转自先知社区 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攻防较量的过程,对抗的点就是哪一方考虑的更加周全。

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

  1. 关于PHP索引数组unset某key后json_encode相关问题踩坑记录

    <?php $a = [1,2,3]; var_dump(json_encode($a)); #string(7) "[1,2,3]" unset($a[0]); var_d ...

  2. Bash : 索引数组

    Bash 提供了两种类型的数组,分别是索引数组(indexed array)和关联数组(associative array).本文主要介绍索引数组的基本用法. 索引数组的基本特点 Bash 提供的数组 ...

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

    原文地址: http://www.tuicool.com/articles/F7reem http://blog.csdn.net/yl2isoft/article/details/11711833 ...

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

    JS 索引数组.关联数组和静态数组.动态数组 数组分类: 1.从数组的下标分为索引数组.关联数组 var ary1 = [1,3,5,8]; //按索引去取数组元素,从0开始(当然某些语言实现从1开始 ...

  5. SELinux配置不当导致vsftpd系统用户不能登陆

    1.测试是否是SELinux配置不当导致的: setenforce 0 再次登陆ftp,正常,说明是SELinux配置不当导致.还原配置 setenforce 1 2.查看配置: getsebool ...

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

    原文:Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析 前段时间,公司同事开发了一个小工具,在工具执行过程中,UI界面一直处于卡死状态. 通过阅读代码发现,主要是 ...

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

    CCLuaObjcBridge是cocos2d-x系列引擎与Objective-C进行交互的"桥梁",老廖的quick-cocos2d-x在其framework进行了简单了封装,封 ...

  8. numpy 数组索引数组

    在numpy中,数组除了可以被整数索引,还可以被数组索引. a[b]就是已数组b的元素为索引,读取数组a的值. 当被索引数组a是一维数组,b是一维或则多维数组时,结果维度维度与索引数组b相同. a = ...

  9. js 索引数组转JSON为空

    let a = [] a.a = 1 console.log(a) // [a: 1] console.log(JSON.stringify(a)) // [] 当然js根本没索引数组一说,这是php ...

随机推荐

  1. MySQL数据库实现分页查询的SQL语句写法!

    一:分页需求: 客户端通过传递start(页码),limit(每页显示的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n,但是该函数的用法和我们的 ...

  2. os x && linux 文件传输基础命令

    一.从服务器下载文件到本机 1.修改文件所属 由于只能下载文件所属为自己的文件,所以要做修改文件所属的操作. chown hudelei /opt/logs/tomcat/app/tomcat_stk ...

  3. MT【270】含参绝对值函数最大之二

    已知$f(x)=2ax\cos^2x+(a-1)\cos x-1,a>0$,记$|f(x)|$的最大值为$A$,1)求A.2)证明:$|-2a\sin 2x+(1-a)\sin x|\le 2A ...

  4. css图片替换文字

    含义: 图像替代,就是像我们在平时将文本添加到文本中,然后通过css隐藏文本在它的位置上显示一个背景图片,这样,搜索引擎仍然可以搜到HTML文本,即使我们禁用css后,文本时仍然是可以显示的. 引用& ...

  5. 覆盖的面积 HDU - 1255 (扫描线, 面积交)

    求n个矩阵面积相交的部分,和求面积并一样,不过这里需要开两个数组保存覆盖一次和覆盖两次以上的次数的部分,还是模板,主要注意点就是pushup部分,如果我已经被两次覆盖,那我的两个数组在这个root点的 ...

  6. VSCode创建自定义代码段

    上一篇:PyCharm创建自定义代码段(JetBrains系列通用) 设置方法 很简单,快速过一下,F1,然后输入snippets 然后选择对应语言 Python案例 内容和使用: { // pref ...

  7. QML学习笔记(二)-纯qml画图实现canvas画板-鼠标画图

    作者: 狐狸家的鱼 Github: 八至 版权声明:如需转载请获取授权和联系作者 用纯qml实现canvas画板功能,用鼠标进行画图,可以画直线,画圆,画矩形,画弧线. 由于canvas画图会有延迟和 ...

  8. CF739E Gosha is hunting

    法一: 匹配问题,网络流! 最大费用最大流,S到A,B流a/b费0,A,B到i流1费p[i]/u[i],同时选择再减p[i]*u[i]? 连二次!所以i到T流1费0流1费-p[i]*u[i] 最大流由 ...

  9. (转)MySQL中In与Exists的区别

    背景:总结mysql相关的知识点. 如果A表有n条记录,那么exists查询就是将这n条记录逐条取出,然后判断n遍exists条件. select * from user where exists s ...

  10. php 在服务器端开启错误日志记录方法

    修改php.ini设置,或者通过方法 ini_set设置以下项即可 1.打开error_reporting设置: 如 error_reporting= E_ALL 2.  log_errors=On ...