欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

记一次曲折的Getshell过程

来源:本站整理 作者:三只小潴 时间:2017-08-26 TAG: 我要投稿

最近在挖某框架的漏洞,其中挖到一枚Getshell,挖的过程有点曲折感觉可以写篇文章总结一下,方便与各位大牛交流交流。
因为此框架有大量用户,并且此漏洞并未修复,故此隐去所有有关此框架的信息,连文章中出现的代码都是我自己另写的,重在思路,希望大家理解。
首先通过审计定位到可能导致漏洞的代码(路径:/edit/creat.php):
    $file = $_GP['file'];    $viewFile = './setting/' . $file;    if (!file_exists($viewFile)) {        mkdirs(dirname($viewFile));        file_put_contents($viewFile, ' . $file . ' -->');    }
其中 $GP 是合并 $GET 和 $_POST 的变量。
可以看到写入的文件路径和写入的部分内容都是可控的,看到这里不禁露出了一丝笑容,没想到一枚 getshell 如此轻松。
好吧,先测试一下,把$file的值设置为:
 echo 1111; ?>.php
post 到 /index.php? control=edit&action=creat
(此框架是单入口)

预计生成的文件内容是:
.php -->
好了,那访问一下生成的文件,URL:
http://test.com/edit/setting/%3C%3Fphp%20echo%201111%3B%20%3F%3E.php
右键查看一下源码,发现输出的内容是:
.php -->
居然被过滤了? 回溯之前的代码,在 index.php 文件中发现代码:
    $_GP= array_merge($_GET, $_POST);    $_GP = htmlEncode($_GP);    $control = $_GP['control'];    $action = $_GP['action'];    $controls = array('basic', 'edit');    $actions = array('index', 'creat');    if (in_array($control, $controls) &&in_array($action, $actions)) {        $file ="./$control/$action.php";        include $file;    } else {        echo 'error';    }
关键在开始的两行代码上,htmlEncode ? 搜索这个函数,找到这个函数的代码如下:
function htmlEncode($var) {   if (is_array($var)) {       foreach ($var as $key => $value) {            $var[htmlspecialchars($key)] =htmlEncode($value);       }   } else {       $var = str_replace('&', '&', htmlspecialchars($var,ENT_QUOTES));   }   return $var;}
结合起来,就是对 post 和 get 获取到的所有内容进行htmlspecialchars,所以才会出现上面所看到的尖括号被过滤的情况。
看到这里,脸上的笑容都消失了,哎呀,果然没那么容易。尖括号过滤了,那就没办法写入PHP 代码的解析标签了,想不到什么突破的办法,难道就这样放弃么?开始犯愁…
一直想着:过滤了尖括号怎么办?过滤了尖括号怎么办?过滤了尖括号怎么办……
那我能不能不用尖括号呢?不用尖括号能不能解析?要怎么才能解析?想到这里,突然就想到模板!这个框架的模板和大多数 MVC 的模板一样,使用大括号作为标记:
function view($var) {        /*            这里一系列的处理就不写了            过程就是对模板中出现的伪代码进行处理            这些做过 Web MVC 开发的都知道             而伪代码的格式与常见的格式一样,用大括号把变量括起来,比如:{$var}            当然还有一些 {if $var==xx}、{loop $var as $value} 等等这些             其实这些处理的目的就是生成 PHP 可解析的代码        */        //假设解析后的代码文件存放在一个 tmp 目录里,而目录的路径赋值给了 $viewFile 变量        include $viewFile;}
这样就可以使用模板的标记 {} 来绕过尖括号  的过滤,但是根据这个框架的路由协定,模板不能随便被包含,所以只能覆盖原有的模板。
按照这个思路,找一个有加载模板的功能,覆盖加载的模板,覆盖之后访问了就可以解析了。按照这个思路,找到一个加载了模板的功能,URL是:
/index.php? control=basic&action=index
代码路径在/basic/index.php,代码最后就有调用 view(‘index’);
加载的模板路径在:
/themes/basic/index.html
按照这些信息,应该构造 $file 的值为:
../../themes/basic/index.html
但是这样又有一个问题了,虽然构造这样的值可以覆盖原有的模板文件,但是写入的文件内容就是:
这样的话就没有写入需要的 Webshell 了,怎么办呢?!
根据 URL 的特性,./1.php 和 ./test/../1.php 访问的内容是一样的,都是 1.php 这个文件,但是 test 这个目录名我是可以随便写的,再根据模板伪代码的格式构造一个控制 $file 的测试 POC:
../../{php echo 1111;}/../themes/basic/index.html
(根据 view() 函数的代码,有一个{php }伪代码标签,处理的时候会替换为 。其实就算是没有这标签也可以用其他非组合的标签代替)

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载