web渗透测试 第13课:SQL注入

SQL注入是最常见的(web)漏洞之一。所有SQL注入练习,在这里找到,使用MySQL作为后端。当SQL查询中包含SQL注入时,缺少用户控制输入的编码/转义。

 

根据信息在查询中的添加方式,您需要不同的东西来破坏语法。

有三种不同的方法可以在SQL语句中回显信息:

  1. 使用引号:单引号或双引号。
  2. 使用反引号。
  3. 直接注入:将数据直接从数据库服务器发送到攻击者控制的计算机。

 

例如,如果你想使用信息作为一个字符串,你可以这样做:

SELECT * FROM user WHERE name="root";

或者

SELECT * FROM user WHERE name='root';

 

如果你想使用整数信息,你可以这样做:

SELECT * FROM user WHERE id=1;

 

最后,如果你想使用信息作为列名,你需要这样做:

SELECT * FROM user ORDER BY name;

或者

SELECT * FROM user ORDER BY `name`;

 

也可以使用整数作为字符串,但会更慢:

SELECT * FROM user WHERE id ='1';

 

回显信息的方式,甚至使用什么分隔符,将决定使用的检测技术。但是,您没有此信息,您需要尝试猜测它。您需要制定假设并尝试验证它们。这就是为什么花时间浏览liveCD上的例子非常重要的原因。

 

Example 1

在第一个例子中,我们可以看到参数是一个字符串,我们可以在表中看到一行。要理解服务器端代码,我们需要开始探索:

 

如果我们添加额外的字符,如“1234”,使用?name=root1234,表中不会显示任何记录。从这里,我们可以猜测请求在某种匹配中使用我们的值。

 

如果我们在请求中注入空格,则使用?name=root+++(编码后),显示记录。MySQL(默认情况下)在执行比较时将忽略字符串中的尾随空格。

 

如果我们使用双引号,?name=root"则表中不会显示任何记录。

 

如果我们使用注入单引号,?name=root'表格就会消失。我们可能打破了一些......

 

从第一部分开始,我们可以推断出整个必须如下:

SELECT * FROM users WHERE name='[INPUT]';

 

现在,让我们验证这个假设。

 

如果我们是对的,以下注入应该给出相同的结果。

  • ?name=root' and '1'='1:初始查询中的引用将在注入结束时关闭。
  • ?name=root' and '1'='1' #(不要忘记编码#):初始查询中的引用将被注释掉。
  • ?name=root' and 1=1 #(别忘了编码#):在初始查询引用将被注释掉我们不需要'1'='1'
  • ?name=root' #(不要忘记编码#):初始查询中的引用将被注释掉,我们不需要1=1

 

现在这些请求可能不会返回相同的内容:

  • ?name=root' and '1'='0:初始查询中的引用将在注入结束时关闭。页面不应返回任何结果(空表),因为选择标准始终返回false。
  • ?name=root' and '1'='1 #(不要忘记编码#):初始查询中的引用将被注释掉。我们应该与上面的查询具有相同的结果。
  • ?name=root' or '1'='1:初始查询中的引用将在注入结束时关闭。or将选择所有结果,第二部分始终为真。它可能会给出相同的结果,但不太可能,因为该值用作此示例的过滤器(而不是一次只显示一个结果的页面)。
  • ?name=root' or '1'='1' #(不要忘记编码#):初始查询中的引用将被注释掉。我们应该与上面的查询具有相同的结果。

 

通过所有这些测试,我们可以确保我们有一个SQL注入。此培训仅侧重于检测。您可以查看其他PentesterLab高级课程,并了解如何利用此类问题。PentesterLab高级课程后面会讲到的。PentesterLab高级课程也是指web渗透测试平台:Web Pentester II。

 

Example 2

在此示例中,错误消息提供了开发人员创建的保护:ERROR NO SPACE。只要在请求中注入空格,就会显示此错误消息。它阻止我们使用该' and '1'='1方法或任何使用空格字符的指纹识别。但是,使用制表符(HT或\t)可轻松绕过此过滤。您将需要使用编码,以在HTTP请求中使用它。使用此简单绕过,您应该能够看到如何检测此漏洞。制表符空格\t

 

Example 3

在此示例中,开发人员阻止空格和制表符。有一种方法可以绕过这个过滤器。您可以在关键字之间使用注释来构建有效请求,而无需任何空格或制表。可以使用以下SQL注释:/**/。通过使用此注释替换前面示例中的所有空格/列表,您应该能够测试此漏洞。SQL注释

 

Example 4

