PHP代码审计:变量覆盖

0x00 前提

本文是给作为给小伙伴分享教学的一篇文章,给讲一下,所以写的比较简陋。。。见谅而且都比较基础,只是简单讲课提纲吧

0x01 变量覆盖审计

0x00 简介

变量覆盖,顾名思义就是可以覆盖已有变量值,导致变量覆盖的漏洞

常见的造成的代码审计的情景是代码中出现以下关键词:

  • register_globals=on
  • extract()函数
  • parse_str()函数
  • import_request_variables()函数
  • $$

0x01 变量覆盖演示

extract()

extract(array,extract_rules,prefix)函数

https://www.runoob.com/php/func-array-extract.html

该函数可以从数组中将变量导入到当前的符号表,即将数组中的键值对注册成函数,使用数组键名作为变量名,使用数组键值作为变量值。

这里我们要注意一下该函数的第二个参数

  • EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。
  • EXTR_SKIP - 如果有冲突,不覆盖已有的变量。

这就为我们提供了覆盖的可能。

<?php
$a = 'a';
echo $a.'</br>';
extract($_GET);
echo $a
?>

可以看到我们初始变量值为a但是覆盖之后就变成了我们输入的值。

http://127.0.0.1/test/extract.php?a=123

image-20200907141301903

修复:

在使用extract()函数时,可以指定将第二个参数设置为EXTRS_KIP

parse_str()

parse_str()函数用于把查询字符串解析到变量中,如果没有array参数,则由该函数设置的变量将覆盖已存在的同名变量。

在没有array参数的情况下使用此函数,

并且在PHP 7.2中将废弃不设置参数的行为,此函数没有返回值。

<?php
$a = "giao";
echo "a:" . $a;
echo "<br>";
$b = $_GET['b'];
parse_str($b);
echo "a_2:" . $a;
?>
http://127.0.0.1/test/parse_str.php?b=a=zeo

image-20200907145448737

$$

典型的例子就是foreach来遍历数组中的值作为变量。

$$是一种可变变量的写法,它可以使一个普通变量的值作为可变变量的名字,这种类型常常会使用遍历的方式来释放变量的代码

<?php
$a = 10;
echo $a;
echo "<br>";
foreach ($_POST as $k => $v){
    $$k = $v;
    echo $a;
}
?>

image-20200907141129332

import_request_variables()

import_request_variables ( string $types , string $prefix )

https://www.runoob.com/php/php-import_request_variables-function.html

import_request_variables() 函数将 GET/POST/Cookie 变量导入到全局作用域中。该函数在最新版本的 PHP 中已经不支持。

import_request_variables() 函数将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。

版本要求:PHP 4 >= 4.1.0, PHP 5 < 5.4.0

第二个参数$types:指定需要导入的变量,可以用字母 G、P 和 C 分别表示 GET、POST 和 Cookie,这些字母不区分大小写,所以你可以使用 g 、 p 和 c 的任何组合。POST 包含了通过 POST 方法上传的文件信息。注意这些字母的顺序,当使用 gp 时,POST 变量将使用相同的名字覆盖 GET 变量。任何 GPC 以外的字母都将被忽略。

image-20200907104858013

全局变量

当你在升级PHP到PHP5.4及之后的版本的时候,是否发现register_global配置指令不再生效了呢

因为从PHP5.4开始register_global配置指令被移除了。

<?php
echo "register_globals: " . (int)ini_get("register_globals");
echo '<br>';
echo "a=" . $a;
?>

image-20200907114032777

0x02 深x服edr实例

简化后的代码

<?php
#var_dump($_REQUEST);


$show_form = function($params) use(&$strip_slashes, &$show_input) {
    extract($params);

    $host  = isset($host)  ? $strip_slashes($host)  : "127.0.0.1";
    $path  = isset($path)  ? $strip_slashes($path)  : "";
    $row   = isset($row)   ? $strip_slashes($row)   : "";
    $limit = isset($limit) ? $strip_slashes($limit) : 1000;

    // 绘制表单
    echo "<pre>";
    echo '<form id="studio" name="studio" method="post" action="">';
    $show_input(array("title" => "Host ",  "name" => "host",  "value" => $host,  "note" => " - host, e.g. 127.0.0.1"));
    $show_input(array("title" => "Path ",  "name" => "path",  "value" => $path,  "note" => " - path regex, e.g. mapreduce"));
    $show_input(array("title" => "Row  ",  "name" => "row",   "value" => $row,   "note" => " - row regex, e.g. \s[w|e]\s"));
    $show_input(array("title" => "Limit",  "name" => "limit", "value" => $limit, "note" => " - top n, e.g. 100"));
    echo '<input type="submit" id="button">';
    echo '</form>';
    echo "</pre>";
};

$show_form($_REQUEST);

?>

变量匿名函数 $show_form 具有一个形式参数 $params

在这里也就是array(“strip_slashes”=>“system”,“host”=>“id”);

接下来执行extract($params);,后进入如下代码:

$host  = isset($host)  ? $strip_slashes($host)  : "127.0.0.1";

在这个过程中就产生了漏洞,想要了解具体原因:

首先函数传入参数值为array("strip_slashes"=>"system","host"=>"id");

经过extract()函数后,赋值了2个变量:

$strip_slashes = 'system';
$host = 'id';

变量$host利用三元运算重新赋值$strip_slashes($host)

而实际上其赋值内容是函数system('id')的返回结果,这也就造成了命令执行漏洞。

0x03MetInfo实例

/include/common.inc.php

传入的cookie、get、post参数进行变量赋值

foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
	foreach($$_request as $_key => $_value) {
		$_key{0} != '_' && $$_key = daddslashes($_value);
	}
}

daddslashes()防注入,不过并不影响

随便来到一个子文件看看他的加载方式\about\index.php

<?php
# MetInfo Enterprise Content Management System 
# Copyright (C) MetInfo Co.,Ltd (http://www.metinfo.cn). All rights reserved. 
$filpy = basename(dirname(__FILE__));
$fmodule=1;
require_once '../include/module.php';
require_once $module;
# This program is an open source system, commercial use, please consciously to purchase commercial license.
# Copyright (C) MetInfo Co., Ltd. (http://www.metinfo.cn). All rights reserved.
?>

这里使用了require_once函数包含了/include/module.php文件,可以发现这个文件又包含了common.inc.php文件

出现了两个未知变量:$module$fmodule。我们可以用$fmodule变量通过两次文件包含,使用$_request来获取GET传递的新$fmodule值实现变量覆盖。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值