Nettoyage, dmonisation, fichier de pid, locate-mac dans les mails.
darcs-hash:20061211233139-68412-42299750ff783941f620ef522cf74fe5ee71c939.gz
This commit is contained in:
parent
867548324b
commit
3c841d99f2
1 changed files with 118 additions and 49 deletions
|
@ -2,88 +2,157 @@
|
||||||
# -*- encoding: iso-8859-15 -*-
|
# -*- encoding: iso-8859-15 -*-
|
||||||
|
|
||||||
# Utilisation de scappy pour détecter un DHCP pirate.
|
# Utilisation de scappy pour détecter un DHCP pirate.
|
||||||
|
# $Id: dhcp-detect.py,v 1.3 2006-12-11 23:31:39 glondu Exp $
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
from threading import Thread
|
||||||
|
from time import time, sleep
|
||||||
|
from syslog import *
|
||||||
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
import smtplib
|
|
||||||
import os
|
|
||||||
sys.path.append("/usr/bin")
|
sys.path.append("/usr/bin")
|
||||||
|
sys.path.append("/usr/scripts/gestion")
|
||||||
|
sys.path.append("/usr/scripts/gestion/tools")
|
||||||
|
|
||||||
|
# Hack pour scapy
|
||||||
|
os.environ["HOME"] = "/tmp"
|
||||||
|
|
||||||
from scapy import Ether, sendp, sniff, BOOTP, IP, UDP
|
from scapy import Ether, sendp, sniff, BOOTP, IP, UDP
|
||||||
|
from email_tools import send_email
|
||||||
|
from locate_mac import trace_machine, info_machine
|
||||||
|
|
||||||
# Adresse MAC de egon
|
PIDFILE = "/var/run/dhcp-detect.pid"
|
||||||
#mac=os.popen(r"ifconfig | grep '^eth0' | awk '{print $(NF)}'").readline().strip()
|
|
||||||
# maintenant c'est crans l'interface
|
# Interface à surveiller
|
||||||
INTERFACE = "crans"
|
INTERFACE = "crans"
|
||||||
|
|
||||||
mac=os.popen(r"ifconfig | grep '^crans' | awk '{print $(NF)}'").readline().strip()
|
# Adresse MAC
|
||||||
|
mac = os.popen(r"ifconfig | grep '^%s' | awk '{print $(NF)}'" % INTERFACE).readline().strip()
|
||||||
|
|
||||||
# Paquet à envoyer pour détecter un DHCP (il a été capturé pour avoir la bonne tête)
|
# Paquet à envoyer pour détecter un DHCP (il a été capturé pour avoir la bonne tête)
|
||||||
tosend = Ether("\xff\xff\xff\xff\xff\xff\x00\x80\xc8\xc9\xab\x01\x08\x00E\x10\x01H\x00\x00\x00\x00@\x11y\x96\x00\x00\x00\x00\xff\xff\xff\xff\x00D\x00C\x014\x9aA\x01\x01\x06\x00\xb2\x87\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xc8\xc9\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01\x012\x04R\xe1'67\x07\x01\x1c\x02\x03\x0f\x06\x0c\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
tosend = Ether("\xff\xff\xff\xff\xff\xff\x00\x80\xc8\xc9\xab\x01\x08\x00E\x10\x01H\x00\x00\x00\x00@\x11y\x96\x00\x00\x00\x00\xff\xff\xff\xff\x00D\x00C\x014\x9aA\x01\x01\x06\x00\xb2\x87\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xc8\xc9\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01\x012\x04R\xe1'67\x07\x01\x1c\x02\x03\x0f\x06\x0c\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||||
|
|
||||||
# On met à jour ce paquet
|
# On met à jour ce paquet
|
||||||
tosend.getlayer(Ether).src = mac
|
tosend.getlayer(Ether).src = mac
|
||||||
tosend.getlayer(IP).chksum = None
|
tosend.getlayer(IP).chksum = None
|
||||||
tosend.getlayer(UDP).chksum = None
|
tosend.getlayer(UDP).chksum = None
|
||||||
tosend.getlayer(BOOTP).chaddr = ''.join(map(lambda x: chr(int(x,16)),mac.split(":")+['0']*10))
|
tosend.getlayer(BOOTP).chaddr = ''.join(map(lambda x: chr(int(x,16)),mac.split(":")+['0']*10))
|
||||||
tosend = Ether(tosend.build())
|
tosend = Ether(tosend.build())
|
||||||
dejavu = {} # Tableau associatif "mac" - "mailé pour la dernière fois"
|
|
||||||
|
|
||||||
print "Le paquet suivant va être envoyé à intervalles réguliers pour tester la présence de DHCP pirates."
|
# Tableau associatif "mac" - "mailé pour la dernière fois"
|
||||||
print tosend.summary()
|
dejavu = {}
|
||||||
|
|
||||||
|
|
||||||
|
def createDaemon():
|
||||||
|
"""Detach a process from the controlling terminal and run it in the
|
||||||
|
background as a daemon.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
pid = os.fork()
|
||||||
|
except OSError, e:
|
||||||
|
raise Exception, "%s [%d]" % (e.strerror, e.errno)
|
||||||
|
if (pid == 0): # The first child.
|
||||||
|
os.setsid()
|
||||||
|
try:
|
||||||
|
pid = os.fork() # Fork a second child.
|
||||||
|
except OSError, e:
|
||||||
|
raise Exception, "%s [%d]" % (e.strerror, e.errno)
|
||||||
|
if (pid == 0): # The second child.
|
||||||
|
os.chdir("/")
|
||||||
|
os.umask(0)
|
||||||
|
else:
|
||||||
|
os._exit(0) # Exit parent (the first child) of the second child.
|
||||||
|
else:
|
||||||
|
os._exit(0) # Exit parent of the first child.
|
||||||
|
|
||||||
|
# Iterate through and close all file descriptors.
|
||||||
|
for fd in range(0, 3):
|
||||||
|
try:
|
||||||
|
os.close(fd)
|
||||||
|
except OSError: # ERROR, fd wasn't open to begin with (ignored)
|
||||||
|
pass
|
||||||
|
os.open("/dev/null", os.O_RDWR) # standard input (0)
|
||||||
|
os.dup2(0, 1) # standard output (1)
|
||||||
|
os.dup2(0, 2) # standard error (2)
|
||||||
|
|
||||||
print
|
|
||||||
|
|
||||||
# Envoi par mail le paquet
|
# Envoi par mail le paquet
|
||||||
def mail(paquet):
|
def mail(paquet):
|
||||||
if (paquet.getlayer(Ether).src in globals()['dejavu'] and (time.time() - globals()['dejavu'][paquet.getlayer(Ether).src]) < 60*60):
|
mac_pirate = paquet.getlayer(Ether).src
|
||||||
|
if (mac_pirate in globals()['dejavu'] and (time() - globals()['dejavu'][mac_pirate]) < 60*60):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
globals()['dejavu'][paquet.getlayer(Ether).src] = time.time()
|
globals()['dejavu'][mac_pirate] = time()
|
||||||
msg = "From: %s\r\nTo: %s\r\nSubject: DHCP pirate\r\n\r\n" % ("Vincent Bernat (dhcp) <bernat@crans.org>", "Disconnect team <disconnect@crans.org>")
|
print "Envoi d'un mail...",
|
||||||
msg = msg + """Un DHCP pirate a été découvert sur le réseau. Voici quelques renseignements mineurs à son sujet :
|
msg = u"""Boujour,
|
||||||
|
|
||||||
Son adresse Ethernet : %s
|
Un DHCP pirate a été découvert sur le réseau. Voici quelques renseignements mineurs à son sujet :
|
||||||
Son adresse IP : %s
|
|
||||||
Son TTL : %d
|
Son adresse Ethernet : %s
|
||||||
|
Son adresse IP : %s
|
||||||
Merci de votre attention et à bientôt.""" % (paquet.getlayer(Ether).src, paquet.getlayer(IP).src, paquet.getlayer(IP).ttl)
|
Son TTL : %d
|
||||||
|
|
||||||
server = smtplib.SMTP('localhost')
|
""" % (mac_pirate, paquet.getlayer(IP).src, paquet.getlayer(IP).ttl)
|
||||||
#server.sendmail('gdetrez@crans.org', ('disconnect@crans.org',), msg)
|
msg += trace_machine(mac_pirate)
|
||||||
server.sendmail('gdetrez@crans.org', msg)
|
msg += u"\n"
|
||||||
server.quit()
|
msg += info_machine(mac_pirate)
|
||||||
|
msg += u"""
|
||||||
# Reception d'une réponse
|
Merci de votre attention et à bientôt.
|
||||||
|
|
||||||
|
--
|
||||||
|
dhcp-detect.py
|
||||||
|
"""
|
||||||
|
send_email(u"DHCP-detect <disconnect@crans.org>",
|
||||||
|
u"Disconnect Team <disconnect@crans.org",
|
||||||
|
u"DHCP pirate",
|
||||||
|
msg)
|
||||||
|
print "ok"
|
||||||
|
|
||||||
|
|
||||||
|
# Réception d'une réponse
|
||||||
def recoit(paquet):
|
def recoit(paquet):
|
||||||
# On affiche
|
# On affiche
|
||||||
print paquet.summary()
|
print "Réception de : ", paquet.summary()
|
||||||
# On verifie que c'est bien ce qu'on attend
|
# On verifie que c'est bien ce qu'on attend
|
||||||
if ((paquet.getlayer(Ether).dst.upper() == globals()['mac']) and (paquet.haslayer(BOOTP)) and (paquet.getlayer(BOOTP).op == 2) and (paquet.getlayer(IP).src != '138.231.136.6') and (paquet.getlayer(IP).src != '138.231.136.3')):
|
if paquet.getlayer(Ether).dst.upper() == globals()['mac'] and paquet.haslayer(BOOTP) and paquet.getlayer(BOOTP).op == 2 and paquet.getlayer(IP).src != '138.231.136.3':
|
||||||
# DHCP pirate ?
|
# DHCP pirate ?
|
||||||
print "DHCP pirate ? (%s)" % paquet.getlayer(Ether).src
|
msg = "DHCP pirate ? (%s)" % paquet.getlayer(Ether).src
|
||||||
|
print msg
|
||||||
|
syslog(msg)
|
||||||
mail(paquet)
|
mail(paquet)
|
||||||
|
|
||||||
|
|
||||||
# Envoi du paquet test
|
# Envoi du paquet test
|
||||||
def send(pere):
|
def send():
|
||||||
while pere.isAlive():
|
while True:
|
||||||
time.sleep(60)
|
sleep(60)
|
||||||
print tosend.summary()
|
print "Envoi de :", tosend.summary()
|
||||||
sendp(tosend)
|
sendp(tosend, verbose=False)
|
||||||
print "Fin des envois"
|
|
||||||
|
|
||||||
# Sniffer
|
# Sniffer
|
||||||
def get(pere):
|
def get():
|
||||||
while pere.isAlive():
|
while True:
|
||||||
|
sleep(1)
|
||||||
# On prend les paquets par 100, sinon, le process grossit beaucoup trop
|
# On prend les paquets par 100, sinon, le process grossit beaucoup trop
|
||||||
a = sniff(iface=INTERFACE , filter="port bootpc and ether dst %s" % globals()['mac'], prn=recoit, count=100)
|
a = sniff(iface=INTERFACE, filter="port bootpc and ether dst %s" % mac, prn=recoit, count=100)
|
||||||
print "Fin du sniff"
|
|
||||||
|
|
||||||
# On va démarrer le thread qui envoie régulièrement le paquet et celui qui sniffe régulièrement la réponse
|
|
||||||
threading.Thread(target=send, name="send", args=(threading.currentThread(),)).start()
|
|
||||||
threading.Thread(target=get, name="get", args=(threading.currentThread(),)).start()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
time.sleep(10)
|
if __name__ == "__main__":
|
||||||
|
# On quitte les éventuelles instances démonisées en cours
|
||||||
|
try:
|
||||||
|
pid = int(file(PIDFILE).read().strip())
|
||||||
|
os.kill(pid, 15)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if "-d" in sys.argv:
|
||||||
|
createDaemon()
|
||||||
|
file(PIDFILE, "w").write("%d\n" % os.getpid())
|
||||||
|
else:
|
||||||
|
print "Le paquet suivant va être envoyé à intervalles réguliers pour tester la présence de DHCP pirates :"
|
||||||
|
print tosend.summary()
|
||||||
|
|
||||||
|
openlog("dhcp-detect", LOG_PID)
|
||||||
|
syslog("Démarrage de dhcp-detect")
|
||||||
|
# On démarre le thread qui envoie régulièrement le paquet...
|
||||||
|
Thread(target=send, name="send").start()
|
||||||
|
# ...et celui qui sniffe régulièrement la réponse
|
||||||
|
Thread(target=get, name="get").start()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue