当前位置: 首页 > news >正文

sql注入之宽字节注入

宽字节注入

宽字节案例引入       

        宽字节注入准确来说不是注入手法,而是另外一种比较特殊的情况。为了说明宽字节注入问题,我们以SQLi-labs 32 关为例子。 使用?id=1' 进行测试的时候,发现提交的单引号会被转义[\']。此时,转义后的单引号会被作为普通字符带入数据库查询。也就是说,我们提交的单引号不会影响到原来SQL 语句的结构

addslashes 是 PHP 中的一个内置函数,用于在字符串的某些字符前面添加反斜线 \,以确保这些字符在 SQL 查询或其他需要转义的场景中被正确处理。这有助于防止注入攻击,尤其是在构建动态 SQL 语句时。

函数定义:

string addslashes(string $str)
参数:
  • $str:需要添加反斜线的字符串。

返回值:

返回一个新的字符串,其中的反斜线字符 \、单引号 '、双引号 " 和 NULL 字符 \0 都被加上了反斜线。

示例用法:

$str = "It's a beautiful day.";$safeStr = addslashes($str);// $safeStr 现在等于 "It\'s a beautiful day."
在上面的例子中,单引号'被转义,这样当这个字符串被插入到 SQL 查询中时,不会导致任何问题。

注意:

  • addslashes 主要用于单引号 ' 包围的字符串。如果你的字符串使用双引号 ",应该使用 addcslashes($str, "\\\\") 来转义反斜线。
  • 在 PHP 7.3.0 之后,推荐使用更为安全的 quotemeta 函数,因为它会自动为所有可能的正则表达式元字符添加转义,而不仅仅是几个特定的字符。

安全性:

