热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThinkPHP3.1快速入门(16)安全

在开发过程中,除了确保业务逻辑没有安全隐患外,应该充分了解和利用框架内建的安全机制或者工具来确保应用以及服务器的安全性,下面我们总结下ThinkPHP中涉及到的安全机制。
在开发过程中,除了确保业务逻辑没有安全隐患外,应该充分了解和利用框架内建的安全机制或者工具来确保应用以及服务器的安全性,下面我们总结下ThinkPHP中涉及到的安全机制。

系统安全

系统安全指ThinkPHP可以配合的服务器的安全部署策略。

应用部署建议

首先,我们建议在条件允许的情况下,把框架目录和项目目录都部署在非WEB访问目录下面,ThinkPHP的访问机制完全支持框架和项目的非WEB目录访问,你只需要把入口文件和资源(主要是指JS、样式和图片文件)目录放置于WEB目录下面即可。因此,建议的部署目录如下:
  1. index.php 项目入口文件
  2. Public/ 项目资源文件目录
  3.     JsJS目录
  4.     Css/ 样式文件目录
  5.     Images/  图像文件目录
  6. protected/ (受保护的目录,可以部署到非WEB目录或者设置安全访问)
  7.     ThinkPHP/ 框架系统目录
  8.     App/ 项目目录
  9.     Uploads/ 项目上传目录

系统安全设置

如果你已经通过部署策略设置了系统目录安全访问的话,则可以跳过这段。
如果你无法完全做到上述的服务器目录安全保护,也无需担心,ThinkPHP仍然可以通过设置确保你的目录安全。框架的核心文件本身已经做了访问判断,所有核心文件均不能直接在URL中被访问,因此也不用担心直接访问某些文件导致的错误暴露你的服务器路径之类的信息。
对于应用目录,系统则提供了目录安全访问机制,你可以在第一次生成项目目录结构之前,在入口文件中添加:
  1. define('BUILD_DIR_SECURE'true);
运行项目后会自动给项目的相关目录生成目录安全文件(在相关的目录下面生成空白的htm文件),并且可以自定义安全文件的文件名 DIR_SECURE_FILENAME ,默认是index.html,如果你想给你们的安全文件定义为default.html可以使用
  1. define('DIR_SECURE_FILENAME''default.html');
还可以支持多个安全文件写入,例如你想同时写入index.html和index.htm 两个文件,以满足不同的服务器部署环境,可以这样定义:
  1. define('DIR_SECURE_FILENAME''index.html,index.htm');
默认的安全文件只是写入一个空白字符串,如果需要写入其他内容,可以通过DIR_SECURE_CONTENT参数来指定,例如:
  1. define('DIR_SECURE_CONTENT''deney Access!');
下面是一个完整的使用目录安全写入的例子
  1. define('BUILD_DIR_SECURE',true);
  2. define('DIR_SECURE_FILENAME''index.html');
  3. define('DIR_SECURE_CONTENT''deney Access!');
除了目录安全之外,还需要保护模板文件不被直接访问,因为有可能会在模板文件中暴露数据表的字段信息。解决办法是配置.htaccess文件(针对Apache服务器,其他服务器参考修改),把以下代码保存在项目的模板目录目录(默认是Tpl)下保存存为.htaccess。
  1.  *.html>
  2.   Order Allow,Deny 
  3.   Deny from all
如果你的模板文件后缀不是html可以将*.html改成你的模板文件的后缀。

表单安全

自动验证和自动完成

ThinkPHP内置的自动验证自动完成功能可以有效地对表单提交的数据安全加以控制。这两部分在快速入门系列中已经有过详细的介绍,就不再描述了。

表单令牌

ThinkPHP内置了表单令牌验证功能,可以有效防止表单的重复提交等安全防护。
表单令牌验证相关的配置参数有:
  1. 'TOKEN_ON'=>true,  // 是否开启令牌验证 默认关闭
  2. 'TOKEN_NAME'=>'__hash__',    // 令牌验证的表单隐藏字段名称
  3. 'TOKEN_TYPE'=>'md5',  //令牌哈希验证规则 默认为MD5
  4. 'TOKEN_RESET'=>true,  //令牌验证出错后是否重置令牌 默认为true
