代码审计--变量覆盖

漏洞原理

变量覆盖(Dynamic Variable Evaluation) 是指变量未被初始化,

而我们自定义的变量可以替换程序原有的变量值。


相关函数

$$ , extract , parse_str , import_request_variables 等等

这里涉及到一个安全函数: register_globals

register_globals 的意思就是注册为全局变量,

当为 On 的时候,传递过来的值会被直接注册为全局变量直接使用,

当为 Off 的时候,则需要到特定的数组里去得到它。

注:此选项已经被 PHP5.3.0 起废弃,并将自 PHP 5.4.0 起移除


1. $$可变变量

双 $$ 这种写法称为可变变量,

为了更好的理解,举个例子:


<?php

 $a = "hello";
 echo "$a".'<hr>';   // 输出 hello
 $a = "world";
 echo "$a".'<hr>';   // 输出 world
 echo "$$a".'<hr>';  // 输出 $world

?>

解释:一个可变变量($$a)获取了一个普通变量($a)的值(world)作为这个可变变量的变量名($world) 。


再来一个常见的例子


<?php


foreach ($_GET as $key => $value) {
  $$key = $value;
  echo $$key.'<hr>';
}

?>

这里的意思是变量GET的内容,然后把值($value) 当作 $$key 的变量名,

当我们输入 flag=aaa 的时候,来看看结果

这个时候 $$key 把 值(flag) 当作变量名来使用了。

images


再看个ctf题


<?php
   include "flag.php";   // 包含并运行指定文件

   $_403 = "Access Denied";  // 设置初始变量

   $_200 = "Welcome Admin";

   if ($_SERVER["REQUEST_METHOD"] != "POST")   // 返回post的值
   {
         die("BugsBunnyCTF is here :p...");
   }
   if ( !isset($_POST["flag"]) )   // 检查是否设置,没有设置直接pass
   {
         die($_403);
   }
   foreach ($_GET as $key => $value)  // 遍历 GET数据
   {
         $$key = $$value;
   }
   foreach ($_POST as $key => $value)  // 遍历 POST数据
   {
         $$key = $value;
   }
   if ( $_POST["flag"] !== $flag )
   {
         die($_403);
   }
   echo "This is your flag : ". $flag . "\n";
   die($_200);
?>

die() 函数输出一条消息,并退出当前脚本。

REQUEST_METHOD 函数 ,超全局变量,可以接收 GETPOSTCOOKIE的值

来分析下代码,

要满足三个if条件才能访问到flag

第一个if判断有没有POST数据传递过来,

第二个if判断传递过来的POST数据有没有参数flag

第三个if判断POST参数flag的值是不是等于$flag变量的值,

如果不是很熟悉代码的话,这三个if判断估计会有点懵逼,

我们先一步一步来测试吧。


首先从这段代码开始

第一个遍历语句


foreach ($_GET as $key => $value){  // 遍历 POST数据
  $$key = $$value;
}

value 的意思是 把键和值分别当作变量名来使用,

因为两个都是可变变量,所有不存在谁使用谁的值,

我们GET输入 flag=aaa 看看结果,

经过 $$key = $$value 处理后讲会变成了 $flag = $aaa

images


再来看第二个遍历语句


foreach ($_POST as $key => $value){  // 遍历 GET数据
  $$key = $value;
}

当输入 flag=aaa 时 ,将会变成 $flag=aaa

images


既然我们知道了这些条件,那么将如何构造payload呢???

经过上面分析,我们知道必须要满足 $_POST["flag"] !== $flag ,

那么也就是说,$_GE 的 value值 要等于 $_POST 的 key值

同事 $_POST 不能为空

images


2. extract()函数

介绍:
extract() 函数从数组中将变量导入到当前的符号表。

该函数使用数组键名作为变量名,使用数组键值作为变量值。

语法:extract(array,extract_rules,prefix)

