WordPress 4.5.1 XSS

文章目录

Source Code Preparation

一般来说, 开源CMS所使用的Flash文件也都来自其他的开源项目, 所以直接获取WordPress所使用的SWF文件的actionscript源码并不是一件困难的事情. 以本次漏洞的目标文件wp-includes/js/mediaelement/flashmediaelement.swf为例, 通过查看Github上与这个文件相关的最新的commit, 可以发现flashmediaelement.swf来自于一个开源项目MediaElement, 版本号为2.18.1. 恰好, 这个开源项目也托管在Github上, 那么直接下载它对应版本的Release. 同时, 在对MediaElement的源码目录初步研究后发现, 该项目也引用了另外一个开源项目flashls的swc文件, 还贴心低注释了版本号为4.3.4, 该swc文件对应版本的源码同样也可以在Github上找到Release. 这样的好处一是可以避免反编译过程中本地变量名混淆/代码块失踪的尴尬, 二是可以通过手动添加debug信息再本机编译, 更快地消化代码分支结构及数据流.

Vulnerable Output

首先来看存在漏洞的输出, 99%的Flash XSS都是由于ExternalInterface.call函数的参数注入导致的, 当然本次也不例外. 拿到源码之后, 第一件事就是看看源码中出现了几次调用ExternalInterface.call, 对应的参数是否都是可控的. 在排除了几个参数不可控或者已经做了对应防注入的调用, 唯一剩下的就是下面的代码.

只要攻击者能够控制传入Log类下5个静态方法的参数, 就可以触发XSS. 在默认的HLSSettings里面(同时也是WordPress里flashmediaelement.swf的设置), 只有logInfo/logError/logWarn这三个属性被设置为true, 所以我们着重跟踪Log.info/Log.warn/Log.error这三个方法.

通过跟踪代码发现, HLS类中的dispatchEvent方法调用了Log.error这个方法, 传入的参数是HLSEvent类的error属性.

继续查看HLSEvent类中error属性的定义

继续看HLSError的定义

toString的方法会将HLSError类中的_code/_url/_msg三个属性输出, 这三个参数均是通过构造函数从外部传入, 并通过变量名来推测, 很有可能是攻击者可控的.

我们再缕一遍XSS攻击中可能的数据流.
攻击者控制的部分参数传入HLSError的构造函数的url/msg参数, 生成一个恶意的HLSError对象a, 这个恶意对象a又作为parameter参数传入了HLSEvent的构造函数, 生成一个恶意的HLSEvent对象b, 最后, 恶意对象b作为event参数被传入dispatchEvent函数, 进入Log.error时被隐式转换为字符串类型, 触发了toString方法, 对应的返回值传入了ExternalInterface.call函数, 导致XSS.

Evil Input

再回过头来看看输入端. flashmediaelement.swf对外部的输入有两层防御. 第一层, 它会检查所有的参数是否包含恶意字符, 如果包含, 则直接返回终止执行; 第二层, 它会检查外部传入的参数是否是在URL中的QueryString出现过, 如果是, 则删除该部分, 避免直接通过URL传参.

对于第二层防止直接从URL传参的防御, 可以利用Flash Player对URL参数的解析和flashmediaelement.swf代码中对URL参数的解析的差异进行绕过. Flash Player会丢弃URL里%后非16进制的字符, 所以a.swf?a%s=b对于Flash Player来说是给a赋值b, 但对于flashmediaelement.swf中的代码逻辑而言, 是给a%s赋值b, 这样就可以利用两者的不一致性绕过这一检测. 但对于第一层的检测, 目前没有更好的办法进行绕过, 只能查看flashmediaelement.swf是否会通过读取传入的URL中的内容, 给目标参数赋值, 如果可以的话, 那么我们就可以通过污染URL的内容, 而不是URL本身, 执行参数注入, 达到绕过第一层检测的目的.

通过上述的分析, 查找所有调用dispatchEvent函数的地方, 分析其传入的参数, 发现如下:

上述代码是加载fragment时的一个处理错误的handler, 当加载的fragment为一外域的资源, 且该域的crossdomain.xml不允许swf所在域与其通信时, 会抛出一个hlsError的实例, 其中的参数就包含试图加载的fragment的url. 通过查询M3U8的文件格式, 我们可以通过文件内容指定加载的fragment的URL.

exp.m3u8

PoC:

原文链接:,转发请注明来源!

发表评论

要发表评论,您必须先登录