变量覆盖

转自:FREEBUF.COM

0×00 背景

近期在研究学习变量覆盖漏洞的问题,于是就把之前学习的和近期看到的CTF题目中有关变量覆盖的题目结合下进一步研究。 

通常将可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞。经常导致变量覆盖漏洞场景有:$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。 

本篇收集了几个CTF中的题目作为例子,对$$,extract(),parse_str()的问题进行总结。

0×01 $$导致的变量覆盖问题

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,如以下的示例代码,使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。

1.<?php

2.//?name=test

3.//output:string(4) “name” string(4) “test” string(4) “test” test

4.$name=’thinking’;

5.foreach ($_GET as $key => $value)

6.    $$key = $value;

7.    var_dump($key);

8.    var_dump($value);

9.    var_dump($$key);

10.echo $name;

11.?>

CTF中$$导致的变量覆盖问题的例题1: 

题目源码:

1.<?php

2.include “flag.php”;

3.$_403 = “Access Denied”;

4.$_200 = “Welcome Admin”;

5.if ($_SERVER["REQUEST_METHOD"] != “POST”)

6.    die(“BugsBunnyCTF is here :p…”);

7.if ( !isset($_POST["flag"]) )

8.    die($_403);

9.foreach ($_GET as $key => $value)

10.    $$key = $$value;

11.foreach ($_POST as $key => $value)

12.    $$key = $value;

13.if ( $_POST["flag"] !== $flag )

14.    die($_403);

15.echo “This is your flag : “. $flag . “\n”;

16.die($_200);

17.?>

题目分析: 

源码包含了flag.php文件,并且需要满足3个if里的条件才能获取flag,题目中使用了两个foreach并且也使用了$$.两个foreach中对 $$key的处理是不一样的,满足条件后会将$flag里面的值打印出来,所以$flag是在flag.php文件文件中的。 

但是由于第7,11-14行间的代码会将$flag的值给覆盖掉了,所以需要先将$flag的值赋给$_200或$_403变量,然后利用die($_200)或 die($_403)将flag打印出来。

解题方法: 

由于第7,11-14行间的代码会将$flag的值给覆盖掉,所以只能利用第一个foreach先将$flag的值赋给$_200,然后利用die($_200)将原本的flag值打印出来。

最终PAYLOAD: 

本地复现,所以flag与原题不一样

GET DATA:?_200=flag 

POST DATA:flag=aaaaaaaaaaaaaaaaaaaaa

 01.png

0×02 extract()函数导致的变量覆盖问题

extract() 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。 

extract()的用法参考:http://www.runoob.com/php/func-array-extract.html

语法: extract(array,extract_rules,prefix)

02.png

CTF中extract()导致的变量覆盖问题的例题1: 

题目源码:

1.<?php

2.$flag = ‘xxx’;

3.extract($_GET);

4.if (isset($gift)) {

5.    $content = trim(file_get_contents($flag));

6.    if ($gift == $content) {

7.        echo ‘hctf{…}’;

8.    } else {

9.        echo ‘Oh..’;

10.    }

11.} 

12.?>

题目分析: 

题目使用了extract($_GET)接收了GET请求中的数据,并将键名和键值转换为变量名和变量的值,然后再进行两个if 的条件判断,所以可以使用GET提交参数和值,利用extract()对变量进行覆盖,从而满足各个条件。

解题方法: 

GET请求 ?flag=&gift=,extract()会将$flag和$gift的值覆盖了,将变量的值设置为空或者不存在的文件就满足$gift == $content。

最终PAYLOAD: 

GET DATA: ?flag=&gift=

CTF中extract()导致的变量覆盖问题的例题2: 

题目源码:

1.<?php if ($_SERVER["REQUEST_METHOD"] == “POST”) { ?>

2.      <?php

3.        extract($_POST);

4.        if ($pass == $thepassword_123) { ?>

5.            <div class=”alert alert-success”>

6.                <code><?php echo $theflag; ?></code>

7.            </div>

8.        <?php } ?>

9.    <?php } ?>

题目分析: 

题目要求使用POST提交数据,extract($_POST)会将POST的数据中的键名和键值转换为相应的变量名和变量值,利用这个覆盖$pass$thepassword_123变量的值,从而满足$pass == $thepassword_123这个条件。

解题方法: 

使用POST请求提交pass=&thepassword_123=, 然后extract()会将接收到的数据将$pass$thepassword_123变量的值覆盖为空,便满足条件了。

最终PAYLOAD: 

POST DATA:pass=&thepassword_123=

 

0×03 parse_str函数导致的变量覆盖问题

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

语法:parse_str(string,array)

003.png

parse_str() 用法参考:http://php.net/parse_str

CTF中parse_str()导致的变量覆盖问题的例题1: 

