前言
pdf是portable document format的缩写,是目前广泛应用于各种场合的文件格式,其是由Adobe公司根据Postscript语言修改后提出的文件标准,并且被ISO组织接受,目前已经发展到2.0版本(ISO32000-2)。
目前广泛使用的是1.7版本,该版本pdf功能已经相当丰富,可以显示3D模型,播放多媒体音视频,执行Javascript脚本等功能。
PDF中的JavaScript利用
Pdf文件是应用广泛的一种文件格式,很多针对Adobe阅读器的CVE漏洞都是通过pdf文件中的某些结构触发,触发过程都需要执行事先嵌入在pdf文件中的Javascript脚本。例如CVE--11254 Adobe Acrobat 和Reader中addAnnot Use After Free漏洞,就是通过调用Javascript代码调用addAnnot函数从而触发漏洞;以及CVE--4901 针对pdf中Trailer结构里的ID字段的溢出漏洞,也是需要在文件中通过Javascript调用docID来进行触发。
通过研究发现,目前针对该攻击面的攻击主要分为以下三种方式:
通过Javascript调用pdf中的模块进行攻击;
通过Javascript调用阅读器中提供的Javascript相关功能,进行攻击;
其他未知形式的攻击。
PDF中的JavaScript规范
在PDF中插入JavaScript的相关介绍信息可以在Javascript_api_reference.pdf中看到文档下载
文档开头函数介绍时,使用四元数组进行函数介绍,如图:
我们来看看这四元数组各自所代表的含义:
第一列指的是该方法的启用版本以及是否还在使用
第二列指的是该方法引起的变化是否会影响文件
第三列指的是该方法执行需要特殊设置
第四列指的是该方法的可用性
PDF中的JavaScript影响范围
Pdf中的Javascript按照影响范围分为以下几种:文件夹级脚本、文档级脚本、页面级脚本、域级脚本以及批处理级脚本。所有类型的脚本都是事件驱动的,即当发生相应事件时,才会响应执行。
文件夹级脚本
可以影响Acrobat的变量声明和函数定义。一般用于增加菜单或者菜单项等针对Acrobat有影响的函数,包括两种:app和user。此类脚本一般是放到相应文件夹中,一般在Acrobat启动时载入,一般与event实体的应用初始化事件联系。
文档级脚本
可以影响给定文件的变量声明和函数定义,在文件之外不能应用。可以通过Acrobat创建该级别脚本嵌入pdf文件中。除该类型脚本外,还有文档级动作脚本,其触发动作包括:文件关闭前,文件保存前,文件保存后,文件打印前和文件打印后。
页面级脚本
该类型脚本在一页打开或关闭时执行。打开事件为当一个页面完成绘制或任何时候查看一个新页的时候。关闭事件为当用户查看的页面不再是当前页时。
域级脚本
域级脚本与Acrobat中的表格域绑定,当用户与相应区域直接或间接交互时,即触发相应的域事件,该级别脚步存放在pdf文件中。
PDF中的可利用函数
在pdf阅读器支持的所有Javascript函数中以下函数在实际应用中,还是可以对用户的使用造成一些困扰:
app.launchURL()、app.media.getURLdata()、app.alert()、app.execDialog()、doc.getURL。
App.launchURL()
该函数在PDF中指定远程链接地址,用于加载远程文件。
该函数的四元组如下;
该函数包含两个参数,为cURL(用于指定文件的路径)和bNewFrame(用于指定是否用新建页面显示文件)。
当打开包含该函数的pdf文件时,首先会弹出窗口提醒用户建立远程链接,随后使用默认浏览器打开一个远程连接。
使用示例:
example 1:
app.launchURL("/", true);
example 2:
app.addMenuItem({
cName: "myHelp", cUser: "Online myHelp",
cParent: "Help",
cExec: "app.launchURL('/myhelp.html');",
nPos: 0
});
App.media.getURLdata()
该函数功能指定需要打开的多媒体文件。
该函数的四元组如下;
该函数包含两个参数,cURL(用于指定文件的路径)和cMimeType(可选,用于指定文件MIME类型)。
使用示例:
var myURLClip = "/myClip.mpg";
var args = {
URL: myURLClip,
mimeType: "video/x-mpg",
doc: this,
settings: {
players: app.media.getPlayers("video/x-mpg"),
windowType: app.media.windowType.floating,
data: app.media.getURLData(myURLClip,"video/x-mpg"),
floating: { height: 400, width: 600 }
}
}
app.media.openPlayer(args)
当打开包含该函数的pdf文件时,首先会弹出窗口提醒用户建立远程链接,随后根据版本和应用不同可能会有安全提示,随后需要用户手动选择信任,最终使用系统默认的播放器播放URL指定的文件。
app.alert()
该函数可以弹出一个警示对话框。PDF_XSS主要是alert()函数来执行的.
该函数四元组如下:
该函数包含多个参数分别为:cMsg(用于指定对话框的内容)、nIcon(可选,用于指定对话框图标)、nType(可选,用于指定按钮的类型)、cTitle(可选,用于指定对话框标题)、oDoc(可选,指定与警告相关的Doc结构)、oCheckbox(可选,在对话框中放一个checkbox并且可以指定相关内容、初始值以及结束值)
使用示例:
example1
Display a simple alert box:
app.alert({
cMsg: "Error! Try again!",
cTitle: "Acme Testing Service"});
example 2
Close the document with the user’s permission:
// A MouseUp action
var nButton = app.alert({
cMsg: "Do you want to close this document?",
cTitle: "A message from A. C. Robat",
nIcon: 2, nType: 2
});
if ( nButton == 4 ) this.closeDoc()
example 3
One document creates an alert box in another document. There are two documents, DocA and DocB, one open in a browser and the other in the viewer.
// The following is a declaration at the document level in DocA
var myAlertBoxes = new Object;
myAlertBoxes.oMyCheckbox = {
cMsg: "Care to see this message again?",
bAfterValue: false
}
//The following is a mouse-up action in DocA. The variable theOtherDoc is the Doc object of DocB. The alert box asks if the user wants to see this alert box again. If the user clicks the check box, the alert does not appear again.
if ( !myAlertBoxes.oMyCheckbox.bAfterValue )
{
app.alert({
cMsg: "This is a message from the DocA?",
cTitle: "A message from A. C. Robat",
oDoc:theOtherDoc,
oCheckbox: myAlertBoxes.oMyCheckbox
});
}
app.execDialog()
该函数功能创建一个对话框,可以自定义高度定制化对话框。
该函数四元组如下;
doc.getURL()
该函数为通过GET方法获取RL指向文件。
该函数四元组如下;
该函数包含两个参数,分别为cURL(目标文件的地址)和bAppend(如果为true,将运行结果附加到当前文件;当文件在浏览器中运行时,推荐使用false)。
使用示例;
this.getURL("/", false);
当该函数运行后,仍然会有安全性提示,如下:
然而该函数还有另外一个功能是可以运行本地文件,同时为了防止执行任意文件,还在注册表项中\LOCAL_MACHINE\SOFTWARE\Policies\Adobe\Acrobat Reader\11.0\FeatureLoc kDown\ cDef aultLaunchAttachmentPerms进行了限制。当用户尝试执行文件不在限制范围内时,还会调用系统函数SaferiIsExecutableFileType判断是否为可执行文件,同时不受两方面限制后将会出现以下两个弹窗进行提示:
最终打开目标文件;
PDF_XSS
这里使用app.alert()函数在PDF中插入代码来测试xss,当然其他的攻击也可以利用上面的函数进行利用。这里使用的是迅捷PDF编辑器进行PDF的XSS测试。
漏洞复现
首先在编辑器中新建文党,如下;
右键文档缩略图,点击文档的属性设置,可以在右边看到页面设置。
点击动作,可以选择打开和关闭页面的动作设置。进去点击新增按钮,运行JavaScript。
边界js动作为alert弹窗
可以看到在浏览器在线访问时,弹窗成功,js代码执行成功。
经测试,在360浏览器,Google浏览器和Edge浏览器上访问PDF文件,js代码会被执行。
注:
Adobe 支持自身的 JavaScript 对象模型,例如 alert(‘xss’)必须被 APP 对象调用,因此变成了 app.alert(‘xss’)。这意味着,利用 JavaScript 进行攻击时只能使用 Adobe 所支持的功能。
项目实战
在项目功能点发现上传文件选项
构造插入恶意JS语句的PDF文件进行上传,
在Google浏览器上访问上传的PDF文件,JS语句执行,弹窗成功
修复建议
1.作为网站管理员或开发者,可以选择强迫浏览器下载 PDF 文件,而不是提供在线浏览等,或修改 Web 服务器配置的 header 和相关属性
2.使用第三方插件解析pdf,不用chrome自带的pdf解析就行,/adobe-type-tools/cmap-resources