PHP中uploaded_files函数使用方法详解


Posted in PHP onMarch 09, 2011

对PHP语言有些了解的朋友们都知道,它包含有功能强大的函数库。我们今天就一起来了解一下PHP uploaded_files函数的具体功能。
在早期的PHP版本中,上传文件很可能是通过如下的代码实现的:

…… 
if (isset($_FILES['file'])) { 
$tmp_name = $_FILES['file']['tmp_name']; 
} 
if (file_exists($tmp_name)) { 
copy($tmp_name,$destfile); 
} 
……

但是很可能会被伪造一个$_FILES['file']数组出来,如果tmp_name的内容会被指定为/etc/passwd等敏感信息的内容,那么很容 易出现安全问题。PHP在后来的版本中用is_uploaded_file() 和 move_uploaded_file()解决了这个问题,用PHP uploaded_files函数不仅会检查$_FILES['file'] ['tmp_name']是否存在,而且会检查$_FILES['file']['tmp_name']是否是上传的文件,这样就使得伪造$_FILES 变量变得不可能,因为脚本会在检查到$_FILES['file']['tmp_name']不是PHP上传的时候终止执行。
伪造变得不可能了么?在很多的脚本里面我看到初试化部分就有@extract($_POST)之类的操作,以保证程序在register globals为off的环境下能继续运行,这样的环境下我们很轻松可以伪造$_FILES数组,甚至将原来的$_FILES数组覆盖,但是想完全的伪造 一个$_FILES数组还是很困难的,因为你无法饶过is_uploaded_file() 和 move_uploaded_file()。
但是在windows下的PHP环境下测试时,我们发现PHP的临时文件很有规律,是C:\WINDOWS \TEMP\PHP93.tmp这种格式,上传的时候文件名字会是C:\WINDOWS\TEMP\PHPXXXXXX.tmp这种格式变化,其中 XXXXXX是十六进制的数字,并且是按照顺序增加的,也就是说如果这次上传的临时文件名是C:\WINDOWS\TEMP\PHP93.tmp,那么下 次就会是C:\WINDOWS\TEMP\PHP94.tmp,临时文件名变得有规律。
但是我们可能不知道当前的文件名是什么,这可以通过PHP自身的错 误机制泄露出来,譬如我们将临时文件拷贝到一个没有权限的目录或者在目标文件里包含文件系统禁止的字符就可以将当前的临时文件名字给泄露出来,当然前提是 没有错误抑制处理。
那么到底如何饶过is_uploaded_file() 和 move_uploaded_file()呢?看看PHP uploaded_files函数部分的代码:
PHP_FUNCTION(is_uploaded_file) 
{ 
zval **path; 
if (!SG(rfc1867_uploaded_files)) { 
RETURN_FALSE; 
} 
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &path) != SUCCESS) { 
ZEND_WRONG_PARAM_COUNT(); 
} 
convert_to_string_ex(path); 
if (zend_hash_exists(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), Z_STRLEN_PP(path)+1)) { 
RETURN_TRUE; 
} else { 
RETURN_FALSE; 
} 
}

它 是从当前的rfc1867_uploaded_files哈希表中查找看是否当前的文件名是否存在。其中rfc1867_uploaded_files保 存了当前PHP脚本运行过程中由系统和PHP产生的有关文件上传的变量和内容。如果存在,就说明指定的文件名的确是本次上传的,否则为否。
PHP 有个很奇怪的特性就是,当你提交一个上传表单时,PHP在做处理之前这个文件就已经被上传到临时目录下面,一直到PHP脚本运行结束的时候才会销毁掉。也 就是说,你即使向一个不接受$_FILSE变量的PHP脚本提交这样一个表单,$_FILSE变量依然会产生,文件依然会被先上传到临时目录。问题就产生 了。下面的脚本可能能说明这个问题:
< ? 
$a=$_FILES['attach']['tmp_name']; 
echo $a.”………….”; 
$file='C:\\WINDOWS\\TEMP\\PHP95.tmp'; 
echo $file; 
if(is_uploaded_file($file)) echo ‘………………Yes'; 
?>

