php变量类型-PHP代码审计-变量覆盖漏洞

2023-08-23 0 1,701 百度已收录

变量覆盖漏洞

变量覆盖(DynamicVariableEvaluation)是指变量还没有被初始化,我们自定义的参数值可以替换程序原来的变量值。

漏洞危害:

一般结合程序中的其他漏洞实现完整的攻击,例如文件上传页面覆盖原来的白名单列表,导致任意文件上传; 未初始化的变量未被用户注册页面控制覆盖导致SQL。

挖矿经验:

迭代已初始化的变量

常见遍历方法释放代码,可能导致变量覆盖漏洞

extract() 变量覆盖

intexttract($array, extract_rules, 前缀)

• 与$array 关联的字段受第二个和第三个参数的影响。

• extract_rules 如何处理非法/数字和冲突密钥将遵循提取标志

• 仅当第二个参数特殊时才需要前缀,添加前缀

危险函数

• EXTR_OVERWRITE - 默认值。 如果存在冲突php变量类型,现有变量将被覆盖。

• EXTR_SKIP - 如果存在冲突,请勿覆盖现有变量。 (忽略链表中同名元素)

• EXTR_PREFIX_SAME - 如果存在冲突,请在变量名称前添加前缀。从 PHP 4.0.5 开始,这还包括数字对

索引处理

• EXTR_PREFIX_ALL - 所有变量名称都添加前缀(第三个参数)

• EXTR_PREFIX_INVALID - 仅添加非法或数字变量名称的前缀。 该标签是PHP4.0.5中新添加的。

• EXTR_IF_EXISTS - 仅当当前符号表中已存在同名变量的值时才覆盖它们。 其他未处理,已可以使用

定义了一组合法的变量,然后需要从$_REQUEST这样的链表中取出值来覆盖这样的变量。 这个标记是PH

P4.2.0中新增。

• EXTR_PREFIX_IF_EXISTS - 仅当当前符号表中已存在同名变量时才构造附加前缀的变量名,除此之外别无其他

处理。 该标签是PHP4.2.0中新添加的。

• EXTR_REFS - 提取变量作为引用。 这强烈表明导出的变量始终引用 var_array 参数的值。可以

单独使用该标志或与 extract_type 中的任何其他标志或 OR 一起使用。该标签是 PHP4.3.0 中新添加的

的。

变量覆盖是指通过外部输入覆盖变量的值。

通常,将原始变量值可以替换为自定义参数值的情况称为变量覆盖漏洞。

0x02register_globals 全局变量覆盖

php.ini中有一项叫做register_globals,就是注册全局变量。 当register_globals=On时,传递的值将直接注册为全局变量并直接使用。 当register_globals=Off时,我们需要去特定的字段去获取。

注意:register_globals 自 PHP5.3.0 起已被弃用,自 PHP5.4.0 起将被删除。

当register_globals=On时,变量未初始化且可由用户控制,会存在变量覆盖漏洞:

1
2
3
4
5
6
7

<?php
echo "Register_globals: " . (int)ini_get("register_globals") . "
"; if ($a) { echo "Hacked!"; } ?>

通过GET和POST方法输入变量a的值:

其实也可以从COOKIE中输入:

0x03extract() 变量覆盖率

extract() 函数将变量从链表导出到当前符号表。 该函数使用链表键值作为变量名,使用链表通配符作为变量值。 对于链表中的每个元素,都会在当前符号表中创建一个对应的变量。

函数定义如下:

1

int extract ( array $var_array [, int $extract_type [, string $prefix ]] )

其中,第二个参数指定函数将变量导出到符号表时的行为。 两个最常见的值是EXTR_OVERWRITE和EXTR_SKIP。

当值为EXTR_OVERWRITE时,在导出变量到符号表的过程中,如果变量名冲突,所有变量都会被覆盖; 值为EXTR_SKIP,表示跳过,不覆盖。 如果不指定第二个参数,则默认使用EXTR_OVERWRITE。

当extract()函数从用户控制的链表导入变量且第二个参数未设置或设置为EXTR_OVERWRITE时,存在变量覆盖漏洞:

1
2
3
4
5
6
7
8
9


上面的例子以GET为例:

防御方法:调用extract()时使用EXTR_SKIP,确保现有变量不会被覆盖

1

extract($_GET,EXTR_SKIP);

0x04parse_str()变量覆盖率

parse_str()函数一般用于解析URL中的查询字符串,并将查询字符串解析为变量。 如果没有数组参数,则该函数设置的变量将覆盖现有的同名变量。

函数定义如下:

1

void parse_str ( string $str [, array &$arr ])

当parse_str()函数的参数值可以由用户控制时,存在变量覆盖漏洞:

1
2
3
4
5
6
7
8
9
10


我们看一下子主题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17


是弱类型和变量重写的组合:

0x05mb_parse_str() 变量覆盖

mb_parse_str()函数用于解析GET/POST/COOKIE数据并设置全局变量,与parse_str()类似:

1
2
3
4
5
6
7
8
9
10


0x06import_request_variables()变量覆盖率

支持版本:PHP4>=4.1.0、PHP5<5.4.0

import_request_variables()函数将GET、POST、Cookies中的变量导出到全局。

