首页 > 编程语言 >【PHP系列】变量覆盖

【PHP系列】变量覆盖

时间:2024-08-03 17:21:58浏览次数:17  
标签:变量 覆盖 globals PHP extract id

环境搭建工具

PHPStudy
PHP 7.3.4

审计策略
变量覆盖

一、$$ 变量覆盖
    1.1 $$ 简介
    1.2 漏洞产生

二、extract()变量覆盖
    2.1 extract()
    2.2 漏洞产生

三、parse_str()变量覆盖
    3.1 parse_str()
    3.2 漏洞产生

四、register_globals变量覆盖
    4.1 register_globals
    4.2 漏洞产生

五、import_request_variables()变量覆盖
    5.1 import_request_variables
    5.2 漏洞产生

审计策略

全局搜索与变量覆盖相关的函数并对参数进行溯源,判断参数是否可控

变量覆盖

变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击。

经常导致变量覆盖的漏洞场景有:

$$

extract()函数

parse_str()函数

register_globals开启了全局变量注册

import_request_variables()使用不当

一、$$变量覆盖

1.1 $$简介

"$$"在PHP中用于定义可变变量,可变变量主要用于获取了一个普通变量的值并将该值作为这个可变变量的变量名,例如:

<?php
  $a='aaa';      
  $aaa='123';
  echo $$a;     //$$a=$($a)=$(aaa)='123'
?>

运行之后的结果如下:

123

1.2 漏洞产生

常见的一些以遍历的方式释放变量的代码可能会导致变量覆盖,例如:

803.php

<?php
$id =5;
foreach (array('_COOKIE','_POST','_GET') as $_request)  
{
    foreach ($$_request as $_key=>$_value)  
    {
        $$_key=  $_value;
    }
}
if($id == 1) {
    echo "flag{Welcome_to_FLy!}";
  die();
}
?>

上面的代码会判断用户的请求方式GET、POST、Cookie,之后将请求的参数作为$key,值作为$value,此时如果我们构造“id=1”那么,此时的$key即为id,$value即为1,而此时的$$key就等价于$id,之后在L7的赋值等价于$id=1,从而实现对原有变量$id的覆盖,从下面的运行实例可以看到成功实现了对变量id的覆盖并获取到了flag的值:

二、extract()变量覆盖

2.1 extract()

extract()函数用于将变量从数组中导入到当前符号表,该函数使用数组键名作为变量名,使用数组键值作为变量值,针对数组中的每个元素将在当前符号表中创建对应的一个变量,语法如下:

extract(array,extract_rules,prefix)

2.2 漏洞产生

extract的extract_rules默认值为EXTR_OVERWRITE--如果有冲突则覆盖已有的变量,如果使用不当则容易造成变量覆盖漏洞,例如:

803.php

<?php
  $id=5;  
  extract($_GET);
  if($id==1){
      echo "flag2{Welcome_to_Fly!}";
   }else{
        echo "Error!";
    }
?>

从以上代码可以看到我们要想获得flag,那么就必须要使得$id==1成立,而在开头已经声明了$id=5,那么怎么办呢❓
可以看到这里使用了extract函数,而且没有extract_rules即为默认覆盖已有变量,那么我们可以构造"?id=1"来访问该php文件,实现对参数id的覆盖并获取flag,具体如下:

三、parse_str()变量覆盖

3.1 parse_str()

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

语法:parse_str(string,array)

运行实例:

803.html

<!DOCTYPE html>
<html lang="en">

<body>
<?php
parse_str("name=Bill&age=60",$myArray);
print_r($myArray);
?>
</body>
</html>

3.2 漏洞产生

<?php
error_reporting(0);      //关闭错误报告
if(empty($_GET['id'])){
  show_source(__FILE__);  //显示文件
  die();
}else{
  include('flag.php');
  $a="www.OPENCTF.com";
  $id=$_GET['id'];
  @parse_str($id);//把查询字符串解析到变量中,没有使用array选项,若有同名变量,将原来的覆盖。这里明显可以将原来的$a的值给覆盖掉。
  if($a[0]!='QNKCDZO'&&md5($a[0])==md5('QNKCDZO')){
    //判断$a[0]的值不是QNKCDZO并且$a[0]的MD5值要和QNKCDZO的MD5值相同,很难找出这样的字符串。
        echo $flag;
  }else{
    exit('其实很简单,其实并不难');
  }
}

这里最重要的就是处理下面的这个问题:

if($a[0]!='QNKCDZO'&&md5($a[0])==md5('QNKCDZO')),我们要找到一个字符串值和QNKCDZO不同,但是字符串的MD5值和QNKCDZO的MD5值相同。

这里可以利用PHP处理0e开头的MD5哈希字符串的漏洞:PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,这样的话两个不同字符串也就可以相等了。这里的"QNKCDZO"经MD5加密后的值是0e830400451993494058024219903391,下面构造以下payload:?id=a[]=s1836677006a

PS:以0e开头的MD5可以参考

https://blog.csdn.net/Fly_hps/article/details/104702138

四、register_globals变量覆盖

4.1 register_globals

register_globals是php.ini里的一个配置,这个配置影响到php如何接收传递过来的参数,当register_globals的值为On的时候,传递过来的值会被直接的注册为全局变量直接使用,而Off的时候我们需要到特定的数组里去得到它

4.2 漏洞产生

代码示例:

<?php
echo "Register_globals: ".(int)ini_get("register_globals")."<br/>";

if ($auth){
   echo "private!";
}
?>

当register_globals=OFF时,这段代码不会出问题,但是当register_globals=ON时,构造请求?auth=1,变量$auth将自动得到赋值,得到的结果为 Register_globals:1 private!:

我的:

