SQL注入原理及代码分析(二)
前言
上一篇文章中,对union注入、报错注入、布尔盲注等进行了分析,接下来这篇文章,会对堆叠注入、宽字节注入、cookie注入等进行分析。第一篇文章地址:SQL注入原理及代码分析(一)
如果想要了解Access的详细手工注入过程,可以看我的这篇文章:https://www.cnblogs.com/lxfweb/p/12643011.html
如果想要了解MySQL的详细手工注入过程,可以看我的这篇文章:https://www.cnblogs.com/lxfweb/p/12655316.html
如果想要了解SQL server的详细手工注入过程,可以看我的这篇文章:https://www.cnblogs.com/lxfweb/p/12675023.html
SQL注入原理
SQL注入漏洞的产生需要满足两个条件
- 参数用户可控:前端传给后端的参数内容是用户可以控制的。
- 参数带入数据库查询:传入的参数拼接到SQL语句并带入数据库查询。
所以在实际环境中开发者要秉持“外部参数皆不可信原则”进行开发。
几种常见的SQL注入攻击
堆叠查询注入
先说一下堆叠查询,堆叠查询可以执行多条语句,多语句之间以分号隔开。堆叠注入就是利用这个特点,在第二条SQL语句中构造自己要执行的句子。
然后看代码
<?php
try {
$conn = new PDO("mysql:host=localhost;dbname=dvwa", "root", "XFAICL1314");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->query("SELECT * FROM users where `user_id`='" . $_GET['id']."'");
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach ($stmt->fetchAll() as $k => $v) {
foreach ($v as $key => $value) {
echo $value;
}
}
$dsn = null;
}
catch (PDOException $e)
{
echo "error";
}
$conn = null;
?>
在堆叠注入页面中,程序获取GET参数id,使用PDO的方式进行数据查询,但是还是将id拼接到SQL语句中,导致POD没起到预编译的效果。程序仍然存在SQL注入。使用PDO执行SQL语句时,可以执行多条语句,但只返回第一条执行的结果。所以第二条语句中可以使用时间盲注等来会获取数据。时间注入上一篇文章分析了。
所以咱们构造的语句为:
';select if(substr(user(),1,1)=0x72,sleep(5),1)%23
我们发现构造的时间注入语句成功执行,之后可以通过这种方法猜解出,库名,表名,字段及内容。
宽字节注入攻击
先说一下宽字节注入原理,如果我们注入的参数为字符型,我们构造自己的SQL语句的时候需要用单引号闭合前面的SQL语句,但是咱们输入的单引号被转义(反斜杠)了,导致参数无法逃逸单引号的包围,一般情况是没有SQL注入的,不过有一个特例,那就是当数据库的编码为GBK时,可能存在宽字节注入,具体操作是先在url后添加%df,在添加单引号,因为反斜杠的编码为%5c,而在GBK编码中,%df%5c是繁体字"綅"。所以单引号逃逸,就可以执行咱们构造的SQL语句了。
然后看代码
<?php
$conn = mysql_connect('localhost','root','XFAICL1314') or die('abd!');
mysql_select_db('dvwa',$conn) OR emMsg("数据库连接失败");
mysql_query("SET NAMES 'gbk'",$conn);
$id = addslashes($_GET['id']);
$sql="select * from users where user_id='$id'limit 0,1";
$result = mysql_query($sql,$conn) or die(mysql_error());
$row = mysql_fetch_array($result);
if($row)
{
echo $row['user'].":".$row['password'];
}
else
{
print_r(mysql_error());
}
?>
</font>
<?php
echo "<br><br>SQL : ".$sql."<br><br>";
?>
在宽字节注入页面中,程序获取GET参数id,并对参数id使用addslashes()转义,然后拼接到SQL语句中,进行查询。现在进行尝试。
构造语句:%df' and 1=1%23
我们发现单引号成功逃逸,之后的过程就是和union注入一样了,猜表,猜字段,获得数据。
cookie注入攻击
先看代码
<?php
$id=$_COOKIE['id'];
$value="1";
setcookie("id",$value);
$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if(mysqli_connect_error())
{
echo "连接失败:". mysqli_connect_error();
}
$result = mysqli_query($con,"select * from users where `user_id`=".$id);
if (!$result){
printf("Error:%s\n",mysqli_error($con));
exit();
}
$row= mysqli_fetch_array($result);
echo $row['user'].":". $row['password'];
echo "<br>";
?>
在cookie注入页面中,程序通过$_COOKIE获取到参数id,并直接将id拼接到select语句中进行查询,如果有结果,将解惑输出到页面。
我们打开页面,发现url中没有GET参数。通过抓包发现参数id在cookie中。
接着构造语句:and 1=2
拼接到cookie中,发现报错了,可以注入,之后也是用union注入的一些语句。
包括用order by 判断字段,接着使用联合查询。得到表名,字段名和数据。
cookie注入还有一种情况,那就是,程序用$_REQUEST[]来接收用户的输入,但是程序的防御程序只是对GET和POST接收的输入做了防御。没考虑cookie,这就导致了cookie注入。和上面的操作方式一样,只需要抓包,将有注入点的参数移到cookie中就可以了。
XFF注入攻击
XFF注入原理是通过修改X-Forwarded-For头对带入系统的dns进行sql注入,从而得到网站的数据库内容。X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP。
这里用墨者学院的XFF注入靶场来做演示。
打开靶场,发现是登陆页面,随便输入账号和密码。发现返回客户机ip,猜测是由XFF控制。
抓包,添加XFF头,改为1.1.1.1,发现也更改,说明存在XFF注入。
接着使用报错注入的方法,用updataxml()等函数将我们需要的数据查询出来,详细查询过程这里就不写了,查询到的账号密码的语句为:
' and updatexml(1,concat(0x7e,(select concat(username,0x7e,password) from user limit 0,1) ,0x7e),1) or '1'='1
小结
两篇文章将常见的几种SQL注入都简单分析了一遍,并构造了相关有缺陷的代码用来加深理解。希望对大家有所帮助。
参考文献:《Web安全攻防》