函数定义如下:

1

bool import_request_variables (string $types [, string $prefix])

$type代表要注册的变量,G代表GETphp变量类型,P代表POST,C代表COOKIE,第二个参数是要注册的变量的前缀。

使用该函数只需指定类型即可,这里G指定导出GET请求中的变量:

1
2
3
4
5
6
7
8
9
10


0x07$$引起的变量覆盖

$$ 是一个可变变量。 可变变量获取普通变量的值作为可变变量的变量名。

$ 和 $​$ 之间的区别

$var 是普通变量,名称为:var,存储任意值,如:字符串、整数、浮点数等。

$$var 是一个引用变量,用于存储$var 的值。

看看演示:

1
2
3
4
5
6
7
8
9
10
11

<?php  
	$x = "mi1k7ea";
	$$x = 666;
	echo $x."
"; echo $$x."
"; echo $mi1k7ea; //也可以写到双引号中解析,输出结果一样 // echo "$x
"; // echo "${$x}
"; // echo "$mi1k7ea"; ?>

变量覆盖漏洞

$$导致的变量覆盖问题在CTF代码审核题目中经常出现在foreach中,比如下面的示例代码,使用foreach遍历链表中的值,然后将得到的链表键值作为变量,链表中的通配符作为变量的值。 因此,形成了可变覆盖漏洞。 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

$_value)  
    {
        $$_key=  $_value;
    }
}
$id = isset($id) ? $id : "test";
if($id === "mi1k7ea") {
    echo "flag{xxxxxxxxxx}";
} else {
	echo "Nothing...";
}
?>

这里可以通过GET、POST或者COOKIE来触发。 传入id=mi1k7ea后,foreach语句中$_key为id,$_value为mi1k7ea,因此$$_key为$id,实现了变量覆盖:

CTF主题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

 $value){
	$$key = $$value;
}
foreach ($_POST as $key => $value){
	$$key = $value;
}
if ( $_POST["flag"] !== $flag )	{
	die($_403);
} else {
	echo "This is your flag : ". $flag . "n";
	die($_200);
}
?>

可以看到,有3个if语句和2个foreach语句。

if语句中,第一个要求你通过POST方法发出请求,第二个需要POST一个flag参数,第三个是比较flag参数是否等于包含的真实flag。

foreach语句中,第一个是用变量覆盖GET的参数,第二个是用变量覆盖POST的参数,不过这两个语句的处理有点不同,就是一个名为的key $$value 另一个是$value。

这里总结一下思路:由于POST的参数必须是flag,所以第二个foreach语句的$key就是flag,所以$$key就是$flag,所以$flag的值就是flag参数通过 POST 值传递; 这里因为第二个foreach语句将$flag的原始值改为POST传递的flag参数的值,所以最后一个if语句的条件始终不成立,在后续的else代码块逻辑中echo输出只能为改变后的$flag值,即POST传递过来的flag参数的值代替原来的$flag值,然后输出$_200变量的值; 如果要输出原来的$flag值,我们需要将原来的$flag覆盖到$_200变量中,所以在第一个foreach语句中,通过GET输入_200=flag,这样得到的$$key是 $_200,$$value 是 $flag,因此实现在更改 $flag 的值之前将其覆盖到 $_200 变量。

验证一下:

parse_str() 变量覆盖

voidparse_str(字符串$encoded_string[,数组&$结果])

• $encoded_string 输入的字符串

•$result 变量将作为链接列表元素存储在此字段中

导入请求变量()

(PHP4>=4.1.0,PHP5<5.4.0)

import_request_variables - 将 GET/POST/Cookie 变量导出到全局范围

boolimport_request_variables(字符串$类型[,字符串$前缀])

• $type 指定需要导出的变量。 字母“G”、“P”和“C”分别可以用来表示 GET、POST 和 Cookie

• $prefix 变量名前缀

使固定

• 在 php.ini 文件中设置 register_globals=OFF

• 使用原有变量字段,如$_POST、$_GET等字段变量进行操作

• 不要使用foreach 语句来遍历$_GET 变量,而是使用[(index)] 来指定

•验证变量是否存在,在注册变量之前判断变量是否存在

序列化漏洞

序列化和反序列化

•序列化:将对象转换为字节序列的过程称为对象的序列化

• 反序列化:将字节序列恢复为对象的过程称为对象的反序列化

漏洞驱动:

反序列化对象有魔法,但是魔法里面的代码是可以控制的,

漏洞根据不同的代码可以引发多种攻击,如代码注入、SQL注入、目录遍历等

日历等

序列化的不同结果

• 民众

• 私人的

• 保护

漏洞性质:

• unserialize函数的变量是可控的

• php文件中有可用的类,并且类中有魔术

魔术技巧:

__construct(),__destruct()

__call(),__callStatic()

__get(),__set()

__isset(),__unset()

__睡眠(),__唤醒()

__toString()

__调用()

__set_state()

__克隆()

__调试信息()

漏洞案例

根据不同的代码可以造成多种类型的攻击,如代码注入、SQL注入、目录遍历等。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 php php变量类型-PHP代码审计-变量覆盖漏洞 https://www.wkzy.net/game/144856.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务