extract_rules 可能值:

  1. EXTR_OVERWRITE -     默认。如果有冲突,则覆盖已有的变量。
  2. EXTR_SKIP -     如果有冲突,不覆盖已有的变量。
  3. EXTR_PREFIX_SAME -     如果有冲突,在变量名前加上前缀 prefix。
  4. EXTR_PREFIX_ALL -     给所有变量名加上前缀 prefix。
  5. EXTR_PREFIX_INVALID -     仅在不合法或数字变量名前加上前缀 prefix。
  6. EXTR_IF_EXISTS -     仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。
  7. EXTR_PREFIX_IF_EXISTS -    仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。
  8. EXTR_REFS -     将变量作为引用提取。导入的变量仍然引用了数组参数的值。

从以上说明我们可以看到第一个参数是必须的,

会不会导致变量覆盖漏洞由第二个参数决定,

该函数有三种情况会导致变量覆盖,

第一种:当第二个参数为 EXTR_OVERWRITE 时,他表示如果有冲突,则覆盖已有的变量,

第二种:当只传入第一个参数,这个时候默认为 EXTR_OVERWRITE模式,

第三种:当第二个参数为 EXTR_PREFIX_IF_EXISTS,它表示仅在当前符号表中已有的同名变量时,覆盖他们的值


举个粟子


<?php

$a = 1;    // 初始值为1
$b = array('a' => '2');
extract($b);    // 经过extract()函数对$b处理后
echo $a;    //输出结果为2

?>

这种满足第一种情况,本来 $a已经有初始值了,

然后又将 a 的值指定为 2 , => 定义数组键对值,

当经过 extract()函数处理后,两个值就冲突了,

所以后面的值会覆盖掉前面的值


举个CTF粟子


<?php if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
    <?php
      extract($_POST);
      if ($pass == $thepassword_123) { ?>
        <div class="alert alert-success">
            <code><?php echo $theflag; ?></code>
        </div>
    <?php } ?>
<?php } 
?>

$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。

REQUEST_METHOD 访问页面使用的请求方法;例如,“GET”“HEAD”“POST”“PUT”

代码首先判断是不是POST提交,然后通过 extract()函数来处理POST参数,

如果 $pass == $thepassword_123 那么就输出flag

我们知道,这个函数判断变量有没有冲突,有冲突就覆盖,

那么我们可以让他不冲突,同时又满足了 $pass == $thepassword_123

那么payload就应该是这样子的: $pass=233&$thepassword_123=233


3. parse_str()函数

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

语法: parse_str(string,array)

参数:

  1. string   必需。规定要解析的字符串。
  2. array   可选。规定存储变量的数组的名称。该参数指示变量将被存储到数组中。

例:


<?php

  $b = 1;
  parse_str('b=2');
  echo $b;

?>

经过 parse_str() 函数处理后,注册的变量会放到这个数组里面,

如果这个数组原来就存在相同的键(key) ,也就是 b 的时候,

则会覆盖掉原有的键值(value) , 然后输出 2


来看道题


<?php
  error_reporting(0);
  if(empty($_GET['id'])) {     // empty()检查是否为空
    show_source(__FILE__);     // highlight_file 代码高亮
    die();                     // 等同于exit 输出一个消息并且退出当前脚本
} else {
  include ('flag.php');
  $a = "www.OPENCTF.com";
  $id = $_GET['id'];
  @parse_str($id);
  if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('NKCDZO')) {
    echo $flag;
  } else {
    exit('其实很简单其实并不难!');
  }
}

?>

首先检查GET参数id是否为空,如果为空直接退出当前脚本 ,

给 $a 设置初始值,用变量$id来接收GET的数据 ,

然后使用 parse_str()函数来处理 $id ,

然后再判断 $a[0] 不能等于 QNKCDZO ,并且要求 md5加密后的 $a[0] 要等于 md5加密后的 NKCDZO

我们知道 PHP在处理哈希字符串时,会利用 "!=" 或 "==" 来对哈希值进行比较,

它把每一个以 "0E" 开头的哈希值都解释为0,

