安全
Web应用安全
总有一些人会千方百计的想着破坏你的Web应用,提前想办法加强自己的Web应用的安全性非常重要。幸运的是, The Open Web Application Security Project (OWASP) 已经提供详尽的已知安全问题列表和防范对策。 每个关注Web安全的开发者都应该仔细阅读该列表。
数据过滤
永远不要在PHP代码中信任外部输入,在使用之前一定要先过滤和验证,filter_var和filter_input函数可以帮助过滤文本和 验证文本格式(如邮箱地址)。
外部输入可以是:$_GET和$_POST表单输入数据、$_SERVER超级变量中的某些值和通过fopen('php://input', 'r')获取的 HTTP请求体。要记住外部输入不仅仅是用户提交的表单数据,还包括上传和下载的文件、session变量、cookie数据和第三方Web服务提供的 数据等。
当外部数据被存储合并之后,下次读取时,它们仍然算是外部输入,每次在代码中处理的时候,需要问自己是否已经正确过滤,是否可以 信任它们。
数据需要根据不同用处,进行不同的过滤,如果把未经过滤的数据输出到HTML页面,它可以在你的网站里执行HTML和JavaScript!即通常 说的跨站脚本攻击(XSS)。避免XSS的一个策略就是使用strip_tags函数过滤外部输入的所有HTML标签,或者使用htmlentities/ htmlspecialchars转义其中的HTML实体。
另外一个例子是传给命令行命令的选项,这可能非常危险(通常不是一个好主意),不过你可以用内置的escapeshellarg函数过滤命令行的 参数。
最后一个例子是根据外部输入来从文件系统中加载文件的操作,可以通过修改路径中的文件名实施攻击。你需要过滤输入中的”/”, “../”, null bytes, 或其他特殊字符,以防止加载不能公开的包含敏感数据的文件。
数据清洗
数据清洗就是删除或转义外部输入中的非法或不安全字符。比如把外部数据输出到HTML或插入到SQL语句之前,需要先清洗外部输入。 当你通过PDO绑定数据时,它会替你转义输入数据。
有时候需要允许外部数据包含安全的HTML标签,并输出到HTML页面中。这个比较难处理,可以考虑使用其他更严格的格式,如 或BBCode,实在不能的话,可以使用HTML Purifier库来进行数据清洗。
数据验证
数据验证外部输入就是你预期的,如你在处理注册表单时,需要验证email地址、电话号码和年龄等数据
配置文件
在创建应用的配置文件时,请遵循下面的业界最佳实践:
配置文件保存在Web不能直接访问和上传的目录中。
如果配置文件只能放在文档根目录时,请使用.php作为文件名后缀,这样即使直接访问该配置文件,也不会输出配置信息。
配置文件内容应该加密,或者对文件设置访问权限。
注册全局变量
提示:从PHP 5.4.0开始,register_globals配置已经删除,不再生效。保留这个配置,只是提示依赖该配置的应用进行升级。
启用register_globals配置后,$_POST, $_GET和$_REQUEST中的变量自动注册为全局变量,使得应用很难辨别变量的确切来源,从而产生安全漏洞。
例如:$_GET['foo']将注册变量$foo,这会覆盖程序中未声明的同名变量。如果你使用PHP 5.4.0之前的版本,请确保已经把register_globals设置为off。
错误提示
错误日志可以帮助追查应用的Bug,但是也会暴露应用的结构信息而产生安全问题,为此,需要在开发环境和线上环境设置不同的配置,防止 敏感信息的泄漏。
开发环境
要在开发环境显示错误提示,需要在php.ini中配置以下配置项:
display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On
-1表示显示各种错误,包括将来增加的新错误类型,和PHP 5.4中的E_ALL行为相同。
E_STRICT错误级别在5.3.0版本引入,不在E_ALL中,不过5.4.0版本开始,E_ALL包含E_STRICT级别的错误。所以在5.3版本中,要显示 所有错误,需要把error_reporting设置为-1或者E_ALL | E_STRICT。
各PHP版本显示所有错误的配置
< 5.3 -1 or E_ALL
5.3 -1 or E_ALL | E_STRICT
> 5.3 -1 or E_ALL
线上环境
要在线上环境隐藏错误提示,需要在php.ini中配置以下配置项:
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On
这样设置后,线上错误会记录到Web服务器的错误日志中,而不是直接显示给用户。如果想了解更多错误提示相关的设置,请参考手册: