在工作中,由于接触了大量的历史代码,所以需要解决一些历史遗留的安全问题。由于我们网站规模很小,所以遇到的安全问题大部分都集中在网站程序层面,系统级的很少。下面列出了主要的安全漏洞类型:
-
脚本过滤
脚本过滤不干净会导致用户账户被盗发生,如果管理员帐号被盗,网站安全就受到了很威胁。
通常脚本内容都来自我们网站提供的允许使用HTML的地方。如果用户提交内容包含了javascript代码,在其他用户打开时,这些代码会被执行,并且能够获取到用户已经授权了的
cookie
信息。所以我们必须转义或者过滤这些内容。这些过滤现在程序员通常能过注意到,但是有些地方我们缺会忽略。比如用户提交的 HTML 代码中包含了
onload
onclick
等元素属性,这些属性同样会触发 javascript 的执行,同样会让用户的cookie
数据丢失。另外对于可加载资源的元素,我们也需要进行过滤,防止元素资源其实是在执行一段 javascript 代码。
通常这些 javascipt 代码通常会获取用户的合法
cookie
来伪装用户,所以当我们因为一些原因无法进行过滤时,可以考虑将用户授权信息设置成http only
来防止cookie
被非法脚本获取。上面的办法对于存在BUG或漏洞的浏览器是无效的,因此强化方法是将 cookie 与浏览器进行绑定,这样 cookie 即使被盗取后,该授权 cookie 也将会无效。浏览器的识别我可以通过用户IP,用户代理信息以及浏览器canvas信息来确定唯一性。
上面的措施只是对于用户cookie是安全的。对于伪装用户却是无效了,因为恶意脚本在执行后有可能会直接模拟表单提交,修改用户密码。这就是我们下面需要解决的表单授权问题。
-
表单提交没有前期授权
表单授权是一个很重要的步骤,通常我们是在表单页面中增加一个hash字符串来做一个简单授权,当表单提交时,服务器端必须先检查这个字符串是否有效。这样就能防止自动脚本伪装用户进行操作。威胁用户安全。所以通常对于这些数据更改请求我们都建议使用POST的方式来提交,并且每次提交前都需要进行一次授权。当然随机字符串的授权方式对于Ajax提交时也不是十分安全的,只能增加脚本的攻击难度。对于一些十分重要的操作还是需要最安全的方式就是图形验证码,以防止伪装用户进行某些操作的提交。
-
文件上传过滤问题
文件上传检查,通常是根据后缀名来处理,但是当web服务程序有安全问题时,这个判断也不是十分安全的,最简单有效的方法是限制web程序的权限,防止其任意写入文件来避免网站被恶意修改。另外就是限制用户上传文件到指定位置,并控制该位置的执行权限。
我们服务器是nginx+ php-fpm的方式,所以我将php-fpm的执行用户安排成了
apache
这么一个禁止登录的用户,而对于php程序则改成了web
用户,当然他们都属于一个www
用户,所有的文件权限都改成了750
这样,对于apache
用户来说,这些php脚本只能读,而不能做任何修改与上传文件到这些目录。对于需要上传文件的地方,我们需要禁止php的执行或访问。这样能有效防止因为程序问题导致被上传非法文件或者程序被篡改。这个只一个简单的例子,我们还可以使用 SELinux 来进行更强大的控制。
-
数据库过滤问题
数据库的注入通常发生在字符串参数的传入时,对于数字或者日期,我们可以简单判断,而对于字符串则由于其中包含的内容的复杂性而常常让我们的过滤无效。对于 php 与 mysql 的组合,我们可以使用一些引号转义函数来帮助我们解决部分问题,但是也有可能因为程序的问题而无法达到效果,比如在没有检查传入参数类型的情况下,而判断其是数字,而在 SQL 中没有用引号将这个参数包含。为了防止这些情况在历史代码中发生,我们可能可以通过过滤部分SQL的关键字来防止注入可能。因此我还是建议对所有类型参数都使用引号。