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缩略图等比例无损压缩,可填充空白区域补充色
Jun 10 PHP
PHP资源管理框架Assetic简介
Jun 12 PHP
Laravel 5框架学习之表单验证
Apr 08 PHP
PHP查找数值数组中不重复最大和最小的10个数的方法
Apr 20 PHP
php实现中文字符截取防乱码方法汇总
Apr 29 PHP
php使用curl打开https网站的方法
Jun 17 PHP
php面向对象与面向过程两种方法给图片添加文字水印
Aug 26 PHP
PHP版本升级到7.x后wordpress的一些修改及wordpress技巧
Dec 25 PHP
将PHP的session数据存储到数据库中的代码实例
Jun 24 PHP
PHP foreach遍历多维数组实现方式
Nov 16 PHP
php 魔术常量详解及实例代码
Dec 04 PHP
php处理抢购类功能的高并发请求
Feb 08 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
javascript中最常用的继承模式 组合继承
2010/08/12 Javascript
JavaScript通过元素的ID和name设置样式
2014/07/08 Javascript
JavaScript对数字的判断与处理实例分析
2015/02/02 Javascript
javascript日期计算实例分析
2015/06/29 Javascript
异步加载JS、CSS代码(推荐)
2016/06/15 Javascript
NODE.JS跨域问题的完美解决方案
2016/10/20 Javascript
js模式化窗口问题![window.dialogArguments]
2016/10/30 Javascript
JAVA Web实时消息后台服务器推送技术---GoEasy
2016/11/04 Javascript
jquery操作ID带有变量的节点实例
2016/12/07 Javascript
JS实现点击表头表格自动排序(含数字、字符串、日期)
2017/01/22 Javascript
nodejs搭建本地服务器轻松解决跨域问题
2018/03/21 NodeJs
点击按钮弹出模态框的一系列操作代码实例
2019/03/29 Javascript
JavaScript中工厂函数与构造函数示例详解
2019/05/06 Javascript
微信接入之获取用户头像的方法步骤
2019/09/23 Javascript
Node.js HTTP服务器中的文件、图片上传的方法
2019/09/23 Javascript
[01:21:36]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
python复制与引用用法分析
2015/04/08 Python
在Django的模型中添加自定义方法的示例
2015/07/21 Python
详解Python命令行解析工具Argparse
2016/04/20 Python
深入理解python多进程编程
2016/06/12 Python
Python使用matplotlib绘制多个图形单独显示的方法示例
2018/03/14 Python
Django项目中用JS实现加载子页面并传值的方法
2018/05/28 Python
python+selenium打印当前页面的titl和url方法
2018/06/22 Python
基于python实现聊天室程序
2018/07/27 Python
Python常见读写文件操作实例总结【文本、json、csv、pdf等】
2019/04/15 Python
英国网上购买门:Direct Doors
2018/06/07 全球购物
如果NULL和0作为空指针常数是等价的,那我到底该用哪一个
2014/09/16 面试题
如何利用cmp命令比较文件
2016/04/11 面试题
简历自我评价怎么写好呢?
2014/01/04 职场文书
宝宝周岁宴答谢词
2014/01/26 职场文书
财务总监管理岗位职责
2014/03/08 职场文书
货物运输服务质量承诺书
2014/05/29 职场文书
房屋租赁委托书范本
2014/10/04 职场文书
学校节水倡议书
2015/04/29 职场文书
七年级上册生物的课件
2019/08/07 职场文书
mysql联合索引的使用规则
2021/06/23 MySQL