$ cat writeup.md…
$ cat writeup.md…
gpnctf
Task: PHP 7.4 app with md5_file() on user-controlled path, User class with __destruct() calling system('rm ' . avatar_path). Solution: plant a malicious PHAR via stateful HTTP server (404→200 toggle), trigger phar:// deserialization through md5_file() to get RCE via __destruct gadget.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
PHP7 was soo cooked...
A PHP 7.4 web application takes a path GET parameter and calls md5_file() on it. A User class with a dangerous __destruct() method provides a command injection gadget. The goal is to achieve RCE and read the flag from the server.
<?php class User { public $avatar_path; public $name; public $password; function __construct($name, $password) { $this->name = $name; $this->password = $password; $this->avatar_path = "avatars/".$name.".png"; 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)); $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 Deserialization (PHP 7.x): The challenge title "Pharry" is a pun on PHAR. In PHP 7.x, md5_file() (and other file functions like file_exists, fopen, etc.) automatically deserialize PHAR metadata when called with the phar:// stream wrapper. This behavior was hardened/removed in PHP 8.0+. The flavor text "PHP7 was soo cooked" confirms the target runs PHP 7.
Command Injection Gadget: User::__destruct() calls system("rm ".$this->avatar_path). By crafting a User object with avatar_path = "x; <malicious_command> #", we get arbitrary command execution when the object is garbage-collected after deserialization.
File Plant Primitive: The FALSE branch writes remote content to /tmp/remote_file.jpg via file_get_contents(). This allows planting a malicious PHAR file on the server's filesystem at a known path.
Red Herrings: The $res == 0xdeadbeef comparison (PHP type juggling with loose ==) and the flag.txt containing ASCII art are both decoys. The real flag is at /flag on the server.
...
$ grep --similar