所以如果两个不同的密码经过哈希以后,其哈希值都是以 "0E" 开头的,

那么PHP将会认为他们相同,都是 0 。

详情请参考:

https://www.freebuf.com/news/67007.html

然后我们发现,NKCDZO 经过 md5加密(16位) 后是以 0e 开头,

所以只要 a[0] 的值加密之后能以 0e 开头,条件就成立,

然后payload:

?id=a[0]=s1836677006a

或者

?id=a[0]=240610708

s1836677006a md5加密(32位),也是以 0e 开头,

$a已经有初始值了,所以当我们输入payload后,就会替换掉原来的 $a的值,

最后 0=0 条件成立


4. import_request_variables()函数

mport_request_variables()函数就是把GETPOSTCOOKIE的参数注册成变量,

register_globals被禁止的时候使用

语法: bool import_request_variables ( string $types [, string $prefix ] )

例:


<?php 

  $b = 1;
  import_request_variables('GP');
  echo $b;

?>

其中 G表示 GET , P表示POST ,C表示 COOKIE

当我们输入 ?b=2 的时候,

$b 的值 1 会被覆盖为 2


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/630303.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嬴政只比刘邦大三岁,项羽竟是比刘邦小24岁的小老弟?

大秦始皇帝祖龙嬴政、汉太祖高皇帝刘邦、西楚霸王项羽他们的出生顺序怎样&#xff1f; 细看正史我们就知道&#xff0c;项羽嬴政刘邦这三个人&#xff0c;说他们是兄弟可以&#xff0c;说他们有代差也不错&#xff1a;公元前259年&#xff0c;秦始皇降生&#xff0c;三年后的…

Blender 导入资源包的例子

先到清华源下载资源包&#xff1a; Index of /blender/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 具体地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/blender/demo/asset-bundles/human-base-meshes/human-base-meshes-bundle-v1.1.0.zip 解压/hum…

【数据结构】C++语言实现二叉树的介绍及堆的实现(详细解读)

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

【Leetcode每日一题】 动态规划 - 简单多状态 dp 问题 - 删除并获得点数(难度⭐⭐)(76)

1. 题目解析 题目链接&#xff1a;LCR 091. 粉刷房子 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 1. 状态定义 在解决这类问题时&#xff0c;我们首先需要根据题目的具体要求来定义状态。针对房屋粉刷问题&#…

malloc_consolidate

此文章用于详细介绍malloc_consolidate。 众所周知&#xff0c;fastbin一般是不能合并&#xff0c;但在malloc_consolidate中是个例外。 1.触发机制 首先构造这样的堆块结构 一个0x40的堆块在fastbin中&#xff0c;一个0x110的堆块在unbin中 随后我们尝试分配一个0x300的堆…

智能BI(后端)-- 系统异步化

文章目录 系统问题分析什么是异步化&#xff1f;业务流程分析标准异步化的业务流程系统业务流程 线程池为什么需要线程池&#xff1f;线程池两种实现方式线程池的参数线程池的开发 项目异步化改造 系统问题分析 问题场景&#xff1a;调用的服务能力有限&#xff0c;或者接口的…

strcpy函数详解

strcpy函数详解 1.函数简介2.strcpy函数的使用2.1使用方法一2.1使用方法二 3.strcpy在使用过程中的注意事项3.1被复制字符必须以\0结尾3.2目标空间必须能够大于源字符串长度3.3目标空间必须可变 1.函数简介 strcpy函数包含在<string.h>库函数中&#xff0c;是将一个字符…

共享文件夹(以及问题解决方法)

目录 文件夹共享 第一步&#xff0c;将文件夹共享 第二步&#xff0c;设置用户权限 第三步&#xff0c;打开网络发现 第四步&#xff0c;访问 网络中没有设备问题 控制面板&#xff0c;启动 重启 还是不行&#xff1f;计算机管理&#xff0c;启动 FDResPub服务&#x…

波搜索算法(WSA)-2024年SCI新算法-公式原理详解与性能测评 Matlab代码免费获取

