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文件的实现方法
Mar 19 PHP
PHP Smarty生成EXCEL文档的代码
Aug 23 PHP
php数组函数序列 之array_count_values() 统计数组中所有值出现的次数函数
Oct 29 PHP
PHP禁止个别IP访问网站
Oct 30 PHP
PH P5.2至5.5、5.6的新增功能详解
Jul 14 PHP
在php和MySql中计算时间差的方法详解
Mar 27 PHP
php简单统计字符串单词数量的方法
Jun 19 PHP
thinkphp3.x中变量的获取和过滤方法详解
May 20 PHP
php根据数据id自动生成编号的实现方法
Oct 16 PHP
php图形jpgraph操作实例分析
Feb 22 PHP
PHP去除空数组且数组键名重置的讲解
Feb 28 PHP
Smarty模板类内部原理实例分析
Jul 03 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获取MSN好友列表类的实现代码
2013/06/23 PHP
如何解决CI框架的Disallowed Key Characters错误提示
2013/07/05 PHP
PHP简单遍历对象示例
2016/09/28 PHP
PHP判断密码强度的方法详解
2017/05/26 PHP
laravel 配置路由 api和web定义的路由的区别详解
2019/09/03 PHP
Javascript中的this绑定介绍
2011/09/22 Javascript
JS函数实现动态添加CSS样式表文件
2012/12/15 Javascript
用Javascript获取页面元素的具体位置
2013/12/09 Javascript
javascript原型链继承用法实例分析
2015/01/28 Javascript
JQuery中DOM加载与事件执行实例分析
2015/06/13 Javascript
js省市联动效果完整实例代码
2015/12/09 Javascript
JavaScript根据CSS的Media Queries来判断浏览设备的方法
2016/05/10 Javascript
Vue 仿百度搜索功能实现代码
2017/02/16 Javascript
AngularJS 中ui-view传参的实例详解
2017/08/25 Javascript
浅谈JS获取元素的N种方法及其动静态讨论
2017/08/25 Javascript
详解在vue-cli项目中使用mockjs(请求数据删除数据)
2017/10/23 Javascript
vue-cli脚手架-bulid下的配置文件
2018/03/27 Javascript
JS内部事件机制之单线程原理
2018/07/02 Javascript
jQuery实现form表单基于ajax无刷新提交方法实例代码
2019/11/04 jQuery
python实现将英文单词表示的数字转换成阿拉伯数字的方法
2015/07/02 Python
在Mac OS系统上安装Python的Pillow库的教程
2015/11/20 Python
Python 利用内置set函数对字符串和列表进行去重的方法
2018/06/29 Python
flask入门之表单的实现
2018/07/18 Python
django主动抛出403异常的方法详解
2019/01/04 Python
Tensorflow轻松实现XOR运算的方式
2020/02/03 Python
keras 多gpu并行运行案例
2020/06/10 Python
纯css3实现图片翻牌特效
2015/03/10 HTML / CSS
详解HTML5 window.postMessage与跨域
2017/05/11 HTML / CSS
如何查看浏览器对html5的支持情况
2020/12/15 HTML / CSS
创业女性典型材料
2014/05/02 职场文书
社区党员志愿服务活动方案
2014/08/18 职场文书
个人委托书范本汇总
2014/10/01 职场文书
死亡赔偿协议书
2015/01/28 职场文书
2015年公民道德宣传日活动总结
2015/03/23 职场文书
通知怎么写?
2019/04/17 职场文书
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang