PHP中危险的file_put_contents函数详解


Posted in PHP onNovember 04, 2017

前言

最近在EIS上遇到一道文件上传的题,发现过滤了<,这样基本很多姿势都无效了,想了很久没做出来这题,赛后才知道是利用数组来绕过, 这里分析了下原理,话不多说了,来一起看看详细的介绍吧。

来看下file_put_contents函数第二个参数data的官网定义:

data
要写入的数据。类型可以是 string,array 或者是 stream 资源(如上面所说的那样)。
 
如果 data 指定为 stream 资源,这里 stream 中所保存的缓存数据将被写入到指定文件中,这种用法就相似于使用 stream_copy_to_stream() 函数。
 
参数 data 可以是数组(但不能为多维数组),这就相当于 file_put_contents($filename, join('', $array))。

可以看到,data参数可以是数组, 会自动做join('',$array)转换为字符串的

该函数访问文件时,遵循以下规则:

  • 如果设置了 FILE_USE_INCLUDE_PATH,那么将检查 *filename* 副本的内置路径
  • 如果文件不存在,将创建一个文件
  • 打开文件
  • 如果设置了 LOCK_EX,那么将锁定文件
  • 如果设置了 FILE_APPEND,那么将移至文件末尾。否则,将会清除文件的内容
  • 向文件中写入数据
  • 关闭文件并对所有文件解锁
  • 如果成功,该函数将返回写入文件中的字符数。如果失败,则返回 False。

但我们字符串过滤函数一般是用preg_match函数来过滤的,如:

if(preg_match('/\</',$data)){
 die('hack');
}

我们知道,很多处理字符串的函数如果传入数组会出错返回NULL, 如strcmp,strlen,md5等, 但preg_match 函数出错返回false, 这里我们可以通过var_dump(preg_match('/\</',$data)); 来验证, 这样的话,preg_match 的正则过滤就失效了

因此,猜测文件上传的代码是这样写的

<?php 
 
if(isset($_POST['content']) && isset($_POST['ext'])){
 $data = $_POST['content'];
 $ext = $_POST['ext'];
 
 //var_dump(preg_match('/\</',$data));
 if(preg_match('/\</',$data)){
  die('hack');
 }
 $filename = time();
 file_put_contents($filename.$ext, $data);
}
 
?>

于是我么可以传入content[]=<?php phpinfo();?>&ext=php 这样来绕过

修复方法

修复方法是使用fwrite 函数来代替危险的file_put_contents函数,fwrite函数只能传入字符串,如果是数组会出错返回false

<?php 
 
if(isset($_POST['content']) && isset($_POST['ext'])){
 $data = $_POST['content'];
 $ext = $_POST['ext'];
 
 //var_dump(preg_match('/\</',$data));
 if(preg_match('/\</',$data)){
  die('hack');
 }
 $filename = time();
 // file_put_contents($filename.$ext, $data);
 $f = fopen($filename.$ext);
 var_dump(fwrite($f,$data));
}
 
?>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
十天学会php之第二天
Oct 09 PHP
第十三节--对象串行化
Nov 16 PHP
用PHP实现读取和编写XML DOM代码
Apr 07 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
Jan 23 PHP
深入掌握include_once与require_once的区别
Jun 17 PHP
php保存任意网络图片到服务器的方法
Apr 14 PHP
php数组合并与拆分实例分析
Jun 12 PHP
PHP如何读取由JavaScript设置的Cookie
Mar 22 PHP
PHP实现的注册,登录及查询用户资料功能API接口示例
Jun 06 PHP
浅析PHP类的反射来实现依赖注入过程
Feb 06 PHP
用PHP做了一个领取优惠券活动的示例代码
Jul 05 PHP
Laravel find in set排序实例
Oct 09 PHP
PHP回调函数概念与用法实例分析
Nov 03 #PHP
PHP实现字符串翻转功能的方法【递归与循环算法】
Nov 03 #PHP
PHP空值检测函数与方法汇总
Nov 19 #PHP
使用PHPStorm+XDebug搭建单步调试环境
Nov 19 #PHP
php利用云片网实现短信验证码功能的示例代码
Nov 18 #PHP
swoole和websocket简单聊天室开发
Nov 18 #PHP
php单元测试phpunit入门实例教程
Nov 17 #PHP
You might like
PHP遍历XML文档所有节点的方法
2015/03/12 PHP
Laravel 5框架学习之Blade 简介
2015/04/08 PHP
php中的异常和错误浅析
2017/05/03 PHP
Yii框架页面渲染操作实例详解
2019/07/19 PHP
jQuery 常见开发使用技巧总结
2009/12/26 Javascript
JS中的substring和substr函数的区别说明
2013/05/07 Javascript
js实现仿阿里巴巴城市选择框效果实例
2015/06/24 Javascript
Js类的静态方法与实例方法区分及jQuery拓展的两种方法
2016/06/03 Javascript
Vue组件BootPage实现简单的分页功能
2016/09/12 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(一)
2017/05/11 Javascript
vue的常用组件操作方法应用分析
2018/04/13 Javascript
微信小程序五子棋游戏的棋盘,重置,对弈实现方法【附demo源码下载】
2019/02/20 Javascript
函数式编程入门实践(一)
2019/04/20 Javascript
express框架下使用session的方法
2019/07/31 Javascript
js实现移动端tab切换时下划线滑动效果
2019/09/08 Javascript
Vue解析带html标签的字符串为dom的实例
2019/11/13 Javascript
详解React 元素渲染
2020/07/07 Javascript
JavaScript实现切换多张图片
2021/01/27 Javascript
[56:35]DOTA2上海特级锦标赛C组小组赛#1 OG VS Archon第二局
2016/02/27 DOTA
Python 3中print函数的使用方法总结
2017/08/08 Python
python interpolate插值实例
2020/07/06 Python
css3实现元素环绕中心点布局的方法示例
2019/01/15 HTML / CSS
Html5元素及基本语法详解
2016/08/02 HTML / CSS
Expedia韩国官网:亚洲发展最快的在线旅游门户网站
2018/02/26 全球购物
护理学毕业生自荐信
2013/10/02 职场文书
大门门卫岗位职责
2013/11/30 职场文书
关于赌博的检讨书
2014/01/08 职场文书
优乐美广告词
2014/03/14 职场文书
法律七进实施方案
2014/03/15 职场文书
优秀毕业生就业推荐信
2014/05/22 职场文书
大学第二课堂活动总结
2014/07/08 职场文书
居委会个人对照检查材料思想汇报
2014/09/29 职场文书
当幸福来敲门观后感
2015/06/01 职场文书
Django migrate报错的解决方案
2021/05/20 Python
openstack中的rpc远程调用的方法
2021/07/09 Python
mysql数据库如何转移到oracle
2022/12/24 MySQL