一个XSS带来的一些收获和警示&常见安全问题总结

Oct 23, 2014

一个月前我们遭遇了一次XSS,原因很简单:输入内容没有做检查。说起来也很蠢:前端没有检查、写数据库没有检查、Cookie也不是Httponly的,所有可以做的防御措施,我们全部都轻松的避过去了。这样别人轻松的就拿到cookie登录到后台了。

而最近又先后爆出SSL心脏滴血、Bash破壳漏洞等重大的安全问题,所以这一个月我就恶补了一些关于安全的知识,在代码和网站中去是不是以前忽略过的坑坑洼洼。有些东西可以总结一些。很基础但也很容易忽略。

一、常见的攻击方式及防御

1. XSS注入

XSS注入是最常见的、最容易的,但危害性缺不小。对于需要登录的网站,拿到cookie就意味着可以登入后台。如果后台是管理员用的,那意味着网站的大部分信息都暴漏了。如果是用户的后台,一次注入可能就意味着很多用户的私人信息暴漏在了别人面前。

XSS原理简单、手法说起来也不复杂。只要有输入框,没有做过滤,就留给了有心人一个注入代码的可能。通过注入代码调用远程的js文件,可以轻松获取到cookie等信息。

XSS的的基本防御是对用户输入的内容做好过滤,对于一些特殊字符的进行必要的处理。特别是需要写入到数据库里的数据。

2. CSRF攻击

别人诱导你点了一个链接、向后端发了一个请求,这个请求下转走了你支付宝里的钱,这就是CSRF。我登录了A站,A站有扣款的服务。我又登陆了B站,B站有个按钮实际上是A站的扣款链接,我并不知情,基本上就是这样的。

防御CSRF的关键在于后端要判断出请求是不是来自于自己呈现给用户的网页。在客户端的输入框隐藏一个输入框,框里留一个随机数,后端校验这个随机数,就能有效防御绝大部分的CSRF攻击。因为其它的网页和你的网页同时在浏览器存在的时候,从他的网页里请求你的连接时,虽然能带上cookie等信息,但是他的网页却没办法从你的网页里获取到这个随机数。

3. SQL注入

SQL注入与XSS类似,也是从输入入手。但不同于XSS,SQL注入的内容可能并不是在输入框里进行的。一个请求需要根据用户请求的内容查询数据库,就意味着可能会有SQL注入的风险。通过与预期不同的字符串进行查询,构造SQL语句来获取数据库的信息,哪怕是有一个SQL注入的漏洞不小心暴漏给了有心的人,可能整个数据库就要沦陷了。

SQL注入的防御工作也是要对从前端获取到的查询信息进行严格的过滤。对于不在预期之内的字符串进行完善的处理。

4. 被上传webshell

所谓webshell,就是能通过浏览器直接在服务器上操作命令,甚至读取到结果。webshell是由上传而已。比如PHP可以通过system命令或者exec命令执行系统命令。如果有心的人上传一个脚本到你的服务器,脚本中带上了一句:echo system($_GET['cmd']);,很不幸,他能执行任何web服务器和PHP解释器有权限执行的命令。

预防webshell需要对上传文件做严格的限制,严格控制上传文件的格式,检查上传的内容。如果是有特殊必要,也要对上传文件的访问做好严格的限制。

同时也要关注服务器、web服务器和脚本解释器的动态,比如Bash的破壳漏洞、IIS6的解析漏洞,及时防御才能规避风险。

二、开发和管理系统过程中的注意事项

许多事情需要在平时开发和维护的过程中注意,处理好一些上的问题,往往能有效的规避大部分的风险。

1. 特殊文件和特殊路径的问题

不要让不该显示的信息显示出去,不要让不该让人访问的东西让别人看到。

刚搭好环境,有时候习惯随手写个phpinfo.php放那里检查一下,事后忘记了处理,别人正好看到了,猜解路径、或者恰好又拿到了别的把柄,一整个网站基本上也就去了。

一些框架特定的版本爆出来大的漏洞,而你恰好留了version或license文件在网站跟目录,替别人省了很多事情。比如thinkphp曾经有过任意代码执行漏洞。

直接通过svn更新代码,svn早期有些版本会在所有目录下都有.svn目录,有特定的文件命名文件里直接就是代码,而你的web服务器恰好没有解析,整个网站的代码就到了别人手里。即使在新的版本里,根目录下也有个wc.db的文件,而你恰好又没有不允许.svn目录的访问。

管理后台就是一个简单的网站的路径,比如phpmyadmin就是/phpmyadmin,phpmyadmin有几个版本有万能用户名的漏洞,轻轻松松拿到数据库。

项目开发过程中,随手把数据库导出一个sql文件保存在web根目录下面,放到服务器上的时候也没有删除,有人随手去试一试,就把它下载下来了。这是很危险的。

2. 不要使用弱口令

任何时候、任何地方都不要使用弱口令。

像上面所说,即使你的phpmyadmin的版本恰好规避了以上的漏洞,而你安装的时候随手敲了个123456当密码。那基本上等于没有设防。

还有网站后台的admin如果,使用一些简单的网站名称、域名或者常见的数字字母组合当密码,很容易猜解出来。

服务器端的脚本访问数据库也不要用root账户完全权限的账号密码,如果网站被上传webshell,拿到配置文件,而数据库又恰好是超级权限的账户,不近代码暴漏在别人面前,网站也被拖库了。

3. 服务端安全策略与权限分配

如果服务器沦陷了,那基本上任何信息都暴漏在了他人面前,所以做好服务器端的管理尤为重要。登录限制、防暴力猜解、防sqlmap、防端口扫描、监控异常流量和IP能够抵御部分极大的隐患。比如破壳漏洞出现时,有些恶意注入会执行一个ping,如果ping回对方的服务器,你的服务器很快就沦陷到他手里了。如果你恰好禁止了icmp包的output,就能度过一段缓冲期。

在Linux上,每个应用程序都有一个执行的用户,web服务器和脚本解释器的用户权限做好限制、web文件目录做好分配可限制也能防止一些异常命令的执行。

4. 经常检查服务器、数据库等log信息

有时候事情已经发生了,能及时发现及时处理也能把损失降到最低。可怕的时候服务器已经沦陷在别人手里了,你还不知道。

很多时候漏洞和隐患也不是单独存在的,找到一个突破口,往往就能攻陷其它地方。比如在数据库里写入一个webshell语句,然后通过构造查询拿到服务器上的东西。

5. 经常关注安全信息

一个安全问题爆出来之后,不要想当然的认为我这里应该没事,及时检查一下才能有效预防。经常浏览一下乌云和freebuf也能及时获取到相关的资讯。

安全问题是个长期的工作,没有铁打的系统,不是一蹴而就的事情,时时留心最重要。