admin

SQL注入——Mysql宽字节注入
SQL注入——Mysql宽字节注入原理Mysql 在使用GBK编码时,会认为两个字符为一个汉字。宽字节注入就是发生...
扫描右侧二维码阅读全文
30
2018/08

SQL注入——Mysql宽字节注入

SQL注入——Mysql宽字节注入

原理

Mysql 在使用GBK编码时,会认为两个字符为一个汉字。宽字节注入就是发生在PHP向Mysql请求时字符集使用了GBK编码

利用场景:addslashes()转义的sql注入

涉及到的几个概念

URL编码:一个字符ascii码的十六进制,再在前面加上%,如""的ASCII码为是92,92的十六进制是5c,所以“”的url编码就是%5c。

GBK编码:在GB2312-80标准基础上的内码扩展规范,使用了双字节编码方案,其编码范围从8140至FEFE(剔除xx7F)

UTF-8:由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。一个utf-8编码的汉字占三个字节

addslashes():
函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号(')
  • 双引号(")
  • 反斜杠()
  • NULL

Mysql宽字节注入

实验环境:

<?php
$dbhost = '127.0.0.1';
$dbuser = 'root';
$dbpasswd = 'root';
$dbname = 'test';
header("Content-type:text/html;charset=gbk");
$mysqli = new mysqli($dbhost,$dbuser,$dbpasswd,$dbname);
if($mysqli->connect_error){
    die("Connect error:".$mysqli->connect_errorno.$mysqli->connect_error);
} 

$id = isset($_GET['id'])?addslashes($_GET['id']):1;

$mysqli->set_charset("gbk");

$sql = "select * from users where id = '$id'";

$result = $mysqli->query($sql)or die($mysqli->error);

while ($row = mysqli_fetch_assoc($result)){

    echo "<h2 style='color:red'>执行的sql语句为:<b>$sql</b></h2><p>结果id:<b>{$row['id']}</b>---user:<b>{$row['name']}</b></p>";
}
?>

通过代码可以看到如果要进行sql注入的话需要闭合'但是获得的id会进行addslashes函数的转义,如果我们直接使用'拼接的话会被转义为\'
blog-180830-G2egjG4ILe

绕过addslashes的转义:

  1. 想办法给\前面再加一个\(或单数个即可),变成\\’,这样\被转义了,逃出了限制
  2. 去掉转义符\

前面提到mysql在使用GBK编码会认为两个字符为一个汉字,只要前一个字符的ascii码>128就是汉字的编码范围
129的十六进制为81,我们输入%81'试一下
blog-180830-j7mgb4Bh2

这里发现sql语句出现错误而且单引号没有被转义,我们就可以利用这个特性饶过addslashes的转义

那么是如何去掉 \ 转义符的呢?
首先1%81'经过addslashes处理后——>1%81%5c%27就是1%81\' 接下来转入mysql处理时用了gbk编码认为2个字符为一个汉字 所以%81%5c%27被处理为-->1乗'转义符\ 被吃掉引发了宽字节注入

注入一下试试:1%81' or 1=1 #
blog-180830-2005l333

防御方案

  1. 使用mysql_real_escape_string() (ps:在执行sql注入之前必须使用mysql_set_charset指定php连接mysql的字符集,单独调用mysql_real_escape_string是无法防御的)
  2. 将character_set_client设置为binary
<?php
$dbhost = '127.0.0.1';
$dbuser = 'root';
$dbpasswd = 'root';
$dbname = 'test';
header("Content-type:text/html;charset=gbk");
$mysqli = new mysqli($dbhost,$dbuser,$dbpasswd,$dbname);

if($mysqli->connect_error){
    die("Connect error:".$mysqli->connect_errorno.$mysqli->connect_error);
} 
$mysqli->query("SET NAMES 'gbk'");
$mysqli->query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary");
$id = isset($_GET['id'])?addslashes($_GET['id']):1;
$sql = "select * from users where id = '{$id}'";

$result = $mysqli->query($sql)or die($mysqli->error);

while ($row = mysqli_fetch_assoc($result)){

    echo "<h2 style='color:red'>执行的sql语句为:<b>$sql</b></h2><p>结果id:<b>{$row['id']}</b>---user:<b>{$row['name']}</b></p>";
}
?>

blog-180830-0C5GKk96Kb

Last modification:January 26th, 2019 at 05:45 pm
If you think my article is useful to you, please feel free to appreciate

One comment

  1. fuck86

    支持下

Leave a Comment