如果开启表单令牌验证功能,系统会自动在带有表单的模板文件里面自动生成以TOKEN_NAME为名称的隐藏域,其值则是TOKEN_TYPE方式生成的哈希字符串,用于实现表单的自动令牌验证。
自动生成的隐藏域位于表单Form结束标志之前,如果希望自己控制隐藏域的位置,可以手动在表单页面添加{__TOKEN__} 标识,系统会在输出模板的时候自动替换。
如果页面中存在多个表单,建议添加{__TOKEN__}标识,并确保只有一个表单需要令牌验证。
如果个别页面输出不希望进行表单令牌验证,可以在控制器中的输出方法之前动态关闭表单令牌验证,例如:
  1. C('TOKEN_ON',false);
  2. $this->display();
模型类在创建数据对象的同时会自动进行表单令牌验证操作,如果你没有使用create方法创建数据对象的话,则需要手动调用模型的autoCheckToken方法进行表单令牌验证。如果返回false,则表示表单令牌验证错误。例如:
  1. $User = M("User"); // 实例化User对象
  2. // 手动进行令牌验证
  3. if (!$User->autoCheckToken($_POST)){
  4. // 令牌验证错误
  5. }

表单合法性检测

表单合法性检测是3.1版本开始增加的表单提交字段检测机制,你不再需要担心用户在提交表单的时候注入非法字段数据了。表单字段合法性检测需要使用create方法创建数据对象的时候才能生效,有两种方式:

一、属性定义

可以给模型配置insertFields 和 updateFields属性用于新增和编辑表单设置,使用create方法创建数据对象的时候,不在定义范围内的属性将直接丢弃,避免表单提交非法数据。
insertFields 和 updateFields属性的设置采用字符串(逗号分割多个字段)或者数组的方式,例如:
  1. class UserModel extends Model{
  2.     protected $insertFields = array('account','password','nickname','email');
  3.     protected $updateFields = array('nickname','email');
  4. }
设置的字段应该是实际的数据表字段,而不受字段映射的影响。
在使用的时候,我们调用create方法的时候,会根据提交类型自动识别insertFields和updateFields属性:
  1. D('User')->create();
使用create方法创建数据对象的时候,新增用户数据的时候,就会屏蔽'account','password','nickname','email' 之外的字段,编辑的时候就会屏蔽'nickname','email'之外的字段。
下面是采用字符串定义的方式,同样有效:
  1. class UserModel extends Model{
  2.     protected $insertFields = 'account,password,nickname,email';
  3.     protected $updateFields = 'nickname,email';
  4. }

二、方法调用

如果不想定义insertFields和updateFields属性,或者希望可以动态调用,可以在调用create方法之前直接调用field方法,例如,实现和上面的例子同样的作用:
在新增用户数据的时候,使用:
  1. $User = M('User');
  2. $User->field('account,password,nickname,email')->create();
  3. $User->add();
而在更新用户数据的时候,使用:
  1. $User = M('User');
  2. $User->field('nickname,email')->create();
  3. $User->where($map)->save();
这里的字段也是实际的数据表字段。field方法也可以使用数组方式。
如果你的字段比较多,还可以使用field方法的排除功能,例如:
  1. $User->field('status,create_time',true)->create();

变量安全

变量安全获取

对全局系统变量的获取建议采用系统提供的变量获取方法获取,具体可以参考快速入门系列的变量

全局变量过滤

如果你习惯于直接调用$_GET $_POST变量的话,那么或者可以采用ThinkPHP系统内置的对全局变量的安全过滤方式,只需要设置VAR_FILTERS参数。
例如:
  1. 'VAR_FILTERS'=>'htmlspecialchars'
在3.1.2版本开始,安全过滤方法的定义函数需要调整为引用返回的方式,而且能够实现多维数组的递归过滤,例如:
  1. 'VAR_FILTERS'=>'filter_vars'
