PHP索引数组+unset使用不当导致的问题

转自先知社区 https://xz.aliyun.com/t/2443

0x00前言

通常网站后台可以配置允许上传附件的文件类型,一般登录后台,添加php类型即可上传php文件getshell。但是,随着开发者安全意识的提高,开发者可能会在代码层面强制限制php等特定文件类型的上传,有时会使用unset函数销毁删除允许上传文件类型的索引数组,如:Array(‘gif‘,‘jpg‘,‘jpeg‘,‘bmp‘,‘png‘,‘php‘),不过错误地使用unset函数并不能到达过滤限制的效果。

0x01问题详情

问题描述:

最近在审计某CMS代码过程中,发现后台限制文件上传类型的代码如下:

$ext_limit = $ext_limit != ‘‘ ? parse_attr($ext_limit) : ‘‘;
foreach ([‘php‘, ‘html‘, ‘htm‘, ‘js‘] as $vo) {
    unset($ext_limit[$vo]);
}

其目的是实现:获取配置中的允许上传文件类型$ext_limit并转换为数组,无论后台是否添加了php等类型文件,均强制从允许上传文件类型的数组中删除php,html,htm,js等类型。

但是由于unset函数使用不当,导致其代码无法达到该目的。具体地,执行如下代码:

$ext_limit =  Array(‘gif‘,‘jpg‘,‘jpeg‘,‘bmp‘,‘png‘,‘php‘);
var_dump($ext_limit);
foreach ([‘php‘, ‘html‘, ‘htm‘, ‘js‘] as $vo) {
    unset($ext_limit[$vo]);
}
var_dump($ext_limit);

得到输出为如下,可以看到php并没有被删除

D:\wamp\www\test.php:15:
array (size=6)
  0 => string ‘gif‘ (length=3)
  1 => string ‘jpg‘ (length=3)
  2 => string ‘jpeg‘ (length=4)
  3 => string ‘bmp‘ (length=3)
  4 => string ‘png‘ (length=3)
  5 => string ‘php‘ (length=3)

D:\wamp\www\test.php:19:
array (size=6)
  0 => string ‘gif‘ (length=3)
  1 => string ‘jpg‘ (length=3)
  2 => string ‘jpeg‘ (length=4)
  3 => string ‘bmp‘ (length=3)
  4 => string ‘png‘ (length=3)
  5 => string ‘php‘ (length=3)

问题分析:

unset函数的使用说明可以参考php官网,简单理解就是:unset可以销毁掉一个变量;或者根据传入的key值,销毁数组类型中指定的键值对。
针对PHP 索引数组,调用unset时必须调用其对应的数字索引才能销毁指定的键值对。所以如果传入unset函数的参数不是索引,而是其值的情况(如此处unset(‘php‘)),无法销毁删除对应为php的键值对。

0x03修复办法

修改以上存在缺陷的代码为如下,主要是枚举索引数组为key=>value的形式,根据value进行比较,满足条件时将对应的key传入unset函数,从而销毁删除。

$ext_limit =  Array(‘gif‘,‘jpg‘,‘jpeg‘,‘bmp‘,‘png‘,‘php‘);
var_dump($ext_limit);
foreach ([‘php‘, ‘html‘, ‘htm‘, ‘js‘] as $vo) {
    foreach($ext_limit as $key=>$value){
        if($value===$vo){
            unset($ext_limit[$key]);
        }
    }
}
var_dump($ext_limit);

输出结果如下(php对应的键值对已被删除):

D:\wamp\www\test.php:15:
array (size=6)
  0 => string ‘gif‘ (length=3)
  1 => string ‘jpg‘ (length=3)
  2 => string ‘jpeg‘ (length=4)
  3 => string ‘bmp‘ (length=3)
  4 => string ‘png‘ (length=3)
  5 => string ‘php‘ (length=3)

D:\wamp\www\test.php:23:
array (size=5)
  0 => string ‘gif‘ (length=3)
  1 => string ‘jpg‘ (length=3)
  2 => string ‘jpeg‘ (length=4)
  3 => string ‘bmp‘ (length=3)
  4 => string ‘png‘ (length=3)

0x04小结

使用索引数组时,如果要使用unset销毁删除指定的键值对,切记采用枚举索引数组为key=>value的形式,根据value进行比较,满足条件时将对应的key传入unset函数

ps:安全问题的分析与挖掘就是一个开发者与hacker攻防较量的过程,对抗的点就是哪一方考虑的更加周全。

原文地址:https://www.cnblogs.com/test404/p/9335876.html

