常见的导致文件包含的函数有:
PHP:include(),include_once(),require(),require_once(),fopen(),readfile() 等 JSP Servlet:ava.io.File(),java.io.FileReader() 等 ASP:includefile,includevirtual 等当 PHP 包含一个文件时,会将该文件当做 PHP 代码执行,而不会在意文件时什么类型。
本地文件包含¶本地文件包含,Local File Inclusion,LFI。
上述代码存在本地文件包含,可用 %00 截断的方式读取 /etc/passwd 文件内容。
%00 截断 ?file=../../../../../../../../../etc/passwd%00需要 magic_quotes_gpc=off,PHP 小于 5.3.4 有效。
路径长度截断 ?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.Linux 需要文件名长于 4096,Windows 需要长于 256。
点号截断 ?file=../../../../../../../../../boot.ini/………[…]…………只适用 Windows,点号需要长于 256。
远程文件包含¶远程文件包含,Remote File Inclusion,RFI。
当 register_globals=ON 时,提交 test.php?auth=1,auth 变量将自动得到赋值。
extract() 变量覆盖¶extract() 函数能够将变量从数组导入到当前的符号表,其定义为
int extract ( array $var_array [, int $extract_type [, string $prefix ]] )其中,第二个参数指定函数将变量导入符号表时的行为,最常见的两个值是 EXTR_OVERWRITE 和 EXTR_SKIP。
当值为 EXTR_OVERWRITE 时,在将变量导入符号表的过程中,如果变量名发生冲突,则覆盖所有变量;值为 EXTR_SKIP 则表示跳过不覆盖。若第二个参数未指定,则在默认情况下使用 EXTR_OVERWRITE。
当 extract() 函数从用户可以控制的数组中导出变量时,可能发生变量覆盖。
import_request_variables 变量覆盖¶ bool import_request_variables (string $types [, string $prefix])import_request_variables 将 GET、POST、Cookies 中的变量导入到全局,使用这个函数只用简单地指定类型即可。
import_request_variables("G") 指定导入 GET 请求中的变量,提交 test.php?auth=1 出现变量覆盖。
parse_str() 变量覆盖¶ void parse_str ( string $str [, array &$arr ])parse_str() 函数通常用于解析 URL 中的 querystring,但是当参数值可以被用户控制时,很可能导致变量覆盖。
// var.php?var=new 变量覆盖$var = "init";parse_str($_SERVER["QUERY_STRING"]);print $var;与 parse_str() 类似的函数还有 mb_parse_str()。
命令执行¶ 直接执行代码¶PHP 中有不少可以直接执行代码的函数。
eval();assert();system();exec();shell_exec();passthru();escapeshellcmd();pcntl_exec();...... preg_replace() 代码执行¶preg_replace() 的第一个参数如果存在 /e 模式修饰符,则允许代码执行。
如果没有 /e 修饰符,可以尝试 %00 截断。
preg_match 代码执行¶preg_match 执行的是匹配正则表达式,如果匹配成功,则允许代码执行。
这道题是 xman 训练赛的时候,梅子酒师傅出的一道题。这一串代码描述是这样子,我们要绕过 A-Z、a-z、0-9 这些常规数字、字母字符串的传参,将非字母、数字的字符经过各种变换,最后能构造出 a-z 中任意一个字符,并且字符串长度小于 40 。然后再利用 PHP 允许动态函数执行的特点,拼接出一个函数名,这里我们是 getFlag,然后动态执行该代码即可。
那么,我们需要考虑的问题是如何通过各种变换,使得我们能够去成功读取到 getFlag 函数,然后拿到 webshell 。
在理解这个之前,我们首先需要大家了解的是 PHP 中异或 ^ 的概念。
我们先看一下下面这段代码:
运行结果如下:
我们可以看到,输出的结果是字符 ~。之所以会得到这样的结果,是因为代码中对字符 A 和字符 ? 进行了异或操作。在 PHP 中,两个变量进行异或时,先会将字符串转换成 ASCII 值,再将 ASCII 值转换成二进制再进行异或,异或完,又将结果从二进制转换成了 ASCII 值,再将 ASCII 值转换成字符串。异或操作有时也被用来交换两个变量的值。
比如像上面这个例子
A 的 ASCII 值是 65 ,对应的二进制值是 01000001
? 的ASCII值是 63 ,对应的二进制值是 00111111
异或的二进制的值是 01111110 ,对应的 ASCII 值是 126 ,对应的字符串的值就是 ~ 了
我们都知道, PHP 是弱类型的语言,也就是说在 PHP 中我们可以不预先