题目源码:

1.<?php

2.error_reporting(0);

3.if (empty($_GET['id'])) {

4.    show_source(__FILE__);

5.    die();

6.} else {

7.    include (‘flag.php’);

8.    $a = “www.OPENCTF.com”;

9.    $id = $_GET['id'];

10.    @parse_str($id);

11.    if ($a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)) {

12.        echo $flag;

13.    } else {

14.        exit(‘其实很简单其实并不难!’);

15.    }

16.}

17.?> 

题目分析: 

首先要求使用GET提交id参数,然后parse_str($id)对id参数的数据进行处理,再使用判断$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)的结果是否为真,为真就返回flag,md5(‘QNKCDZO’)的结果是0e830400451993494058024219903391由于此次要满足$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)所以要利用php弱语言特性,0e123会被当做科学计数法,0 * 10 x 123。所以需要找到一个字符串md5后的结果是0e开头后面都是数字的,如,240610708,s878926199a 

PHP处理0e开头md5哈希字符串缺陷/bug 参考:http://www.cnblogs.com/Primzahl/p/6018158.html

解题方法: 

使用GET请求id=a[0]=240610708,这样会将a[0]的值覆盖为240610708,然后经过md5后得到0e462097431906509019562988736854与md5(‘QNKCDZO’)的结果0e830400451993494058024219903391比较都是0 所以相等,满足条件,得打flag。

最终PAYLOAD: 

GET DATA: 

?id=a[0]=s878926199a 

or 

?id=a[0]=240610708

 

0×04 小总结

变量覆盖漏洞在PHP代码审计中会以比较隐晦的方式存在,所以需要更加仔细的阅读源码找出漏洞的点,在CTF里面经常是以比较直接方式展示,所以可以先通过学习CTF各种变量覆盖的题目,然后掌握后再去审计cms,这样可以更加通透的理解掌握和挖掘变量覆盖漏洞。

### 变量覆盖在网络安全中的概念与风险 变量覆盖是指攻击者通过修改程序运行时的变量值,从而改变程序的行为或逻辑。这种技术通常被用于漏洞利用中,尤其是在缓冲区溢出、格式化字符串漏洞等场景下。变量覆盖可能导致的安全风险包括但不限于程序行为异常、权限提升、代码执行等。 #### 1. 变量覆盖的技术实现 变量覆盖的实现通常依赖于程序内存布局的可预测性。以下是一些常见的实现方式: - **缓冲区溢出**:当程序未正确验证输入长度时,攻击者可以通过向缓冲区写入超出其容量的数据,覆盖相邻的变量或返回地址[^2]。 - **格式化字符串漏洞**:如果程序允许用户控制格式化字符串参数,则攻击者可以利用该漏洞读取或写入内存中的变量值[^4]。 - **堆喷射(Heap Spraying)**:攻击者通过分配大量可控数据到堆中,增加成功覆盖目标变量的概率[^2]。 #### 2. 变量覆盖的风险分析 变量覆盖可能带来的安全风险包括: - **程序崩溃**:变量被非法覆盖后,可能导致程序进入不可预期的状态,最终崩溃。 - **权限提升**:攻击者可能通过覆盖特定变量(如权限标志位),获得更高的系统权限。 - **任意代码执行**:通过覆盖函数指针或返回地址,攻击者可以劫持程序执行流程,进而运行恶意代码[^4]。 #### 3. 解决方法 为防止变量覆盖带来的风险,可以从以下几个方面入手: - **输入验证**:严格限制用户输入的长度和内容,避免缓冲区溢出等问题[^2]。 - **编译器防护**:使用现代编译器提供的保护机制,如栈保护(Stack Canaries)、地址空间布局随机化(ASLR)、数据执行保护(DEP)等。 - **安全编程实践**:遵循安全编码规范,例如使用安全性更高的字符串处理函数(如`strncpy`代替`strcpy`)[^2]。 - **定期漏洞扫描**:利用漏洞扫描工具(如Metasploit)检测系统中存在的潜在漏洞,并及时修复[^1]。 ```python # 示例:防止缓冲区溢出的输入验证 def safe_input(buffer, size): if len(buffer) > size: raise ValueError("Input exceeds buffer size") return buffer[:size] try: user_input = "A" * 100 # 模拟用户输入 safe_buffer = safe_input(user_input, 50) print("Safe input:", safe_buffer) except ValueError as e: print("Error:", e) ``` #### 4. 实际案例 在实际攻击中,变量覆盖常与其他技术结合使用。例如,黑客可能利用缓冲区溢出来覆盖返回地址,进而跳转至恶意代码区域执行攻击。此外,DNS劫持攻击也可能涉及变量覆盖,例如篡改DNS缓存中的IP地址映射[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值