DVWA 靶场 – Sql Injection

blog 355
DVWA 靶场 - Sql Injection

0x01 等级:Low


<?php

// 判断表单是否提交
if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // 获取用户表单输入的id值
    $id = $_REQUEST[ 'id' ];

    // 根据用户传入的id值构造sql语句
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
   /* 
      执行上面的sql语句。
      mysqli_query() 执行某个针对数据库的查询语句。 参数1: 要使用的数据库连接,参数2:执行的语句
      die() 输出一条信息,并退出脚本执行
      
      以下语句解析:如果用户键入的id值查询为空则返回的结果转为布尔值则为false,下面语句使用or进行连接,or逻辑运算符有一个短路,就是如果or前面的语句为true,则不再执行后面的数据。也就是说,如果前面的语句查询结果不为空,则不再执行后面的语句。反之执行后面的语句。
    */
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
 
    // 获取sql查询中的结果  mysqli_fetch_assoc()将查询结果作为一个关联数组
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // 获取$row变量中的键值
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // 对最终用户的反馈
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    // 关闭这个sql连接
    mysqli_close($GLOBALS["___mysqli_ston"]);
}

?>

通过审计代码发现,我们可以传入id值,并且传入的id值并没有经过任何过滤。这就可能存在sql注入漏洞。

前端界面是通过from表单以GET请求接受我们传入的参数。执行之后会输出对应id的用户

DVWA 靶场 - Sql Injection

其实这里存在一个union联合查询语句注入

0x01.2 判断注入点类型

我们传入id=2a,发现和id=2的查询结果一致。可以判断这里是一个字符型的注入点,如果是整型(数字型)的注入点,我们传入id=2a的时候要么是查询结果为空,要么直接报错

DVWA 靶场 - Sql Injection
we

那么为什么我们传入id=2a的结果和id=2的结果一致呢?其实PHP有一个弱类型转换。它会将2a转换为整数类型就是2,因此和id=2的结果一致

看示例:

DVWA 靶场 - Sql Injection

= 为PHP的赋值符号,表示将=右边的值赋值给=左边的变量,PHP中以$开头表示是一个变量

== 在进行比较的时候,会先将值的类型转换为相同,再比较

=== 在进行比较的时候,会先判断两种值的类型是否相等,再比较,如果数据类型不相同,则直接返回false

可以看到字符串类型的'123a'与数字类型的123作==比较,他们的值是相等的,因为'123a'转为数字类型则为123。

因为在做类型转换的时候,字符串必须以数字开头才会被转换为数字类型。因此$b的结果为false,数字类型的123'a123'做==运算是不相同的。

$c的结果之所以为false,是因为数字类型的123字符串类型的'123'在做全等于(===)运算的时候,它不会将两者的数据类型,转为同一数据类型,而且它也会比较数据类型,如果数据类型不相同,则直接返回false

但是这个类型转换,不再PHP中转换,而是在我们sql语句执行的时候。会发生类型转换,其原理和PHP类型转换一致。

因此我们传入的id=1a值会被转换为id=1,这也是两者查询结果一致的原因。

DVWA 靶场 - Sql Injection

0x01.3 判断列的列数

由于是字符型注入,所以我们需要闭合后端语句中的单引号

猜测我们后端是这么写的(即是有源码,我还是要猜测一下嘻嘻嘻嘻嘻)

select Firstname,Surname from users where id = $_GET['id']

假设我们传入的id值为id=1,那么我们的sql查询语句就为

select Firstname,Surname from users where id = '1'

在sql语句中实际上是这样查询的。

DVWA 靶场 - Sql Injection

我们传入' order by 4 # 之后点击submit提交

DVWA 靶场 - Sql Injection

之后会跳转到新页面提示未知的列。

DVWA 靶场 - Sql Injection

ORDER BY 语句用于对结果集进行排序

order by 4 表示根据第4列进行排序。但是我们的slq查询中没有第4列,因此会报未知的第4列错误

以下在mysql中执行:

DVWA 靶场 - Sql Injection

我们可以发现,当前选中了两个列即first_namelast_name列,当我们order by 2 的时候,回显是正常的,因为他们第2列,第2列就是last_name

但是执行order by 3 的时候,列是没有第三列的。因此会报一个未知的列3。

我们可以使用order by 语句,可以判断列的列数。

为了方便,我们直接在url中注入,不再使用表单提交注入。

http://172.16.1.2/dvwa/vulnerabilities/sqli/?id=2' order by 3 --+  &Submit=Submit#     未知的列

http://172.16.1.2/dvwa/vulnerabilities/sqli/?id=2' order by 2 --+  &Submit=Submit#     回显正常

其中的#表示注释,在sql语句中的注释有:
#
-- 
/* 要注释的内容 */
注意:-- 后面是有一个空格的。

由上可以得知,sql查询中使用了两列。

0x01.4 union 语句

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

UNION语法:

 SELECT column_name1 FROM table_name1 UNION SELECT column_name2 FROM table_name2  

注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。

UNION ALL 语法:

SELECT column_name1 FROM table_name1  UNION ALL SELECT column_name2 FROM table_name2

UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名

DVWA 靶场 - Sql Injection

注意:UNION联合查询语句,需要UNION语句前的SELECT语句的列数和UNION后的SELECT的列数要一致

所以这也是我们上步猜解列数的原因。

DVWA 靶场 - Sql Injection

可以看到,UNION前的SELECT所选择的列为3列,分别为comment_idcommentname,而后者SELECT则选择的为2列,分别是user_idfirst_name。因此会报选择的列数不同错误。

0x01.4 union 获取数据

http://172.16.1.2/dvwa/vulnerabilities/sqli/?id=2' union select 1,2  --+  &Submit=Submit#

# 其中的+在url编码中表示空格,为了更直观我们使用--+ 当然--空格也是可以的
DVWA 靶场 - Sql Injection

可以发现,页面存在返回了1和2 ,说明存在union联合查询注入。

union语句有个特性:如果SELECT指定的列名为数字且不存在,则会将列名作为结果输出到页面。如果SELECT指定的列都不存在,则会以第一个SELECT指定的列名作为列名,其值为指定的列名

看示例:

DVWA 靶场 - Sql Injection

如果SELECT指定的列名为数字且不存在,则会将列明作为值输出。

DVWA 靶场 - Sql Injection

如果UNION前后的SELECT指定的列不为数字,则直接报未知的列错误

DVWA 靶场 - Sql Injection

我们将

http://172.16.1.2/dvwa/vulnerabilities/sqli/?id=-2' union select version(),user()  -- &Submit=Submit#
DVWA 靶场 - Sql Injection

分享