高级PHP应用程序漏洞审核技术(笔记)

一、变量本身的key

说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。

<?php
//key.php?aaaa'aaa=1&amp;bb'b=2
//print_R($_GET);

foreach ($_GET AS $key => $value){
print $key."\n";
}
?>

此处$_GET的值是数组,例如Array ( [aaaa'aaa] => 1 [bb'b] => 2 ),$key和$value变量名可为任意,分别是键名和键值。

二、变量覆盖

1)extract()函数

extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指定函数可以导致变量覆盖。
语法
  extract(array,extract_rules,prefix)
参数
  array 必需。规定要使用的输入。
  extract_rules
    ·EXTR_OVERWRITE – 默认。如果有冲突,则覆盖已有的变量。
    ·EXTR_SKIP – 如果有冲突,不覆盖已有的变量。(忽略数组中同名的元素)
  prefix 可选。
例子

<?php
$a = 'Original';
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
?>

输出:

$a = Cat; $b = Dog; $c = Horse

2)遍历初始化变量

<?php
//var.php?a=fuck
$a='hi';
foreach($_GET as $key =&gt; $value) {
$key = $value;
}
print $a;
?>

3)parse_str()变量覆盖漏洞

parse_str() 函数把查询字符串解析到变量中。
语法
  parse_str(string,array)
参数
  string 必需。规定要解析的字符串。
  array 可选。规定存储变量的数组名称。该参数指示变量存储到数组中。
例子 1

<?php
parse_str("id=23&name=John Adams");
echo $id."<br />";
echo $name;
?>

例子 2

<?php
parse_str("id=23&name=John Adams",$myArray);
print_r($myArray);
?>

输出:

Array
(
[id]
=> 23
[name]
=> John Adams
)

4)import_request_variables()变量覆盖漏洞

将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了register_globals,但又想用到一些全局变量,那么此函数就很有用。
语法
  bool import_request_variables ( string types [, string prefix] )
参数
  types指定需要导入的变量,可以用字母‘G’、‘P’和‘C’分别表示 GET、POST 和 Cookie。注意这些字母的顺序,当使用“gp”时,POST 变量将使用相同的名字覆盖 GET 变量。任何 GPC 以外的字母都将被忽略。

  prefix可选参数,作为变量名的前缀,置于所有被导入到全局作用域的变量之前。

例子

//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
if ($_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!');
echo 'Hello admin!';

5)PHP5 Globals

php.ini的register_globals =On时,若变量未初始化可造成变量覆盖。

<?php
//var.php?GLOBALS[a]=aaaa&b=111
if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
print $a;
print $_GET[b];
?>

三、哪些地方magic_quotes_gpc没有被保护

1) $_SERVER变量

例如$_SERVER['REMOTE_ADDR'],可以获取客户端的IP地址。X-Forwarded-For漏洞就是利用了$_SERVER变量。

2) getenv()得到的变量

语法
  string getenv(string varname);
getenv()与$_SERVER的区别是getenv()不支持IIS的isapi方式运行的php

3) $HTTP_RAW_POST_DATA与PHP输入、输出流

四、代码注射

参考原文链接http://hi.baidu.com/menzhi007/blog/item/4622205578c33ac8b745ae9f.html

1)代码执行函数

PHP中可以执行代码的函数。如eval()、assert()、``、system()、exec()、shell_exec()、passthru()、 escapeshellcmd()、pcntl_exec() 等

<?php
echo system(dir);
echo `dir`;
?>

2)文件包含

include(),include_once(),require(),require_once(),当allow_url_include=On ,PHP Version>=5.2.0时的代码注射。

<?php
//
http://127.0.0.1/include.php?a=data:text/plain,%3C?php%20phpinfo%28%29;?%3E
include($_GET['a']);
?>

3)正则匹配

preg_replace()函数的pattern参数中若存在/e模式修饰符,即允许执行代码,则有可能产生代码注射。

<?php
echo $regexp = $_GET['reg'];
$var = '<php>phpinfo()</php>';
preg_replace("/<php>(.*?)$regexp", '\\1', $var);
?>

提交URL“http://127.0.0.1/preg_replace1.php?reg=%3C\/php%3E/e”。
分析:
$regexp为“%3C\/php%3E/e”,即“<\/php>/e”,代码即为preg_replace("/<php>(.*?)<\/php>/e", '\\1', $var); 意思是查找$var,根据该正则替换为匹配第一个子模式的文本【即phpinfo()】并执行。

4)动态代码执行

<?php
$dyn_func = $_GET['dyn_func'];
$argument = $_GET['argument'];
$dyn_func($argument);
?>

提交 http://127.0.0.1/dyn_func.php?dyn_func=system&argument=ipconfig 执行ipconfig命令。

<?php
$foobar = $_GET['foobar'];
$dyn_func = create_function('$foobar', "echo $foobar;");
$dyn_func('');
?>

提交 http://127.0.0.1/create_function.php?foobar=system%28dir%29 执行dir命令。同样代码可以写成create_function('', "echo system(dir);"),第一个参数表示函数参数,第二个表示函数代码,例如:

<?php
$dyn_func = create_function('$a,$b','echo $a+$b;');
$dyn_func(1,2);
?>

5)其他函数

(1)ob_start()//执行system(dir),求解释。。。不懂

<?php
$foobar = 'system';
ob_start($foobar);
echo 'dir';
ob_end_flush();
?>

(2)array_map() 函数,返回用户自定义函数作用后的数组。回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。
语法:
array_map(function,array1,array2,array3...)

<?php
$evil_callback = $_GET['callback'];
$some_array = array(0, 1, 2, 3);
$new_array = array_map($evil_callback, $some_array);
//提交http://127.0.0.1/1.php?callback=phpinfo
?>

(3)其他。。。

五、PHP自身函数漏洞及缺陷

1)溢出漏洞

2)其他漏洞

(1)unset()--Zend_Hash_Del_Key_Or_Index Vulnerability
(2)session_destroy()删除文件漏洞    //经测试,win32 php 5.3.3不起作用
session_destroy()函数的功能是删除session文件,很多web应用程序的logout的功能都直接调用这个函数删除session,但是这个函数在一些老的版本中缺少过滤导致可以删除任意文件。

<?php 
session_save_path('./');
session_start();
if($_GET['del']) {
session_unset();
session_destroy();
}
else{
$_SESSION['hei']=1;
echo(session_id());
print_r($_SESSION);
}
?>

提交构造cookie例如:PHPSESSID=/../1.php,则可删除1.php。
(3)随机函数

六、特殊字符

posted @ 2011-07-21 17:51  Landon  阅读(1442)  评论(0编辑  收藏  举报