读书笔记--PHP安全编程

2015/08/21

##register_globals的安全性 本特性已自php5.3.0起废弃并自PHP5.4.0起移除,故不作研究。

##不要让不相关的人看到报错信息

只要关闭display_errors就可以做到,如果你希望得到出错信息,可以打开log_errors选项,并在error_log选项中设置出错日志文件的保存路径。

所有的出错报告级别可以在任意级别进行修改。

PHP允许通过set_error_handler()函数指定自己的出错处理函数。

##网站安全设计的一些原则

深度防范:冗余安全措施

最小权限:只能给予每个人完成他本职工作所必须的尽量少的权限。

简单就是美:没有必要的复杂与没有必要的风险一样糟糕。

暴露最小化:数据暴露必须尽量最小化。

##可用性与数据跟踪

平衡风险与可用性:用户操作的友好性与安全措施是一对矛盾,在提高安全性的同时,通常会降低可用性。尽量是安全措施对用户透明。

跟踪数据:不只是要知道它是什么和它在哪里,还要知道它从哪里来,要到哪里去。

##过滤用户输入

过滤输入的步骤:识别输入;过滤输入;区分已过滤及被污染数据

输入是指所有源自外部的数据。一般来说,把session保存位置与数据库看成是输入是更为安全的。

过滤是防止非法数据进入你的应用。

最好的过滤方法是把过滤看成一个检查的过程。请不要试图好心地去纠正非法数据,要让你的用户按你的规则去做,历史证明了试图纠正非法数据往往会导致安全漏洞。

使用一个命名约定或其他可以帮助你正确和可靠地区分已过滤和被污染数据的方法。如:$clean

经常初始化$clean为一个空数组

加入检查及阻止来自外部数据源的变量命名为clean。

##对输出要进行转义

对输出进行转义或对特殊字符进行编码,以保证原意不变。

输出转义三步:识别输出;输出转义;区分已转义与未转义数据

只对已过滤数据进行转义。

对一些常见的输出目标(包括客户端、数据库和URL)的转义,PHP中有内置函数可用。

使用htmlentities()在数据发出前进行转义是最好的方法。使用此函数的最佳方式是指定它的两个可选参数:引号的转义方式及字符集。

使用一个命名参数保存转义数据:$html

对于mysql用户,最好的转义函数时mysql_real_escape_string(),如果你使用的数据库没有PHP内建转义函数可用的话,addslashed()是最后的选择。

##表单与数据安全

数据分类:已过滤数据;被污染数据

所有你自己设定的可信数据,可以认为是已过滤数据。

任何来自远程数据源的数据都是输入,而所有的输入数据都是被污染的,必须在要在使用前对其进行过滤。

##从URL的语义进行攻击

例子:找回密码。

漏洞:在URL中暴露用户名

解决方法:使用session跟踪正确回答问题的用户

##文件上传攻击的防御

上传文件参数数组$_FILES是一个超级全局数组,里面的内容tmp_name,error及size是PHP所提供的

需要对这些参数进行检查。如tmp_name使用is_uploaded_file()函数判断是否为一个上传的文件。

如果希望只把上传的文件移到一个固定位置,可以使用move_uploaded_file() 可以用filesize()函数来校验文件的大小。

最佳的方法是永远尽可能少地去信任。

##跨站脚本攻击的防御 输入和输出要做过滤和转义 htmlentities

##跨站请求伪造CSRF的防御 CSRF(Cross-Site Request Forgery)

CSRF攻击:攻击者盗用了你的身份,以你的名义发送而已请求。

只允许GET请求检索数据,但是不允许它修改服务器上的任何数据。

防御:在客户端页面增加伪随机数

所有表单包含同一个伪随机数 验证码图片 所有表单包含不同的伪随机数

##表单欺骗提交

攻击者可以通过查看网页源代码来获取表单中的action查看POST的目的地,进而推断出POST的绝对地址。然后再伪造一个表单,并取消各种限制进行攻击。