时间: 2024-08-03 06:08:31

PHP索引数组+unset使用不当导致的问题的相关文章

unset()索引数组

$arr = ['0'=>['aa'],'1'=>['c'],'2'=>['bb','cc']]; unset($arr['1']); echo '<pre>'; print_r($arr); echo PHP_EOL; print_r(array_values($arr)); Array ( [0] => Array ( [0] => aa ) [2] => Array ( [0] => bb [1] => cc ) ) Array ( [0]

类中属性返回形式(对象,关联数组,索引数组)

class A { public $x, $y; function __construct($x, $y)  { $this->x = $x; $this->y = $y; } function get_value($arr = true)  { if($arr == 'arr')   { // 类中属性以关联数组形式转换返回 return get_object_vars($this); }else if($arr == 'obj')   { //类中属性以对象形式返回 return $thi

CCLuaObjcBridge调Objective-C方法传索引数组报invalid key to &amp;#39;next&amp;#39;错调试

CCLuaObjcBridge是cocos2d-x系列引擎与Objective-C进行交互的"桥梁",老廖的quick-cocos2d-x在其framework进行了简单了封装,封装到了luaoc类中,大体能够看成: luaoc.callStaticMethod = CCLuaObjcBridge.callStaticMethod 函数原型例如以下: --[[ 调用Objective-C中的静态方法 @param string className 类名 @param string me

Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析

原文:Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析 前段时间,公司同事开发了一个小工具,在工具执行过程中,UI界面一直处于卡死状态. 通过阅读代码发现,主要是由于Dispatcher.BeginInvoke()方法使用不当导致的. 本文将通过一个WPF模拟程序来演示一下界面卡死的现象,并通过修改代码来解决界面卡死的问题. 希望通过对本文的学习,大家能对Dispatcher.BeginInvoke()方法有一个新的认识. 文章开篇直接给出界面卡死的示例代码

Java 语法 索引 ----- 数组(Arrays)

数组声明,分配, 赋值 int y[] = new int[3]; y[0] = 1; y[1] = 2; y[2] = 3; int[] x = new int[] {1,2,3}; int[] x = {1,2,3}; 二维数组 String[][] x = {{"00","01"},{"10","11"}}; String[][] y = new String[2][2]; y[0][0] = "00"

array_merge和array_values重排索引数组性能比较

###?array_merge?合并一个或多个数组 array?**array_merge**?(?array?`$array1`?[,?array?`$...`?]?) 将一个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面.返回作为结果的数组. -?如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值.然而,如果数组包含数字键名,后面的值将_不会_覆盖原来的值,而是附加到后面.-?如果只给了一个数组并且该数组是数字索引的,则键名会以连续方式重新索引. ###?ar

JS 索引数组、关联数组和静态数组、动态数组

1 JS 索引数组.关联数组和静态数组.动态数组 2 3 数组分类: 4 5 1.从数组的下标分为索引数组.关联数组 6 7 var ary1 = [1,3,5,8]; 8 //按索引去取数组元素,从0开始(当然某些语言实现从1开始) 9 //索引实际上就是序数,一个整型数字 10 alert(ary1[0]); 11 alert(ary1[1]); 12 alert(ary1[2]); 13 alert(ary1[3]); 14 15 16 var ary2 = {}; 17 //存取时,以非

php关联数组和索引数组差别

没有查到明确的php中定义关联数组/索引数组的解析,根据phpdocument及百度的一些资料和实际的代码测试,对关联数组/索引数据进行定义解析.这个问题主要在和手机端ios app产品提供api时遇到,用关联数组转换为json能更好的用oc解析转换为数组. 关联数组:没有明确的索引键,默认从0开始作为索引键. $temp_arr = array ( '已经在别处买到', '商品不符合需求', '价格太高', '不想买了', '卖家没有交易记录', '其他原因', ); $temp_arr[0]

【tp5】索引数组转成关联数组 ( $a=[],转换成 $a[&#39;aa&#39;=&gt;2,&#39;bb&#39;=&gt;&#39;3c&#39;] )

概念: 索引数组 ==== >>>$arr = []; 关联数组 ====>>> $arr = [ 'orange'=>1,'apple'=>'good'  ]; 1.在tp5之前的tp3.2,我们知道索引数组转关联数组,是直接可以转成功的,因为php是弱语言类型. 2.在tp5之后,索引数组不能直接转关联数组,必要通过isset进行判断,然后才能给转成关联数组. 否则,tp5会报错: 未定义数组索引: aa 如何避免这个错误呢? 可以isset进行判断['