虽然 addslashes 可以防止某些类型的注入,但最佳实践是使用参数化查询(prepared statements)来避免 SQL 注入攻击,因为它们可以自动处理特殊字符的转义,并且不依赖于手动转义。

  仔细看该函数,其利用正则匹配将 [ /,'," ]这些三个符号都过滤掉了

关于preg_replace的正则用法可详看——> 命令与执行漏洞 中搜索preg_replace

而我们要绕过这个转义处理,使单引号发挥作用不再被转义,有两个思路:

    让斜杠(\)失去作用
    让斜杠(\)消失

第一个思路就是借鉴程序员的防范思路,对斜杠(\)转义,使其失去转义单引号的作用,成为普通的内容。第二个思路就是宽字节注入。

关于编码

在理解宽字节注入之前,我们需要先了解编码的有关知识,关于什么是编码,为什么要编码,可以详看 ——> 计算机中的编码问题

    某字符的大小为一个字节时,称其字符为窄字节.
    当某字符的大小为两个字节时,称其字符为宽字节.
    所有英文默认占一个字节,汉字占两个字节
    常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

宽字节注入       

宽字节是指多个字节宽度的编码,GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。转义函数在对这些编码进行转义时会将转义字符 ‘\’ 转为 %5c ,于是我们在他前面输入一个单字符编码与它组成一个新的多字符编码,使得原本的转义字符没有发生作用。

        由于在数据库查询前使用了GBK多字节编码,即在汉字编码范围内使用两个字节会被编码为一个汉字(前一个ascii码要大于128,才到汉字的范围)。然后mysql服务器会对查询语句进行GBK编码,即下面所说的

       我们在前面加上 %df'  ,转义函数会将%df’改成%df\’ , 而\ 就是%5c ,即最后变成了%df%5c',而%df%5c在GBK中这两个字节对应着一个汉字 “運” ,就是说 \ 已经失去了作用,%df ' ,被认为運' ,成功消除了转义函数的影响。

  • '           %27
  • \           %5c
  • %df\'    %df%5c' =》  運'

我们输入 ?id=1%df',按道理来说将转义符吃掉了,结果应该是 id=' 運'  ' ,为什么这里转变成了中文后后面还有一个反斜杠了?那个反斜杠是哪里来的?

  其实这个是浏览器显示编码的问题,我们将浏览器编码切换为GB2312即简体中文,如下就正常了。

 联合注入如下

 

GB2312与GBK的不同

gb2312和gbk应该都是宽字节家族的一员。但我们来做个小实验。把源码中set names修改成gb2312

结果就不能注入了,我开始不信,然后再把数据库编码也改成gb2312,也是不成功的。虽然执行的语句还是显示被转换成了中文了,但就是注入不成功

 

为什么,这归结于gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而\是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码,所以自然也是不会被吃掉的。

所以,把这个思路扩展到世界上所有多字节编码,我们可以这样认为:只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。

宽字节注入注入方法

1. 黑盒

就是上面所述的,在注入点后面加%df,然后按照正常的注入流程开始注入即可。如果我们需要使用sqlmap进行检测注入的话也需要在注入点后面加%df然后再用sqlmap跑,否则是注入不出来的,如

sqlmap.py -u "http://localhost/sqli-labs-master/Less-32/?id=1%df%27"

2. 白盒

查看mysql是否为GBK编码,且是否使用preg_replace()把单引号转换成\'或自带函数addslashes()进行转义

 

 

如果存在上面说的,则存在宽字节注入

宽字节注入修复

1. mysql_real_escape_string

听说这个函数能抵御宽字节注入攻击。mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集。mysql_real_escape_string与addslashes的不同之处在于其会考虑当前设置的字符集。

 ‍于是,把addslashes替换成mysql_real_escape_string,来抵御宽字符注入。但是我们发现还是一样注入成功了

 

为什么,明明我用了mysql_real_escape_string,但却仍然不能抵御宽字符注入?

原因就是,你没有指定php连接mysql的字符集。我们需要在执行sql语句之前调用一下mysql_set_charset函数,设置当前连接的字符集为gbk。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

mysqli_set_charset(connection,charset);

参数描述
connection必需。规定要使用的 MySQL 连接。
charset必需。规定默认字符集。

 这样就防止了注入

即先调用mysql_set_charset函数设置连接所使用的字符集为gbk,再调用mysql_real_escape_string来过滤用户输入。

2. 设置参数,character_set_client=binary

3. 使用utf-8编码

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • WEB攻防-通用漏洞SQL注入-ACCESS一般注入与偏移注入
  • 【Scrapy】深入了解 Scrapy 中间件中的 process_spider_output 方法
  • Android 注解的语法原理和使用方法
  • 软设之代理模式
  • 【国内超大型智能算力中心建设白皮书 2024】_智算中心算力规划
  • lodop使用教程---ivx
  • docker 基础命令
  • 免费听书TV版v1.0.1
  • 31. 1049. 最后一块石头的重量 II, 494.目标和,474.一和零
  • 问题清除指南|Dell OptiPlex 7070 升级 win11 开启 TPM 2.0 教程
  • c#的几种通信
  • MybatisPlus 一些技巧
  • 透明加密软件哪个好?这5款好用的加密软件尽在你眼前!
  • InspireFace-商用级的跨平台开源人脸分析SDK
  • Spring框架:核心概念与Spring Boot微服务开发指南
  • 【笔记】你不知道的JS读书笔记——Promise
  • 2017-09-12 前端日报
  • download使用浅析
  • ESLint简单操作
  • Java Agent 学习笔记
  • JS 面试题总结
  • log4j2输出到kafka
  • Node + FFmpeg 实现Canvas动画导出视频
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Python 基础起步 (十) 什么叫函数?
  • session共享问题解决方案
  • unity如何实现一个固定宽度的orthagraphic相机
  • Vue学习第二天
  • win10下安装mysql5.7
  • 排序(1):冒泡排序
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端_面试
  • #162 (Div. 2)
  • #Linux(make工具和makefile文件以及makefile语法)
  • #QT(一种朴素的计算器实现方法)
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (160)时序收敛--->(10)时序收敛十
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (C语言)球球大作战
  • (八十八)VFL语言初步 - 实现布局
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (一)VirtualBox安装增强功能
  • (转)Google的Objective-C编码规范
  • (自用)gtest单元测试
  • .NET文档生成工具ADB使用图文教程
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @property括号内属性讲解
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [ Linux ] Linux信号概述 信号的产生
  • [20171101]rman to destination.txt
  • [2023-年度总结]凡是过往,皆为序章
  • [AIGC] 使用Curl进行网络请求的常见用法
  • [autojs]逍遥模拟器和vscode对接
  • [C/C++] C/C++中数字与字符串之间的转换