对应的过滤方法定义如下:
  1. function filter_vars(&$value){
  2.     $value = htmlspecialchars($value);
  3. }

数据安全

防SQL注入

对于WEB应用来说,SQL注入攻击无疑是首要防范的安全问题,系统底层对于数据安全方面本身进行了很多的处理和相应的防范机制,例如:
  1. $User = M("User"); // 实例化User对象
  2. $User->find($_GET["id"]);

即便用户输入了一些恶意的id参数,系统也会强制转换成整型,避免恶意注入。这是因为,系统会对数据进行强制的数据类型检测,并且对数据来源进行数据格式转换。而且,对于字符串类型的数据,ThinkPHP都会进行escape_string处理。
通常的安全隐患在于你的查询条件使用了字符串参数,然后其中一些变量又依赖由客户端的用户输入,要有效的防止SQL注入问题,我们建议:
查询条件尽量使用数组方式,这是更为安全的方式;
如果不得已必须使用字符串查询条件,使用预处理机制;

查询条件预处理

where方法使用字符串条件的时候,支持预处理(安全过滤),并支持两种方式传入预处理参数,例如:
  1. $Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();
或者
  1. $Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();
模型的query和execute方法 同样支持预处理机制,例如:
  1. $model->query('select * from user where id=%d and status=%d',$id,$status);
或者
  1. $model->query('select * from user where id=%d and status=%d',array($id,$status));
execute方法用法同query方法。

防XSS攻击

XSS(跨站脚本攻击)可以用于窃取其他用户的COOKIE信息,要避免此类问题,可以采用如下解决方案:
直接过滤所有的Javascript脚本;
转义Html元字符,使用htmlentities、htmlspecialchars等函数;
系统的扩展函数库提供了XSS安全过滤的remove_xss方法;
新版对URL访问的一些系统变量已经做了XSS处理。

上传安全

网站的上传功能也是一个非常容易被攻击的入口,所以对上传功能的安全检查是尤其必要的。
系统提供的上传扩展类库(ORG.Net.UploadFile)提供了安全方面的支持,包括对文件后缀、文件类型、文件大小以及上传图片文件的合法性检查,确保你已经在上传操作中启用了这些合法性检查。

其他安全建议

下面的一些安全建议也是非常重要的:
对所有公共的操作方法做必要的安全检查,防止用户通过URL直接调用;
不要缓存需要用户认证的页面;
对于关键操作需要检查用户权限;
对用户的上传文件,做必要的安全检查,例如上传路径和非法格式。
如非必要,不要开启服务器的目录浏览权限;
对于项目进行充分的测试,不要生成业务逻辑的安全隐患(这可能是最大的安全问题);

推荐阅读
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 浅解XXE与Portswigger Web Sec
    XXE与PortswiggerWebSec​相关链接:​博客园​安全脉搏​FreeBuf​XML的全称为XML外部实体注入,在学习的过程中发现有回显的XXE并不多,而 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 弹性云服务器ECS弹性云服务器(ElasticCloudServer)是一种可随时自助获取、可弹性伸缩的云服务器,帮助用户打造可靠、安全、灵活、高效的应用环境 ... [详细]
  • 03Spring使用注解方式注入
    基于注解的DI注入1.导包环境搭建:导入aop包(spring-aop-4.1.6.RELEASE.jar)2.创建类3.创建spring.xml配置文件(必须在src目录下)该配 ... [详细]
  • jvm内存区域与溢出为什么学习jvm木板原理,最短的一块板决定一个水的深度,当一个系统垃圾收集成为瓶颈的时候,那么就需要你对jvm的了解掌握。当一个系统出现内存溢出,内存泄露的时候 ... [详细]
  • 跨站的艺术XSS Fuzzing 的技巧
    作者|张祖优(Fooying)腾讯云云鼎实验室对于XSS的漏洞挖掘过程,其实就是一个使用Payload不断测试和调整再测试的过程,这个过程我们把它叫做F ... [详细]
  • 2月4日每日安全热点节日期间某企远程办公遭XRed攻击 ... [详细]
author-avatar
docetaxel
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有