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攻防较量的过程,对抗的点就是哪一方考虑的更加周全。
PHP索引数组+unset使用不当导致的问题的更多相关文章
- 关于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 ...
- Bash : 索引数组
Bash 提供了两种类型的数组,分别是索引数组(indexed array)和关联数组(associative array).本文主要介绍索引数组的基本用法. 索引数组的基本特点 Bash 提供的数组 ...
- WPF--Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析
原文地址: http://www.tuicool.com/articles/F7reem http://blog.csdn.net/yl2isoft/article/details/11711833 ...
- JS 索引数组、关联数组和静态数组、动态数组
JS 索引数组.关联数组和静态数组.动态数组 数组分类: 1.从数组的下标分为索引数组.关联数组 var ary1 = [1,3,5,8]; //按索引去取数组元素,从0开始(当然某些语言实现从1开始 ...
- SELinux配置不当导致vsftpd系统用户不能登陆
1.测试是否是SELinux配置不当导致的: setenforce 0 再次登陆ftp,正常,说明是SELinux配置不当导致.还原配置 setenforce 1 2.查看配置: getsebool ...
- Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析
原文:Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析 前段时间,公司同事开发了一个小工具,在工具执行过程中,UI界面一直处于卡死状态. 通过阅读代码发现,主要是 ...
- CCLuaObjcBridge调Objective-C方法传索引数组报invalid key to 'next'错调试
CCLuaObjcBridge是cocos2d-x系列引擎与Objective-C进行交互的"桥梁",老廖的quick-cocos2d-x在其framework进行了简单了封装,封 ...
- numpy 数组索引数组
在numpy中,数组除了可以被整数索引,还可以被数组索引. a[b]就是已数组b的元素为索引,读取数组a的值. 当被索引数组a是一维数组,b是一维或则多维数组时,结果维度维度与索引数组b相同. a = ...
- js 索引数组转JSON为空
let a = [] a.a = 1 console.log(a) // [a: 1] console.log(JSON.stringify(a)) // [] 当然js根本没索引数组一说,这是php ...
随机推荐
- Python小爬虫——抓取豆瓣电影Top250数据
python抓取豆瓣电影Top250数据 1.豆瓣地址:https://movie.douban.com/top250?start=25&filter= 2.主要流程是抓取该网址下的Top25 ...
- MT【272】更大的视野,更好的思路.
已知$f(x)=\sum\limits_{k=1}^{2017}\dfrac{\cos kx}{\cos^k x},$则$f(\dfrac{\pi}{2018})=$_____ 分析:设$g(x)=\ ...
- css文本设置
常用的应用文本的css样式: color 设置文字的颜色,如: color:red; font-size 设置文字的大小,如:font-size:12px; font-family 设置文字的字体,如 ...
- js排序算法总结
快速排序 大致分三步: 1.找基准(一般是以中间项为基准) 2.遍历数组,小于基准的放在left,大于基准的放在right 3.递归 快速排序的平均时间复杂度是O(nlogn),最差情况是O(n²). ...
- [2017-7-28]Android Learning Day6
常用控件 Spinner DatePickerDialog TimePickerDiaog RadioButton CheckBox spinner(下拉菜单) <Spinner android ...
- NOI2018d1t1 归程 (dijkstra+kruskal重构树)
题意:给一张无向联通图,每条边有长度和高度,每次询问在高度大于p的边,从v点能到达的所有点到1号点的最短距离(强制在线) 首先dijkstra求出每个点到1号点的距离 易知:如果我按高度从高到低给边排 ...
- Thinkphp5 captcha扩展包安装,验证码验证以及点击刷新
首先下载 captcha扩展包,↓ 下载附件,解压到vendor目录下: 然后进入application/config.php添加配置信息: //验证码 'captcha' => ...
- Java面试题-基础知识
参考文章:Java面试题-基础知识 基础能力 什么是值传递和引用传递 线程状态有哪些,它们之间是如何转换的 进程与线程的区别,进程间如何通讯,线程间如何通讯? HashMap的数据结构是什么?如何实现 ...
- 判断ios还是android
$(function(){ var u = navigator.userAgent; var ua = navigator.userAgent.toLowerCase(); var isAndroid ...
- javascript 实现页面显示当前时间 动态读秒
用户进入网站后,出于友好目的,可以添加一些欢迎语句,并且显示系统当前时间,动态读秒的操作.还是直接粘贴代码吧 <script type="text/javascript"&g ...