此示例表示对如何防止SQL注入的典型误解。在前面的3个示例中,使用该功能mysql_real_escape_string可以防止漏洞。在此示例中,开发人员使用相同的逻辑。但是,使用的值是整数,并且不会在单引号之间回显。由于该值直接放在查询中,因此使用mysql_real_escape_string不会阻止任何操作。在这里,您只需要能够添加空格和SQL关键字来打破语法。检测方法与用于基于字符串的SQL注入的方法非常类似。您只需在有效负载的开头不需要引号。例如:?id=2 or 1=1

不用引号注入

 

另一种检测方法是使用整数。最初的要求是?id=2。通过使用值2,我们可以检测到SQL注入:

  • ?id=2 #(#需要编码)应该返回相同的东西。
  • ?id=3-1应该返回相同的东西。数据库将自动执行减法,您将得到相同的结果。
  • ?id=2-0 应该返回相同的东西。
  • ?id=1+1(+需要编码)应该返回相同的东西。数据库将自动执行添加,您将获得相同的结果。
  • ?id=2.0 应该返回相同的东西。

 

并且以下内容不应返回相同的结果:

  • ?id=2+1
  • ?id=3-0

 

Example 5

这个例子与以前的检测方式非常相似。如果查看代码,您将看到开发人员试图通过使用正则表达式来阻止SQL注入:

if (!preg_match('/^[0-9]+/', $_GET["id"])) {
    die("ERROR INTEGER REQUIRED");  
}

但是,使用的正则表达式是不正确的; 它只是确保参数id 开始以数字。先前使用的检测方法可用于检测此漏洞。例如:?id=2 or 1=1

 

Example 6

这个例子是另一种方式。开发人员再次在正则表达式中犯了一个错误:

if (!preg_match('/[0-9]+$/', $_GET["id"])) {
    die("ERROR INTEGER REQUIRED");  
}

此正则表达式仅确保参数以数字id 结尾(由于$符号)。它不能确保参数的开头有效(缺失^)。您可以使用之前学到的方法。

您只需要在有效负载的末尾添加一个整数。这个数字可以是有效载荷的一部分,也可以放在SQL注释之后:?id=1 or 1=1 # 123。(#需要编码)!

 

Example 7

另一个坏正则表达式的例子:

if (!preg_match('/^-?[0-9]+$/m', $_GET["id"])) {
  die("ERROR INTEGER REQUIRED");    
}

在这里我们可以看到字符串的开始(^)和结束($)被正确检查。但是,正则表达式包含修饰符PCRE_MULTILINE/m)。多行修饰符仅验证其中一行仅包含整数,因此以下值有效(由于其中包含新行):

123\nPAYLOAD;

PAYLOAD\n123;

PAYLOAD\n123\nPAYLOAD

在URL中使用时,需要对这些值进行编码,但是通过使用编码和先前看到的技术,您应该能够检测到此漏洞。例如:

http://192.168.40.133/sqli/example7.php?id=2%0A%20or%201=1

 

Example 8

在此示例中,参数名称表示它将在SQL查询中回显的位置。如果查看MySQL文档,有两种方法可以在ORDER BY语句中提供值:

  • 直接:ORDER BY name;
  • 在反引号之间:ORDER BY `name`

 

该ORDER BY声明不能与单引号或双引号内的值一起使用。如果使用它,则不会对任何内容进行排序,因为MySQL将这些视为常量。

 

要检测此类漏洞,我们可以尝试使用不同的有效负载获得相同的结果:

  • name` ##需要编码)应该给出相同的结果。
  • name` ASC #(#需要编码)应该给出相同的结果。
  • name`, `name:初始查询中的反向标记将在注入结束时关闭。

 

以下有效负载应该给出不同的结果:

  • name` DESC ##需要编码)。
  • name` 不应该给出任何结果,因为语法不正确。

 

Example 9

这个例子类似于前一个例子,但不是反向引号```

 

在这种情况下可以使用其他方法,因为我们之前没有反向引号直接注入请求。我们可以使用MySQL IF语句生成更多有效负载:

  • IF(1, name,age) 应该给出相同的结果。
  • IF(0, name,age)应该给出不同的结果。您可以看到列按年龄排序,但sort函数将值比较为字符串,而不是整数(10小于2)。这是一个副作用IF,如果列中的一个包含字符串,则会将值排序为字符串。
    A+
发布日期:2018年07月03日 19:19:23  所属分类:Web Pentester
最后更新时间:2018-10-11 00:54:31
付杰
  • ¥ 129.0元
  • 市场价:199.0元
  • ¥ 398.0元
  • 市场价:498.0元
  • ¥ 798.0元
  • 市场价:1298.0元
  • ¥ 99.0元
  • 市场价:99.0元

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: