标题: PHP文件包含漏洞详解(包含截断方法) [打印本页] 作者: admin 时间: 2013-4-19 19:07 标题: PHP文件包含漏洞详解(包含截断方法) 一、什么才是”远程文件包含漏洞”? 0 N3 [ O2 M% U4 r 3 _! x E, s: F' q7 \: F$ m回答是:服务器通过php的特性(函数)去包含任意文件时,由于要包含的这个文件来源过滤不严,从而可以去包含一个恶意文件,而我们可以构造这个恶意文件来达到邪恶的目的。 / p" i5 F# u0 g) C3 ~' r2 z$ E$ t/ q* b R1 ^8 `* I; x
涉及到的危险函数:include(),require()和include_once(),require_once() * @5 j8 G7 w2 T3 }2 I& P. R1 p/ Q/ n3 w8 t5 o @6 M3 w0 z
Include:包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但整个php文件继续执行。 ; Q* Z; g, D% V6 X! J5 Q+ ]Require:跟include唯一不同的是,当产生错误时候,include下面继续运行而require停止运行了。- Y2 v! }' c0 D$ g$ V; E7 ^
Include_once:这个函数跟include函数作用几乎相同,只是他在导入函数之前先检测下该文件是否被导入。如果已经执行一遍那么就不重复执行了。. `* k0 ^5 X6 a$ K0 I$ j/ t' j% M& X
Require_once:这个函数跟require的区别 跟上面我所讲的include和include_once是一样的。所以我就不重复了。 - z! Z4 w2 E9 Z1 h s" L; K% R4 {/ h2 }, n% d- k
php.ini配置文件:allow_url_fopen=off 即不可以包含远程文件。Php4存在远程&本地,php5仅存在本地包含。" k8 S" U8 Y1 }
7 y0 u9 _6 Y& _, ~. }
二、为什么要包含文件?, [9 k- E: q" I; Z
2 l3 S8 D; s1 P9 k& j
程序员写程序的时候,不喜欢干同样的事情,也不喜欢把同样的代码(比如一些公用的函数)写几次,于是就把需要公用的代码写在一个单独的文件里面,比 如 share.php,而后在其它文件进行包含调用。在php里,我们就是使用上面列举的那几个函数来达到这个目的的,它的工作流程:如果你想 在 main.php里包含share.php,我将这样写include(“share.php”)就达到目的,然后就可以使用share.php中的 函数了,像这个写死需要包含的文件名称的自然没有什么问题,也不会出现漏洞,那么问题到底是出在哪里呢?3 k$ I1 E. h! W) ~- M7 Z
6 T S2 @4 |% V8 @9 L, t
有的时候可能不能确定需要包含哪个文件,比如先来看下面这个文件index.php的代码:; \& v5 x P# P& }' j
@5 j( U1 g5 \, y
if ($_GET) { % ]9 M4 G, H' B6 w6 q8 o( \; N include $_GET; ' Y6 H% }% H% Z! t. W} else { ! @, g9 t7 V$ j8 b8 n" l. e5 r include ”home.php”;; H7 c2 H4 P# `; o5 A
} + Z d/ C+ f5 @& M 8 v. v2 V/ y9 ~! K K+ T很正常的一段PHP代码,它是怎么运作的呢?( V& y" {1 V' I' C
' K4 ~& l3 G5 k6 Q上面这段代码的使用格式可能是这样的: ) }) q- c) A0 c+ z( i1 q& E; r7 H+ E- l2 W http://hi.baidu.com/m4r10/php/index.php?page=main.php或者8 v+ ?4 m( V/ | http://hi.baidu.com/m4r10/php/index.php?page=downloads.php2 p$ s: J; |, K
5 @# o+ |& Z: A1 `8 A
结合上面代码,简单说下怎么运作的: C$ O. @& s* {1 @# Y7 i8 w3 k' j6 r! d. M, C: G! m3 k6 q3 L
1.提交上面这个URL,在index.php中就取得这个page的值($_GET)。 _- y8 u! @( V* d
2.判断$_GET是不是空,若不空(这里是main.php)就用include来包含这个文件。 % z0 ]# S7 f9 ~. }) O) N% n! P3.若$_GET空的话就执行else,来 include ”home.php” 这个文件。 ( _1 s- `; ^0 z1 a8 a5 G" H6 @; N0 C$ Y9 p! O
三、为什么会产生漏洞? 4 i# b; K% O6 n y4 u3 X, j4 ~8 |9 `) m! r" l, s# f
你也许要说,这样很好呀,可以按照URL来动态包含文件,多么方便呀,怎么产生漏洞的呢?问题的答案是:我们不乖巧,我们总喜欢和别人不一样,我们 不会按照他的链接来操作,我们可能想自己写想包含(调用)的文件,比如我们会随便的打入下面这个URL:http: //hi.baidu.com /m4r10/php/index.php?page=hello.php。然后我们的index.php程序就傻傻按照上面我们说得步骤去执行:取 page为hello.php,然后去include(hello.php),这时问题出现了,因为我们并没有hello.php这个文件,所以 它 include的时候就会报警告,类似下列信息:7 H$ ~0 z: u# l9 t
( a9 I# e U4 @' {Warning: include(hello.php) [function.include]: failed to open stream: No such file or directory in /vhost/wwwroot/php/index.php on line 33 w0 w. `6 s2 X! a
Warning: include() [function.include]: Failed opening ’hello.php’ for inclusion (include_path=’.:’) in /vhost/wwwroot/php/index.php on line 3 3 u9 w9 k( O4 A8 i+ h# N # i" B$ E$ N, k1 Q' Y注意上面的那个Warning就是找不到我们指定的hello.php文件,也就是包含不到我们指定路径的文件;而后面的警告是因为前面没有找到指定文件,所以包含的时候就出警告了。; {8 [) i' p& L O
8 L& N& r! J4 u. B( p- i
四、如何利用? h# h* x+ v; L6 h" g9 v4 L ) {1 ], y- P a' ^6 u/ L上面可以看到,问题出现了,那么我们怎么利用这样的漏洞呢,利用方法其实很多,但是实质上都是差不多的,我这里说三个比较常见的利用方法: ' C' X. X) T3 L3 O) s# Z+ k. z7 ^: C# X" h! ~
1.包含读出目标机上其它文件* ^* x# [, f0 d/ L4 G4 Q3 f9 [
9 t y+ ], R; G+ h6 e' h由前面我们可以看到,由于对取得的参数page没有过滤,于是我们可以任意指定目标主机上的其它敏感文件,例如在前面的警告中,我们可以看到暴露的绝对路径(vhost/wwwroot/php/),那么我们就可以多次探测来包含其它文件,比如指定URL为:http://hi.baidu.com /m4r10/php/index.php?page=./txt.txt可以读出当前路径下的txt.txt文件,也可以使用../../进行目录跳转 (在没过滤../的情况下);也可以直接指定绝对路径,读取敏感的系统文件,比如这个URL:http://hi.baidu.com/m4r10 /php/index.php?page=/etc/passwd,如果目标主机没有对权限限制的很严格,或者启动Apache的权限比较高,是可以读出 这个文件内容的。否则就会得到一个类似于:open_basedir restriction in effect.的Warning(这里是由于apache的open_basedir中限制了访问目录)。' {' X+ [8 S, @1 l7 n5 k
( C; I& d. Y' y5 Q N4 X1 Z: z- [( T y6、利用phpinfo页面getshell。一般大组织的web群存在phpinfo的机会挺大的。% e& y, X( N, [, R t$ Z
poc和介绍参考:" ]% B/ a0 _, Q9 H8 H
《利用phpinfo信息LFI临时文件》 % Z }% ^/ @$ |* K( Zhttp://hi.baidu.com/idwar/blog/item/43101de153370126279791f2.html) g& k6 e, W( |0 l1 X, c5 k! v