SQL注入的危害
SQL注入攻击(SQL Injection),简称注入攻击、SQL注入,被广泛用于非法获取网站控制权,是发生在应用程序的数据库层上的安全漏洞。在设计程序,忽略了对输入字符串中夹带的SQL指令的检查,被数据库误认为是正常的SQL指令而运行,从而使数据库受到攻击,可能导致数据被窃取、更改、删除,以及进一步导致网站被嵌入恶意代码、被植入后门程序等危害。
SQL注入的产生原因
程序开发过程中不注意规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST和GET提交
一些sql语句正常执行
SQL注入的条件
- 可控制用户数据的输入
- 原程序要执行的代码,拼接了用户输入的数据
注入类型
数字型
当输入的参数为整型时,则可认为是数字型注入
如ID、年龄、页码等都可认为是数字型注入,不需要单引号来闭合
实例
新建admin数据库user表,并插入数据
<?php
$id = $_GET['id'];
$conn = mysql_connect('localhost','root','root');
mysql_select_db('admin',$conn);
$sql = "SELECT * FROM USER WHERE id = $id";
$result = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($result)){
echo "ID:".$row['id']."<br>";
echo "USERNAME:".$row['username']."<br>";
echo "PASSWORD:".$row['password']."<br>";
echo "EMAIL:".$row['email']."<br>";
}
mysql_close($conn);
echo "<hr>";
echo $sql;
?>
URL访问and 1=1
正确and 1=2
错误or 1=1
注出全部数据
字符型
实例
<?php
//error_reporting(E_ALL ^ E_NOTICE);
$id = $_GET['id'];
$conn = mysql_connect('localhost','root','root');
mysql_select_db('admin',$conn);
$sql = "SELECT * FROM USER WHERE id = '$id'";
$result = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($result)){
echo "ID:".$row['id']."<br>";
echo "USERNAME:".$row['username']."<br>";
echo "PASSWORD:".$row['password']."<br>";
echo "EMAIL:".$row['email']."<br>";
}
mysql_close($conn);
echo "<hr>";
echo $sql;
?>
在不闭合的情况下,不管是and 1=1
还是and 1=2
都正确'
闭合,and 1=1
正确'
闭合,and 1=2
错误or 1=1 --+
注出全部数据
注入的利用方式
(3)实例(万能密码)
注入过程
- 攻击者访问登录页面
2. 输入用户名及密码
3. 将含有攻击字符串组成SQL语句转发给数据库执行
4. 数据库执行发回应用程序服务器
5. 应用程序将内容返回浏览器,即绕过成功
盲注
在sql注入过程中,sql语句执行的选择后,选择的数据不在页面显示
- 基于布尔SQL盲注
- 基于时间的SQL盲注
- 基于报错的SQL盲注
HTTP头注入
- User-Agent:使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)
- Cookie:网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)
- X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库or某文件[通过修改XXF头可以实现伪造IP])
- Clien-IP:同上,不做过多介绍
- Rerferer:浏览器向 WEB 服务器表明自己是从哪个页面链接过来的
- Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号(这个我本人还没碰到过,不过有真实存在的案例还是写上吧)
宽字节注入
• 字符、字符集与字符序
字符(character)是组成字符集(character set)的基本单位。对字符赋予一个数值(encoding)来确定这个字符在该字符集中的位置。
字符序(collation)指同一字符集内字符间的比较规则。
• UTF8
由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。
• 宽字节
GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。
实例
数字型
字符型
addslashes()
函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
- 单引号(’)
- 双引号(”)
- 反斜杠(\)
- NULL
思路
逃逸单引号的限制
因为%df的关系,\的编码%5c被吃掉了,也就失去了转义的效果,直接被带入到mysql中,然后mysql在解读时无视了%a0%5c形成的新字节,那么单引号便重新发挥了效果
绕过
原理
%df%27===>(addslashes)====>%df%5c%27====>(GBK)====>運’
用户输入===>过滤函数===>代码层的$sql==>mysql处理请求==>mysql中的sql
默认编码character_set_client==>根据character_set_connection转码==>更新数据库时转化成字段所对应的编码
修复方案
(1)使用mysql_set_charset(GBK)指定字符集
(2)使用mysql_real_escape_string进行转义
二次注入
一阶注入:
1. 一阶SQL注入发生在一个HTTP请求和响应中,对系统的攻击是立即执行的
2. 攻击者在http请求中提交非法输入
3. 应用程序处理非法输入,使用非法输入构造SQL语句
4. 在攻击过程中向攻击者返回结果
二阶注入:
1. 攻击者在http请求中提交恶意输入
2. 恶意输入保存在数据库中
3. 攻击者提交第二次http请求
4. 为处理第二次http请求,程序在检索存储在数据库中的恶意输入,构造SQL语句
5. 如果攻击成功,在第二次请求响应中返回结果
原理
注入点因为经过过滤处理无法触发sql注入漏洞,比如addslashes函数,将单引号等字符转义变成\’。但是存进数据库后,数据又被还原,在这种情况下,如果发现一个新的注入同时引用了被插入的数据库数据,就可以实现闭合新发现的注入漏洞引发二次注入
思路
先将注入语句插入到数据库,注册、留言板等功能都具有insert数据库的操作然后在使用update的地方触发插入到数据库的注入语句
实例
新建reg.php文件
写入数据到数据库
新建search.php文件
查询ID正常
往数据库里插入恶意数据
通过搜索读取数据库里的内容
修复方案
- 使用预编译语句
- 使用存储过程
- 检查数据类型
- 使用安全函数