了解 Web 应用程序中的文件包含漏洞

Beginner

介绍

欢迎来到我们关于 Web 应用漏洞的入门课程,我们将重点关注文件包含漏洞(file inclusion vulnerabilities),这是 Web 应用中最普遍的问题之一。

在本模块中,我们将首先剖析 Web 应用中“文件包含”(file inclusion)的概念。然后,我们将在此基础上阐述什么是“文件包含漏洞”。最后,我们将深入探讨文件包含漏洞的两个主要类别。

在本模块的后续部分,我们将深入研究“本地文件包含漏洞”(Local File Inclusion Vulnerabilities)和“远程文件包含漏洞”(Remote File Inclusion Vulnerabilities),为您提供对这些关键安全问题的全面理解。

关键学习成果
  • 理解 Web 应用中文件包含的基本概念。
  • 掌握文件包含漏洞的底层原理。
  • 了解文件包含漏洞的两种主要类型:本地(Local)和远程(Remote)。

理解文件包含

让我们深入了解“文件包含”(file inclusion)的概念及其潜在的漏洞,特别是针对初学者。

文件包含是编程中的常见做法,尤其是在代码可重用性的背景下。开发者通常将频繁使用的函数或模块封装到单独的文件中。当需要这些函数或模块时,他们只需在代码中包含(include)这些文件,从而避免重复编写相同的代码。

在 PHP 中,主要有四种用于文件包含的函数:

  1. include()
  2. require()
  3. include_once()
  4. require_once()

以下是每种函数的简要概述:

  • include(): 此函数在被调用时包含一个文件。如果找不到该文件,PHP 会发出一个警告(warning),但脚本会继续执行。
  • require(): 此函数在脚本开始执行前包含一个文件。如果找不到该文件,PHP 会发出一个致命错误(fatal error)并终止脚本。
  • include_once()require_once(): 这些函数的工作方式与 include()require() 类似,但它们确保文件只被包含一次,即使该函数被多次调用。

文件包含方法可以大致分为两类:

  1. 静态包含(Static inclusion)
  2. 动态包含(Dynamic inclusion)

这两种类型的区别将在接下来的部分通过示例进行阐明。

在我们的实验中,我们将探索位于 /home/labex/project/ 目录下的三个 .php 文件。它们是:

  • lfi_static.php
  • lfi_dynamic.php
  • echo.php

让我们了解每个文件的作用:

  • lfi_static.php: 此文件以静态方式包含 echo.php 文件。换句话说,echo.php 文件的路径是硬编码的,不会改变。这种方法是安全的,不会暴露任何漏洞。

    <?php
    include("./echo.php");
    ?>
    
  • lfi_dynamic.php: 此文件根据 URL 中的 'file' 参数包含其他文件。如果未提供此参数,它会提供如何使用的提示。然而,如果此参数受攻击者控制,这种方法可能存在风险。

    <?php
    if (isset($_GET['file'])) {
        include($_GET['file']);
    }
    else{
        echo "You can use the 'file' parameter to include files";
    }
    ?>
    
  • echo.php: 此文件在被包含时仅输出一条成功消息。

    <?php
    echo 'Great, now you have successfully included the content of echo.php!'
    ?>
    

使用终端中的以下命令准备用于 lfi 测试的镜像:

cd ~/projects
docker build -t lfi-image .

当镜像构建完成后,你可以使用该镜像启动一个容器来测试 lfi 漏洞:

docker run -d --name lfi -p 80:80 lfi-image

现在你可以在浏览器中测试这些文件了。例如,要访问 lfi_static.php 文件,你需要输入以下 URL:

http://127.0.0.1/LFI/lfi_static.php

你会看到 lfi_static.php 文件成功包含了 echo.php 的内容。请记住,这种静态的文件包含方法是安全的。

现在,让我们看看 lfi_dynamic.php 文件。使用以下 URL 访问它:

http://127.0.0.1/LFI/lfi_dynamic.php

你会看到一个提示,告诉你使用 'file' 参数。我们照做,包含 echo.php

http://127.0.0.1/LFI/lfi_dynamic.php?file=./echo.php

你会看到 echo.php 已成功包含。这演示了文件包含的工作原理。重要的是要记住,虽然这是一个 PHP 示例,但这些原理适用于其他编程语言,尽管所使用的具体函数可能有所不同。

理解文件包含漏洞

我们最近学习了如何使用 lfi_dynamic.php 中的 file 参数来包含 echo.php 文件。但一个问题出现了:

是否有可能使用 file 参数包含其他文件?

答案是肯定的!

如果 Web 开发者疏于验证 file 参数,它就有可能被利用来包含服务器上敏感的文件。

以下是一些示例:

  • 在 Linux 系统上,你可能可以包含 /etc/passwd 文件。
  • 在 Windows 系统上,你可能可以包含 C:\Windows\System32\drivers\etc\hosts 文件。

让我们通过一个例子来说明这一点。假设我们将 file 参数设置为 /etc/passwd

http://127.0.0.1/LFI/lfi_dynamic.php?file=/etc/passwd

在浏览器中打开该 URL,你会看到我们成功包含了并显示了 /etc/passwd 文件的内容。这表明存在本地文件包含(Local File Inclusion, LFI)漏洞,这是一个严重的安全问题。

请记住,理解这些漏洞是预防它们的第一步。务必确保验证和清理(sanitize)你在 Web 应用中的所有用户输入。

文件包含漏洞的类型

文件包含漏洞是 Web 安全中的一个关键问题,通常分为两种主要类型:

  1. 本地文件包含(Local File Inclusion, LFI): 此类漏洞发生在包含目标服务器上的本地文件时。

  2. 远程文件包含(Remote File Inclusion, RFI): 此类漏洞发生在包含位于不同、远程服务器上的文件时。

在我们之前讨论的示例中,包含本地 /etc/passwd 文件就是一个典型的本地文件包含(LFI)漏洞实例。理解这两种漏洞类型的区别对于有效保护你的 Web 应用至关重要。

总结

在这个实验(Lab)中,你学习了如何通过文件包含功能发起攻击的方法和过程。让我们回顾一下本节涵盖的重要知识点:

  • 什么是文件包含?
  • 什么是文件包含漏洞?
  • 文件包含漏洞有哪些类型?