这种攻击是不能防止的。但只要做好数据的过滤,用户就必须遵守你的规则,与攻击者如何提交无关。

##HTTP请求欺骗 即伪造一个HTTP请求。

欺骗HTTP请求的做法并不多,对它不应该过多关注。但这个现象的出现再次强调了过滤输入的重要性和HTTP请求提供的任何信息都是不可信的这个事实。

##不要暴露数据库访问权限

把数据库配置文件放在网站根目录以外的目录下

或者把配置文件后缀改为.php

##防止SQL注入

过滤输入,转义输出

转义发送给数据库的数据

使用占位符

##cookie暴露导致session被劫持

使用cookie而产生的一个风险是用户的cookie会被攻击者所盗窃。如果会话标识保存在cookie中,cookie的暴露就是一个严重的风险,因为它能导致会话劫持。

##session劫持的防御

使用SSL

验证User-Agent

##防止源代码的暴露

把所有包含文件放在网站主目录之外

修改apache/nginx文件,把配置文件当做php文件一样处理

##留心后门URL

后门URL是指虽然无需直接调用的资源能直接通过URL访问。

为了防止后门URL,需要确认所有包含文件保存在网站主目录以外。所有保存在网站主目录下的文件都是必须要通过URL直接访问的。

##阻止文件名被操纵

使用动态包含时目录名或文件名中的部分会保存在一个变量中。比如放在$_GET。

防止的方案:在动态包含时永远不要使用被污染数据。

##文件包含的代码注入攻击

如果引入的外部文件中包含可执行代码(如PHP代码)的话,就会被程序解析,造成攻击。 解决方法:在include和require语句前对数据进行过滤。

##文件目录猜测漏洞

防御方案: 让使用者遵从你制定的规则。(如:文件名只包含字母) basename函数在检查是否有不必要的路径时非常有用。

##打开远程文件的风险

永远不要用被污染的数据去执行一个文件名。坚持过滤输入,同时确信在数据指向另一个文件名之前被过滤即可。

##shell命令注入

可能的话,避免使用shell命令。实在要用的话,确保对构造命令串的数据进行过滤,同时必须要对输出进行转义。

##暴力破解攻击

暴力攻击是一种不使用任何特殊手段而去穷举各种可能性的攻击方式。即穷举攻击法。 限制在上一次验证失败后对同一用户再试尝试的频率。

##密码嗅探和重播攻击

使用SSL可以有效地防止HTTP请求和回应不被暴露。

防止重播攻击:设定受保护资源永久访问权的数据的使用;设定受保护资源访问权的数据的暴露(甚至是只提供临时访问权的数据)

##记住登录状态的做法

永久登录是指在浏览器会话间进行持续验证的机制。

永久登录降低了验证机制的安全性,但它增加了可用性。

应该从三个方面来限制永久登录cookie的使用:cookie需在一周内过期;cookie最好只能用于一次验证(在一次成功验证后即删除或重新生成);在服务端限定cookie在一周内过期。

应该设计一个方法来减轻被捕获的永久登录cookie造成的风险

另一个有用的原则是:在用户执行敏感操作前需要用户提供密码。

需要确认登出系统的用户是确实登出了。(如setcookie('auth', 'DELETED!', time()))

##共享主机的源码安全

此问题没有完美的解决方案。你必须考虑所有你的源码都是公开的,甚至是保存在WEB目录之外的代码也是如此。

最好的办法是把所有的敏感数据存放在数据库中。

保存数据库密码的方案是把你的数据库访问权限保存在一个只有系统管理员才能读取的文件中。

##更优的会话数据安全

把会话信息保存在数据库。(session_set_save_handler

##会话数据注入

此类攻击的原因是因为WEB服务器除了对会话存储目录有读取权限外,还有写入权限。解决这个问题的方法是将会话数据保存在数据库中。

##主机文件目录浏览

攻击者可以写脚本获取主机的文件目录。因为共享服务器上的文件都是公开的。

##PHP的安全模式 PHP的安全模式可以认为是一种深度防范机制。



通过赞赏码赞助此文