​ 声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、初始化阶段 二、全…

JumpServer堡垒机应用(v3.10.8) 下

目录 JumpServer堡垒机简单式部署与管理(v3.10.8) 上-CSDN博客 一. 资产管理 1.1创建资产 1.2 给资产主机创建用户 1.2.1 普通账户&#xff1a; 1.2.2 特权账户&#xff1a; 1.2.3 创建用户 二. 命令过滤 2.1 创建命令组 2.2 创建命令过滤 ​编辑 三. 创建资产授权 …

大模型算法(一):从Transformer到ViT再到LLaMA

单任务/单领域模型 深度学习最早的研究集中在针对单个领域或者单个任务设计相应的模型。 对于CV计算机视觉领域&#xff0c;最常用的模型是CNN卷积模型。其中针对计算机视觉中的不同具体任务例如分类任务&#xff0c;目标检测任务&#xff0c;图像分割任务&#xff0c;以CNN作…

Linux的常用指令 和 基础知识穿插巩固(巩固知识必看)

目录 前言 ls ls 扩展知识 ls -l ls -a ls -al cd cd 目录名 cd .. cd ~ cd - pwd 扩展知识 路径 / cp [选项] “源文件名” “目标文件名” mv [选项] “源文件名” “目标文件名” rm 作用 用法 ./"可执行程序名" mkdir rmdir touch m…

Springboot+Vue项目-基于Java+MySQL的制造装备物联及生产管理ERP系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Leetcode—3146. 两个字符串的排列差【简单】

2024每日刷题&#xff08;135&#xff09; Leetcode—3146. 两个字符串的排列差 实现代码 class Solution { public:int findPermutationDifference(string s, string t) {int maps[26];int mapt[26];for(int i 0; i < s.size(); i) {int idxs s[i] - a;int idxt t[i] …

案例|200多套设备实时监测,守护江西彰湖水库安全

中型水库作为水利建设的重要组成部分&#xff0c;在防洪、供水、农业灌溉、改善民生和生态效益等方面都具有重要意义。国务院发布《关于切实加强水库除险加固和运行管护工作的通知》&#xff0c;重点提出要提升信息化管理能力&#xff0c;要加快建设水库雨水情测报、大坝安全监…

判断上三角矩阵 分数 15

题目展示&#xff1a; 代码展示&#xff1a; 点这里&#xff0c;输入题目名称即可检索更多题目答案 ​#include<stdio.h>int main() {//T-tint t 0;scanf("%d",&t);while(t--)//循环t次&#xff0c;处理t个矩阵{int n 0;scanf("%d",&n);…

C语言学习【printf函数和scanf函数】

C语言学习【printf函数和scanf函数】 printf()函数和scanf()函数可以让用户与程序交流&#xff0c;是输入/输出函数 printf()函数 请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如&#xff0c;打印整数时使用%d&#xff0c;打印字符时使用%c。这些符号被称…

字符串_字符函数和字符串函数

C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。 字符串常量适用于那些对它不做修改的字符串函数。 目录 1.函数介绍 1.1strlen 1.1.1strlen函数的模拟实现 1.2strcpy 1.2.1st…

性能测试学习二

瓶颈的精准判断 TPS曲线 tps图 响应时间图 拐点在哪里呢? 这是一个阶梯式增加的场景,拐点在第二个压力阶梯上就出现了,因为响应时间增加了,tps增加的却不多,在第三个阶段时,tps增加的就更少了,响应时间也在不断增加,所以性能瓶颈在加剧,越往后越明显【tps的增长,…

【35分钟掌握金融风控策略29】贷中模型调额调价策略

目录 贷中客户风险管理和客户运营体系 用信审批策略 用信审批策略决策流与策略类型 贷中预警策略 对存量客户进行风险评级 基于客户的风险评级为客户匹配相应的风险缓释措施和建议 调额策略 基于定额策略的调额策略 基于客户在贷中的风险表现的调额策略 调价策略 存…