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
php 正则 过滤html 的超链接
Jun 02 PHP
PHP获取MAC地址的具体实例
Dec 13 PHP
PHP合并静态文件详解
Nov 14 PHP
Laravel 5.0 发布 新版本特性详解
Feb 10 PHP
php中实现用数组妩媚地生成要执行的sql语句
Jul 10 PHP
php使用APC实现实时上传进度条功能
Oct 26 PHP
PHP实现的观察者模式实例
Jun 21 PHP
浅析PHP类的反射来实现依赖注入过程
Feb 06 PHP
php命令行写shell实例详解
Jul 19 PHP
laravel-admin 后台表格筛选设置默认的查询日期方法
Oct 03 PHP
laravel框架如何设置公共头和公共尾
Oct 22 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 Smarty初体验二 获取配置信息
2011/08/08 PHP
提升PHP性能的21种方法介绍
2013/06/25 PHP
一个php短网址的生成代码(仿微博短网址)
2014/05/07 PHP
php 魔术方法详解
2014/11/11 PHP
windows8.1下Apache+Php+MySQL配置步骤
2015/10/30 PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
2017/10/25 PHP
php微信开发之关注事件
2018/06/14 PHP
JQuery 实现的页面滚动时浮动窗口控件
2009/07/10 Javascript
入门基础学习 ExtJS笔记(一)
2010/11/11 Javascript
JS如何将数字类型转化为没3个一个逗号的金钱格式
2014/01/27 Javascript
node.js中的fs.fsync方法使用说明
2014/12/15 Javascript
JS判断页面是否出现滚动条的方法
2015/07/17 Javascript
JS实现的表格行上下移动操作示例
2016/08/03 Javascript
浅谈js中的变量名和函数名重名
2017/02/13 Javascript
bootstrap响应式导航条模板使用详解(含下拉菜单,弹出框)
2017/11/17 Javascript
create-react-app 修改为多入口编译的方法
2018/08/01 Javascript
小程序页面动态配置实现方法
2019/02/05 Javascript
layui问题之渲染数据表格时,仅出现10条数据的解决方法
2019/09/12 Javascript
vue实现商城秒杀倒计时功能
2019/12/12 Javascript
[40:05]LGD vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
[01:04:14]VP vs TNC 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
MySQL中表的复制以及大型数据表的备份教程
2015/11/25 Python
python利用requests库进行接口测试的方法详解
2018/07/06 Python
django开发post接口简单案例,获取参数值的方法
2018/12/11 Python
Python 获取主机ip与hostname的方法
2018/12/17 Python
Python配置文件处理的方法教程
2019/08/29 Python
Python实现图像的垂直投影示例
2020/01/17 Python
Python面向对象多态实现原理及代码实例
2020/09/16 Python
python常量折叠基础知识点讲解
2021/02/28 Python
夏尔巴人登珠峰品牌:Sherpa Adventure Gear
2018/02/08 全球购物
项目合作意向书范本
2014/04/01 职场文书
销售竞赛活动方案
2014/08/23 职场文书
李强为自己工作观后感
2015/06/11 职场文书
商场广播稿范文
2015/08/19 职场文书
详解redis分布式锁的这些坑
2021/05/19 Redis
python中如何对多变量连续赋值
2021/06/03 Python