PS:从 PHP » 4.2.0 版开始配置文件中 PHP 指令 register_globals 的默认值从 on 改为 off 了,自 PHP 5.3.0 起废弃,并将自PHP 5.4.0起移除。

五、import_request_variables()变量覆盖

5.1 import_request_variables

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

语法格式:

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

参数说明:

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

$prefix:变量名的前缀,置于所有被导入到全局作用域的变量之前。所以如果你有个名为 userid 的 GET 变量,同时提供了 pref_ 作为前缀,那么你将获得一个名为 $pref_userid 的全局变量。虽然 prefix 参数是可选的,但如果不指定前缀,或者指定一个空字符串作为前缀,你将获得一个 E_NOTICE 级别的错误

5.2 漏洞产生

代码示例1:

<?php
  $get_id=0;
  import_request_variables("g", "get_");
  echo $get_id;
?>

如上代码所示,如果我们构造一个?id=1,那么将会将导入一个$get_id的全局变量,从而覆盖之前的$_get_id的值,程序运行结果如下:

代码示例2:

<?php  
    $auth = '0';  
    import_request_variables('G');  
      
    if($auth == 1){  
      echo "private!";  
    }else{  
      echo "public!";  
    }  
?>

以上代码,如果构造?auth=1,那么将会输出private!,运行结果如下:

PS:该函数在最新版本的PHP中已经不支持了,目前可用版本范围为:PHP 4 >= 4.1.0 PHP 5 < 5.4.0

标签:变量,覆盖,globals,PHP,extract,id
From: https://www.cnblogs.com/o-O-oO/p/18340600

相关文章

  • 【Java基础】02变量和数据类型
    变量一个数据存储空间的表示不同数据存入具有不同内存地址的空间,相互独立,内存地址不好记,通过变量名可以简单快速地找到数据。变量命名规则包含数字、字母、下划线、$不能以数字开头,不能是纯数字英文命名,要有意义帕斯克命名法(驼峰命名法)大骆驼:HelloWorld首字母大写,一般......
  • 【PHP系列】PHP反序列化--字符逃逸
    概念了解字符逃逸前需要的补充知识点一知识点二字符逃逸—字符增加字符逃逸—字符减少概念在学PHP字符串逃逸之前先了解一下原理是什么,字符串逃逸的原理其实就是让字符串变成可以执行的序列化代码。在序列化和反序列化这个中间过程中,序列化字符增加或减少后,再去反序列化......
  • 单个或两个及以上java安装与环境变量配置
    目录java下载地址:1.安装java1.1安装程序1.2选择安装路径1.3等待安装2.首先,进入环境变量2.1找到设置(第一个win11,第二个win10)2.2进入到系统高级系统设置(第一个win11,第二个win10)2.3点击环境变量2.4新建与添加2.5添加CLASSPATH2.6添加JAVA_HOME2.7找到path,编辑......
  • 变量
    目录在Java语言中,所有的变量在使用前必须声明。局部变量(LocalVariables)实例变量(InstanceVariables)参数变量(Parameters)在Java语言中,所有的变量在使用前必须声明。声明变量的基本格式如下:typeidentifier[=value][,identifier[=value]];格式说明:type--数据类型。......
  • PHP8-快速脚本参考-全-
    PHP8快速脚本参考(全)原文:PHP8QuickScriptingReference协议:CCBY-NC-SA4.0一、使用PHP要开始用PHP开发,创建一个带有.php文件扩展名的纯文本文件,并在您选择的编辑器中打开它——例如,Notepad、jEdit、Dreamweaver、NetBeans或PHPEclipse。这个PHP文件可以包含任何......
  • 最小圆覆盖
    性质一:最小圆覆盖是唯一的证:若存在两个最小圆,如下显然所有点只能存在于两个圆的交集中,于是以中间那条实心蓝线为直径做一个圆,这个圆显然更小而且能够覆盖所有点性质二:若我们已经用最小覆盖圆覆盖了所有点,设这些点的点集为\(S\),现在我们新加入一个点\(p\),若\(p\)不在\(S\)的最......
  • 如何记录网页的链接并将其存储在变量中?
    基本上在我的项目中,我使用webbrowser打开一个网页,然后使用pyautogui在搜索栏中输入一些内容,这会打开一个新页面。我需要一个函数来查找新页面的链接并将其存储为变量,以便我可以拥有动态requests.get()函数。我希望我的解释有意义我不知道如何检索它并将其保存为变量,我......
  • 易优cms在phpstudy环境下,可以去除:/index.php?/guanyuwomen/ 中的index.php吗
    针对不同服务器、虚拟空间,运行PHP的环境也有所不同,目前主要分为:Nginx、apache、IIS以及其他服务器。下面分享如何去掉URL上的index.php字符,记得在管理后台清除缓存,对于一些ECS服务器可能要重启nginx等服务!【IIS服务器】可以移步,《iis怎么去掉index.php》【Nginx服务器】在......
  • c语言中的地址与指针的概念,及变量的指针和指向变量的指针变量
    C语言中的地址、指针、以及变量的指针与指向变量的指针变量。1.地址(Address)在C语言中,每个变量在内存中都有一个唯一的内存地址。这个地址是变量存储的位置的标识符。可以通过& 运算符来获取一个变量的地址。#include<stdio.h>intmain(){  intx=10;  ......
  • c语言结构体的概述,定义结构体变量类型的方法,结构体变量的引用,结构体变量的初始化,结构
    1.C语言结构体的概述在C语言中,结构体(struct)是一种复合数据类型,用于将不同类型的数据组合在一起。它可以包含基本数据类型(如int、float、char等)以及其他结构体。结构体非常适合表示具有多种属性的复杂数据,如学生信息(包含姓名、年龄、成绩等)或坐标点(包含x和y坐标)。结构......