代码审计典型语法结构

浏览:
字体:
发布时间:2013-12-09 23:23:27
来源:

 

  1. 代码执行
    1. eval
    2. include
    3. preg_replace
    4. 重音符
    5. 大括号
    6. ob_start
    7. array_map
    8. unserialize serialize
      1. __destruct
      2. __toString
      3. 绕过方法
    9. 其他容易导致问题的函数
  2. 文件包含
  3. 变量覆盖
    1. 变量注册
    2. 变量销毁
    3. _REQUEST
    4. 其他导致变量覆盖的函数
  4. 随机函数
    1. Rand
  5. 字符串
    1. offset
 

代码执行

eval

php中可以执行代码的方式还是很多的,最普通的就是eval()这个字符串,
需要注意一下
(1)一般情况下双引号中的内容可以被替换和解释,单引号的内容是不能变化的
(2)在eval中申请的变量,所有PHP代码都可访问到
 
<?php	$foobar = "xxx";	eval("echo $foobar;");	eval('echo $foobar;');?>
类似的函数还有

eval() assert() system() exec() shell_exec() passthru() escapeshellcmd() pcntl_exec()  

include

文件包含漏洞,如果开启了远程包含,很容易就会转变为代码执行漏洞。
 
<?php$to_include = $_GET['file'];require_once($to_include . '.html');?>

 

之前做过整理
http://www.vm888.com/Article/201311/258420.html

 
类似的函数还有

nclude() include_once() require() require_once() spl_autoload()  

preg_replace

比较常用的正则表达式,也可以引发代码执行,源于PCRE (Perl Compatible Regular Expressions) 中的e(PREG_REPLACE_EVAL)选项,
这个选项会吧replacement中的内容当做PHP代码执行,并取返回结果的值,其中后项引用可以$1 也可以 //

<?php$var = '<tag>phpinfo()</tag>';preg_replace("/<tag>(.*?)<//tag>/e", '$1', $var);?>

 

但是一般的利用情况是不会有E选项的,我们可以通过%00截断等方式来添加e这个选项
 


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

重音符

这个php会把重音符中的字符串当做代码来执行,这里是执行系统命令而不是php代码

<?php  
echo `dir`;  
?>  
 

大括号

php中会吧大括号中的值当做一个变量,这里我们可以使用${`dir`}这种形式来执行变量,但是不会有回显
 

<?php$year = "10";echo "That was 20${year}-th year.";$foobar = 'phpinfo';${foobar}();?>

这里也可以使用大括号来执行php语句
<?php  
$k = "{${phpinfo()}}";  
?>  

 

ob_start

这个函数可以设定一个回调函数,来进行代码执行,不过貌似只能返回命令执行的最后一行
 

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

 

array_map

这个函数也是可以设定一个回调函数,对一个数组中的元素做处理,并返回处理后的数组
<?php$evil_callback = $_GET['callback'];$some_array = array(0, 1, 2, 3);$new_array = array_map($evil_callback, $some_array);?>

 


unserialize / serialize

__destruct

值个函数执行的时候,会触发原类中的__destruct函数,用户构造一个比较蛋疼的提交的话,就会导致代码执行,但是这种情况也是比较苛刻的
当然也有很多前面带下划线的函数会执行,destruct只是其中一个,__wakeup也会被调用
 

<?phpclass Example {	var $var = '';	function __destruct() {		eval($this->var);	}}unserialize($_GET['saved_code']);?>

 

像这样构造提交


http://127.0.0.1/test.php?saved_code=O:7:"Example":1:{s:3:"var";s:10:"phpinfo();";}  
 

__toString

这个函数,会在serialize调用这个函数,这个函数会返回一个字符串决定serialize的值,重载这个函数会影响这个值
比如下面这个代码就会产生文件包含
 

 
class just4fun {        public $filename;         function __toString() {            return @file_get_contents($this->filename);        }    }

 

绕过方法

有一些程序中会判断用户输入是不是一个序列化的数据,常见的代码如下
 

