流年 发布于 ThinkPHP官方博客: https://blog.thinkphp.cn/789333

本文主要和大家探讨一下ThinkPHP的安全注意事项,可以作为ThinkPHP建议的安全规范实践。(如果有新的内容我也会及时补充)

首先,没有绝对的安全,只要你有足够的安全意识才能尽可能的杜绝安全隐患。规范的使用框架,能让你尽量避免一些看起来比较幼稚的安全问题。本文描述的安全注意事项主要是指生产环境下面的安全策略,本地开发的情况下有时候为了调试的需要安全并不是第一考虑。

ThinkPHP在考虑开发体验的同时,仍然十分重视框架的底层安全,虽然屡有安全漏洞被播报,但官方都是第一时间进行修复处理,而且大部分漏洞只要开发者有一定的安全意识都是可以避免的,今年也和国内的几个安全团队建立了合作关系,有助于提前发现和及时修正框架可能被利用的漏洞或者隐患。

规范部署

这一点很多开发者不是特别重视,安全是一个整体性的问题,任何一个环节出问题,带来的后果都是一样的严重,部署的安全策略是一个基础安全问题。

很多开发者往往不按照官方的部署规范进行部署,请务必把你的WEB根目录指向public目录而不是应用根目录,并且不要随意更改入口文件的位置。public目录下面不要放除了入口文件和资源文件以外的其它应用文件。

关闭调试模式

在部署到生产环境的时候,确保你已经关闭了调试模式,可以通过修改环境变量的方式关闭调试模式。

APP_DEBUG=false

无论是本地开发还是生产环境部署,都不建议直接通过修改配置文件的方式开启/关闭调试模式,而应该使用环境变量(本地开发可以通过定义.env文件)。

关闭调试模式后,系统的健康状态和运行监控主要依靠日志或者你使用的监控服务。所以,要养成定时检查日志和运行状态的习惯。

请求变量过滤

永远不要相信用户的输入,这是一句至理名言。尽可能的过滤请求变量能有效防范大部分的漏洞和隐患。

框架建议的获取请求变量的方法是Request类的param方法(如非必要不要再使用get或者post方法获取,更不要使用原生的$_GET/$_POST等方法获取)。

public function index(Request $request)
{
$name = $request->param('name'); // 在这里可以根据你的业务需求进行更严谨的过滤
// 例如 $name = $request->param('name','','htmlentities,strtolower');
// 或者使用验证器进行专门的验证
}

对于有明确类型的请求变量,可以在使用param方法的时候使用类型强制转换,例如:

public function index(Request $request)
{
// 强制转换字符串数据
$name = $request->param('name/s'); // 强制转换整型数据
$name = $request->param('id/d'); // 强制转换浮点型数据
$name = $request->param('score/f');
}

或者直接使用方法参数获取请求变量

public function index(string $name)
{
// 在这里可以根据你的业务需求进行更严谨的过滤
// 或者使用验证器进行专门的验证
}

如果你需要对所有数据进行处理,可以设置全局的过滤方法。对不同的应用需求设置default_filter过滤规则(默认没有任何过滤规则),常见的安全过滤函数包括stripslasheshtmlentitieshtmlspecialcharsstrip_tags等,请根据业务场景选择最合适的过滤方法。

如果需要获取多个数据,建议使用only方法指定需要获取的变量名称,避免有些不怀好意的数据提交导致权限问题。

public function index(Request $request)
{
// 指定表单数据名称
$data = $request->only(['name','title']);
}

当你使用数据库或者模型操作写入数据的时候,也可以指定字段,避免非法和不希望的字段写入数据库。

// 模型
User::allowField(['name','title'])
->save($data); // 数据库
Db::name('user')
->field(['name','title'])
->insert($data);

模型还有一个只读字段的功能能避免你的数据受到外部的修改。

上传检测

网站的上传功能也是一个非常容易被攻击的入口,所以对上传功能的安全检查是尤其必要的。

系统的think\File类提供了文件上传的安全支持,包括对文件后缀、文件类型、文件大小以及上传图片文件的合法性检查,确保你已经在上传操作中启用了这些合法性检查,可以参考手册的上传章节。

SQL注入

