高级PHP应用程序漏洞审核技术(笔记)
一、变量本身的key说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。
<?php
//key.php?aaaa'aaa=1&bb'b=2
//print_R($_GET);
foreach ($_GET AS $key => $value){
print $key."\n";
}
?>
此处$_GET的值是数组,例如Array ( => 1 => 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 => $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
(
=> 23
=> 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=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=aaaa&b=111
if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
print $a;
print $_GET;
?>
三、哪些地方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)随机函数
六、特殊字符
页:
[1]