12月7日全天:宽字节注入原理解析

网页出现乱码的原因:

客户端与数据库的数据传输处编码、数据库存储处编码,两者编码不同,就会出现乱码。还有一种情况,PHP没有向浏览器发送header头设置,告诉浏览器用用什么编码来展现,导致乱码。

通常,数据库在创建数据表的时候,就已经设置好了数据库存储端的字符编码。可以看到name字段设置的是gbk,而我们注入的时候,脑子中构造的语句都是select xxx from xxx where name="{$user_name}"这样类似的语句。(下面的gbk支持所有常用中文的简体和繁体,utf-8包含所有的字符,至于为何要这么设置,我个人猜测可能是为了保证数据的唯一性吧。有懂数据库的大佬可以在下方留言,因为感觉这方面转换编码挺复杂的)


正常情况下,整个数据的走向大概如下:

请求过程:用户提交数据--->经过中间件--->到达web应用--->web应用再作为客户端,向数据库服务器发送请求--->数据库服务器接受请求,执行web应用发送的sql语句

web应用作为客户端,向数据库服务器发送请求的时候,会以自身php文件默认的编码,来对信息进行编码,接着,再向数据库发送请求,那么这肯定有一个客户端和服务器建立连接的过程,这个建立连接的过程也是统一编码的过程,依靠的mysql的两个内部变量character_set_client和character_set_connection,只有将character_set_client和character_set_connection的变量值(也就是编码方式)都设置成相同的值,那么才不会出现乱码(是在数据库端进行设置)

之后,服务器将处理结果,以客户端能理解的编码方式,再传给客户端(这里的客户端我理解是web应用),按照上面的来看,客户端能理解的就是gbk了,所以,character_set_results就设置成gbk,这就是服务器返回给客户端的按照gbk编码的结果

而通常程序员在php里写的set names utf8也就是上面这三条语句同时执行的效果。同时,我最上面提到,网页的编码也可能造成乱码,那是因为浏览器端的编码和PHP返回结果(或者说是打印结果)的编码不一致导致的。解决方法就是php用header()来告诉浏览器端用什么编码来解码。这样,也就同时解决了浏览器端可能出现的乱码问题。

宽字节注入的问题就是出在这里:

若数据库端设置了character_set_client为gbk,character_set_connection为gbk,那么php代码接受到的$bar为 %df%27 的时候


addslashes()将用户提交上来的url编码的 %df%27 进行解读,发现%27是单引号的意思,所以就加上了转义字符\进行转义,于是就变成了%df%5c%27,这里的%5c就是\的url编码后的形式。问题就在这里形成了,PHP代码中有set names GBK,那就代表character_set_client,character_set_connection,character_set_results的值都是gbk,而php代码执行mysql($sql)的时候,会进行编码转换!

重点:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。在这次编码中,%df%5c被合并成了一个新的字节,而%27则被当做单引号,这样就实现了闭合!


通过查询gdk编码表,可以看到%df%5c就是那个字符(我不认识,好像是运气的运?)这样的话,由于这里的编码变成了新的字符,那么到数据库端执行的语句就成了select xxx from xxx where name='运' and 1=1-- 实现了闭合,也实现了绕过代码层的过滤。

再总结一下:

当一个Mysql连接请求从客户端传来的时候,服务器认为它的编码是character_set_client,然后会根据character_set_connection把请求进行转码,从character_set_client转成character_set_connection,然后更新到数据库的时候,再转化成字段所对应的编码如果使用了set names指令,那么可以修改character_set_connection的值,也同时会修改character_set_client和character_set_results的值,当从数据库查询数据返回结果的时候,将字段从默认的编码转成character_set_results

另外,据我查阅相关资料,得知网站的正常开发都是:

将一些用户提交的GBK字符使用iconv函数(或者mb_convert_encoding)先转为UTF-8,然后再拼接入SQL语句

像这种情况,我搜集资料的时候,看到有人博客上是这么写的

实际上,我想说,不加那个\不是也是同样的效果吗?还是说GBK转成URF8加个\是为了凑字符?不管了,这里就先记着吧。如果我的想法实施的时候错误了,那就再加个\去尝试。

最后,网站如何才能防止这种宽字符注入攻击呢?

(1)使用mysql_set_charset(GBK)指定字符集

(2)使用mysql_real_escape_string进行转义

原理是,mysql_real_escape_string与addslashes的不同之处在于其会考虑当前设置的字符集,不会出现前面e5和5c拼接为一个宽字节的问题,但是这个“当前字符集”如何确定呢?

就是使用mysql_set_charset进行指定。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容