ThinkPHP的查询统一使用了PDOprepare预查询和参数绑定机制,能有效的避免SQL注入的发生。但不代表绝对安全,如果你缺乏良好的代码规范,仍然有可能被利用。

一个最简单的原则就是不要让用户决定你的查询条件(或者字段排序)和控制你的查询数据。

对于一些字符串的查询条件(包括原生查询)或者特殊的查询(包括ORDER部分),需要手动进行参数绑定。

// 错误的
Db::query("select * from think_user where id=$id AND status=$statis");
// 正确的
Db::query("select * from think_user where id=? AND status=?", [ $id, $status]);
// 正确的
Db::execute("update think_user set name=:name where status=:status", [
'name' => 'thinkphp',
'status' => 1
]);

对于使用了whereExpwhereRaw方式的查询,你也需要使用参数绑定。

Db::name('user')
->whereRaw('id > ? AND status = ?',[10, 1])
->select();

使用验证器

对于大量的表单需要验证的情况,建议使用验证器功能统一进行数据的合规验证。验证器的验证操作应该在控制器或者路由阶段使用validate方法进行处理,模型的数据验证功能新版已经取消不再建议使用,模型和数据库操作的时候应该传入经过安全处理过的数据。

XSS攻击

跨站脚本攻击(cross-site scripting,简称 XSS),XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

在渲染输出的页面中,要对一些数据进行安全处理,防止被恶意利用造成XSS攻击,如果是5.1版本的话,所有的输出都已经经过了htmlentities 转义输出,确保安全。如果是5.0版本的话,你可以自定义一个xss过滤函数,在模板文件中对一些关键内容变量进行函数处理。

CSRF

CSRF 跨站请求伪造是 Web 应用中最常见的安全威胁之一,攻击者伪造目标用户的HTTP请求,然后此请求发送到有CSRF漏洞的网站,网站执行此请求后,引发跨站请求伪造攻击。攻击者利用隐蔽的HTTP连接,让目标用户在不注意的情况下单击这个链接,由于是用户自己点击的,而他又是合法用户拥有合法权限,所以目标用户能够在网站内执行特定的HTTP链接,从而达到攻击者的目的。

开启表单令牌验证,尽量开启强制路由并严格规范每个URL请求,定义单独的MISS路由规则。

遵循请求类型的使用规范并做好权限验证,删除操作必须使用DELETE请求,数据更改操作必须使用POSTPUT 或者 PATCH 请求方法,GET请求不应该更改任何数据。

会话劫持

会话劫持是指攻击者利用各种手段来获取目标用户的session id。一旦获取到session id,那么攻击者可以利用目标用户的身份来登录网站,获取目标用户的操作权限。

有效的防护策略包括:

在每次回话启动的时候,调用regenerate方法。

Session::start();
Session::regenerate(true);

更改session配置参数,开启安全选项:

'use_trans_sid'  => 0,
'httponly' => true,
'secure' => true,

升级到安全版本

官方会对一些安全隐患和潜在漏洞进行修复,并且发布一个更为安全的版本。请确认你升级到更安全的版本,确保底层的安全和健壮性。

关注官方的公众号和开发者周刊,注意最新的安全更新。

业务逻辑安全

这个属于应用层面的安全,很多漏洞源于某个业务逻辑自身的安全隐患,包括没有做合理的数据验证和权限检查,尤其是涉及资金及财务层面的,一定要做更多的安全检查,并且开启事务。一个好的建议是更多的对应用进行分层设计,减少每层的复杂性,独立的分层设计便于提高安全性。

服务器安全

最后一点是运维阶段需要特别注意的,及时更新服务器的安全补丁,确保没有可利用的公开系统漏洞,包括你的数据库系统安全(尤其是数据备份工作)。

