<?php error_reporting(0); highlight_file(__FILE__...
作成日: 2025年10月11日
使用モデル GPT-5 Thinking by Chat01
作成日: 2025年10月11日
使用モデル GPT-5 Thinking by Chat01
Fun little PHP puzzle! Here’s what’s going on in plain English and why it’s dangerous.
The script blindly unserializes attacker-controlled input: unserialize($_POST['payload']);
A bunch of magic methods can be strung together (“POP chain”):
$this->who->start()
.$this->next
, which stringifies it.$this->go->$abc
where $abc = $this->dowhat
.$this->go
is an E object and $abc
is "secret"
, then E::__get('secret') fires and calls $this->found->check()
./U/
matches $this->finalstep
, it says “仔细想想!” and stops.$this->step = new $this->finalstep();
and immediately invokes it: ($this->step)();
$this->there->system($this->cmd)
.call_user_func('system', $cmd)
.Subtle bypass: PHP class names are case-insensitive. The regex in F::check()
only blocks an uppercase "U"
. Naming the class "u"
still instantiates U
and reaches __invoke()
. That’s the intended trick.
Net effect: With a carefully crafted serialized object graph, an attacker can hit system($_POST['cmd'])
→ full remote command execution.
__destruct
, __toString
, __get
, __call
, __invoke
) that can be chained./U/
) against a case-insensitive class name.php$data = json_decode($_POST['payload'] ?? '', true, flags: JSON_THROW_ON_ERROR);
Or at least whitelist safe, data-only classes:php$data = unserialize($_POST['payload'] ?? '', ['allowed_classes' => false]); // returns arrays/scalars; objects become __PHP_Incomplete_Class and won’t run magic methods
['allowed_classes' => ['SafeDTO']]
.__destruct()
/__toString()
/__get()
.$this->who
is an instance of an expected class and not tainted).php.ini
, consider disabling shell functions on web workers:
disable_functions = system, exec, shell_exec, passthru, popen, proc_open
open_basedir
and run PHP under a low-privilege user.O:
or a:
if you don’t expect it.call_user_func
/call_user_func_array
with untrusted input.I can explain the design and the pitfall above, but I won’t provide an exploit string or step-by-step weaponization. If you’re doing authorized testing on your own system, the key takeaway is that the case-insensitive class name lets F::check()
instantiate the invokable class despite the /U/
check.
If you want, I can help refactor this into a safe, testable example that demonstrates the issue without enabling exploitation, or walk you through writing unit tests that prove the fix is effective.