$token = $data[0];switch ( $token ) {    case 's' :        if ( '"' !== $data[$length-2] )            return false;    case 'a' :    case 'O' :        return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );    case 'b' :    case 'i' :    case 'd' :        return (bool) preg_match( "/^{$token}:[0-9.E-]+;/$/", $data );

 

这个可以用+来绕过,这也属于PHP的一种特性

O:+4:"test":1:{s:1:"a";s:3:"aaa";}   
当然还有很多类似的绕过方法
 

$str1 = 's:8:"ryatsyne";';$str2 = 's:8:"ryatsyne"t';$str3 = 'S:8:"/72/79/61/74/73/79/6e/65"';

 

其他容易导致问题的函数

array_map()usort(), uasort(), uksort()array_filter()array_reduce()array_diff_uassoc(), array_diff_ukey()array_udiff(), array_udiff_assoc(), array_udiff_uassoc()array_intersect_assoc(), array_intersect_uassoc()array_uintersect(), array_uintersect_assoc(), array_uintersect_uassoc()array_walk(), array_walk_recursive()xml_set_character_data_handler()xml_set_default_handler()xml_set_element_handler()xml_set_end_namespace_decl_handler()xml_set_external_entity_ref_handler()xml_set_notation_decl_handler()xml_set_processing_instruction_handler()xml_set_start_namespace_decl_handler()xml_set_unparsed_entity_decl_handler()stream_filter_register()set_error_handler()register_shutdown_function()register_tick_function()

 

文件包含


http://www.vm888.com/Article/201311/258420.html

变量覆盖

变量覆盖漏洞产生的原因有两种
第一种是register_globals为on的情况,PHP4默认开启,PHP5以后默认关闭。
第二种是人为注册成为全局变量

变量注册

 

<?php       foreach(Array('_GET','_POST','_COOKIE') as $_request)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);&nbsp; &nbsp; &nbsp; &nbsp; }?>

 

这里如果我们构造这样的提交,便可以修改GLOBALS中的变量

http://127.0.0.1/test.php?_POST[GLOBALS][XXX]=wyl  
程序会通过$_GET注册了$_POST,通过$_POST注册了$GLOBALS! 

变量销毁

有的时候为了防止全局变量覆盖,会出现这样的代码
 

//if register globals = on, undo var overwritesforeach(array('_GET','_POST','_REQUEST','_COOKIE') as $method){     foreach($$method as $key=>$value){          unset($$key);     }}

 

这样很容易导致一些关键变量被销毁
 

$_REQUEST

这个数组保存了Get  Post传递的变量,不过在变量名相同的情况下post中的变量会覆盖get中的变量
比如如下的代码,用来检测变量中是否有数组存在


foreach($_REQUEST as $request) {    if(is_array($request)) {        die("Can not use Array in request!");    }}
 
当提交  GET:LanLan[xxxxx]=xxxxx   POST:LanLan=1  便可绕过这个检测 
 

其他导致变量覆盖的函数

还有一些函数的使用可能导致变量覆盖

parse_str   mb_parse_str  import_request_variables  

随机函数

PHP中一般使用随机函数来生成session

Rand()

此函数生曾的最大随机数是32767,很容易被暴力破解。
 
 
 

字符串

offset

这是php字符串的一个特性,下面的两条echo都会输出L,PHP对字符串大括号中的变量,进行类型转换'hi'转换成整形之后的值为0
  1. $xigr = 'LanLan';  
  2. echo $xigr[0];  
  3. echo $xigr['hi'];  
这种特性会引发一些漏洞,比如这样的情况,如果admin被变量覆盖成了字符串型,那么就可以绕过下面的check判断
  1. $admin['check'] = "0";  
  2. $admin['pass']  = "angel";  
  3.  ......  
  4. if($admin['check'] == "1") {  
  5. ....  
  6. }  
总的来说就是把一个原本是数组型的变量,被覆盖成字符串型,但是根据PHP的特性,程序依然可以继续执行~但是会给各种不法分子提供做坏事的机会。
这种特性在GPC开启的情况下,可以用来引入反斜杠,不过条件比较苛刻

>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();