其 中C:\\WINDOWS\\TEMP\\PHP95.tmp是我猜测的临时文件名字,当时,测试这个脚本的时候我们需要向它上传一个文件或者是100个 文件,使得其中一个临时文件名为C:\\WINDOWS\\TEMP\\PHP95.tmp。如果此刻脚本有extract操作,我们就可以很方便的伪造 出一个$_FILES变量了。
不是么?可能要问伪造$_FILES变量有什么作用,我们就可以产生原来程序不允许的文件名了,PHP在处理上传的时候会对 原来的文件名有一个类似于basename()的操作,但是一旦可以伪造之后我们就可以轻易的在文件名之内加\啊../啊等等你所喜欢的任何东西
PHP uploaded_files函数的实际利用可能有点苛刻,但是也总算是PHP一点瑕疵吧,呵呵。
PHP 相关文章推荐
thinkPHP实现表单自动验证
Dec 24 PHP
PHP树的深度编历生成迷宫及A*自动寻路算法实例分析
Mar 10 PHP
php找出指定范围内回文数且平方根也是回文数的方法
Mar 23 PHP
PHP SPL标准库之文件操作(SplFileInfo和SplFileObject)实例
May 11 PHP
PHP中使用array函数新建一个数组
Nov 19 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
Dec 19 PHP
php获得客户端浏览器名称及版本的方法(基于ECShop函数)
Dec 23 PHP
php中namespace use用法实例分析
Jan 22 PHP
Laravel使用Caching缓存数据减轻数据库查询压力的方法
Mar 15 PHP
PHP之将POST数据转化为字符串的实现代码
Nov 03 PHP
php读取qqwry.dat ip地址定位文件的类实例代码
Nov 15 PHP
PHP使用Redis长连接的方法详解
Feb 12 PHP
PHP $_FILES函数详解
Mar 09 #PHP
PHP中for与foreach的区别分析
Mar 09 #PHP
php模板中出现空行解决方法
Mar 08 #PHP
在MongoDB中模拟Auto Increment的php代码
Mar 06 #PHP
PHP数组交集的优化代码分析
Mar 06 #PHP
php下安装配置fckeditor编辑器的方法
Mar 02 #PHP
PHP如何抛出异常处理错误
Mar 02 #PHP
You might like
PHP查询数据库中满足条件的记录条数(两种实现方法)
2013/01/29 PHP
如何使用“PHP” 彩蛋进行敏感信息获取
2013/08/07 PHP
浅谈PHP错误类型及屏蔽方法
2017/05/27 PHP
yii框架结合charjs实现统计30天数据的方法
2020/04/04 PHP
javascript 播放器 控制
2007/01/22 Javascript
写了一个layout,拖动条连贯,内容区可为iframe
2007/08/19 Javascript
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
让JavaScript拥有类似Lambda表达式编程能力的方法
2010/09/12 Javascript
JS+CSS实现淡入式焦点图片幻灯切换效果的方法
2015/02/26 Javascript
AngularJS实现表单手动验证和表单自动验证
2015/12/09 Javascript
Javascript之Number对象介绍
2016/06/07 Javascript
快速解决js开发下拉框中blur与click冲突
2016/10/10 Javascript
Angular 4依赖注入学习教程之InjectToken的使用(八)
2017/06/04 Javascript
vue中引用阿里字体图标的方法
2018/02/10 Javascript
微信小程序 scroll-view的使用案例代码详解
2020/06/11 Javascript
实践Python的爬虫框架Scrapy来抓取豆瓣电影TOP250
2016/01/20 Python
python机器学习理论与实战(一)K近邻法
2021/01/28 Python
详解Python判定IP地址合法性的三种方法
2018/03/06 Python
用python 批量更改图像尺寸到统一大小的方法
2018/03/31 Python
python flask框架实现重定向功能示例
2019/07/02 Python
Python机器学习算法库scikit-learn学习之决策树实现方法详解
2019/07/04 Python
python time.sleep()是睡眠线程还是进程
2019/07/09 Python
Python MySQLdb 执行sql语句时的参数传递方式
2020/03/04 Python
在Mac中PyCharm配置python Anaconda环境过程图解
2020/03/11 Python
numpy矩阵数值太多不能全部显示的解决
2020/05/14 Python
Python3如何使用range函数替代xrange函数
2020/10/05 Python
美国在线购买空气净化器、除湿器、加湿器网站:AllergyBuyersClub
2021/03/16 全球购物
信息技术教学反思
2014/02/12 职场文书
毕业晚会主持词
2014/03/24 职场文书
银行委托书范本
2014/04/04 职场文书
师德师风个人总结
2015/02/06 职场文书
2015年建筑工作总结报告
2015/05/04 职场文书
经费申请报告
2015/05/15 职场文书
职场干货:简历中的自我评价应该这样写!
2019/05/06 职场文书
springboot入门 之profile设置方式
2022/04/04 Java/Android
python小型的音频操作库mp3Play
2022/04/24 Python