ThinkPHP安全规范指引的更多相关文章

  1. 从" ThinkPHP 开发规范 "看 PHP 的命名规范和开发建议

    稍稍水一篇博客,摘抄自Think PHP 的开发规范,很有引导性,我们可以将这些规范实践到原生 PHP 中. 命名规范 使用ThinkPHP开发的过程中应该尽量遵循下列命名规范: 类文件都是以.cla ...

  2. Thinkphp命名规范

    1.类文件都是以.class.php为后缀(这里是指的ThinkPHP内部使用的类库文件,不代表外部加载的类库文件),使用驼峰法命名,并且首字母大写,例如 DbMysql.class.php: 2.类 ...

  3. thinkphp开发规范

    1.编写目的     为了更好的提高技术部的工作效率,保证开发的有效性和合理性,并可最大程度的提高程序代码的可读性和可重复利用性,指定此规范.开发团队根据自己的实际情况,可以对本规范进行补充或裁减. ...

  4. thinkphp 命名规范

    目录和文件命名 目录和文件名采用 小写+下划线,并且以小写字母开头: 类库.函数文件统一以.php为后缀: 类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致(包括大小写): 类名和 ...

  5. 攻城记:Thinkphp框架的项目规划总结和踩坑经验

    一.项目模块规划 1.项目分为PC端.移动端.和PC管理端,分为对应目录为 /Application/Home,/Application/Mobile,/Application/Admin: 对应入口 ...

  6. ThinkPHP学习总结

    ThinkPHP学习总结 网站开发使用的thinkPHP5.0在此总结备查 MVC关系功能图 一.Thinkphp开发规范 l 类 类库.函数文件统一以.php为后缀: 类的文件名均以命名空间定义,并 ...

  7. ThinkPHP 3.2 vendor()方法的深入研究及Phpqrcode的正确扩展

    ThinkPHP vendor 方法导入第三方类库 第三方类库 第三方类库指除了 ThinkPHP 框架.应用项目类库之外的其他类库,一般由第三方系统或产品提供,如 Smarty.Zend 等系统的类 ...

  8. thinkphp中的类库与引用import引入机制

    ThinkPHP的类库包括基类库和应用类库 控制器类 模块名+Action 例如 UserAction.InfoAction 模型类 模型名+Model 例如 UserModel.InfoModel ...

  9. ThinkPHP vendor 方法导入第三方类库

    ThinkPHP 3.2 vendor()方法的深入研究及Phpqrcode的正确扩展 ThinkPHP vendor 方法导入第三方类库 第三方类库 第三方类库指除了 ThinkPHP 框架.应用项 ...

随机推荐

  1. apache基础

    apache基于多域名的虚拟主机 NameVirtualHost *:80<VirtualHost *:80> DocumentRoot "/var/www/html/xk/sh ...

  2. JavaScript 动态选择方法和属性

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  3. python接口测试-认识GET请求

    前边用工具也实现了接口自动化,但是后来很多的时候维护成本有点高.而且灵活上还是有所欠缺的. 于是,自己开始摸索学习敲码.应该有很多不对的地方或者可以优化的望各位大神勿喷,同时欢迎各位大神评论区发表自己 ...

  4. POJ 1185 炮兵阵地 【状压DP】

    <题目链接> 题目大意: 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平 ...

  5. IDEA 2018.2.5最新版破解到2100年图解教程

    先看下我破解后的效果图 把下载的破解补丁放在你的idea的安装目录下的bin的目录下面(如下图所示),本文示例为F:\ProgramFiles\JetBrains\IntelliJ IDEA 2018 ...

  6. Grodno 2015 (Urozero May 2015 Day 5)

    A. Palindromes 留坑. B. Modules 将$a$排序,那么最优解中$a_n$一定放在前后一个,且前面$n-1$个每次要么放最小的,要么放最大的,区间DP即可. #include&l ...

  7. phantomjs 中文文档

    phantomjs 中文文档 转载 入门教程:转载 http://www.cnblogs.com/front-Thinking/p/4321720.html 1.介绍 简介   PhantomJS是一 ...

  8. CCTV5 前端

    get :  fre = 11868  symbolrate  = 27500 pls_n=0------167    CCTV 9------------168    CCTV 3--------- ...

  9. 马昕璐201771010118《面向对象程序设计(java)》第七周学习总结

    第一部分:理论知识学习部分 Java用于控制可见性的4个访问权限修饰符: 1.private(只有该类可以访问) 2.protected(该类及其子类的成员可以访问,同一个包中的类也可访问) 3.pu ...

  10. __x__(13)0906第三天__xhtml 的语法规范

    html中不区分大小写,但是最好用小写. 注释不能嵌套. html标签必须结束,即 <></> 或者 <    /> html标签不能交叉嵌套. html的标签,有 ...