From 21b072efecdf61818b989656368f9b3fc1629473 Mon Sep 17 00:00:00 2001 From: xiemengjun Date: Thu, 18 Oct 2012 23:51:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E7=9A=84=E5=B0=8F=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 9.3.md | 14 +++++----- 9.5.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/9.3.md b/9.3.md index 85e4d4bf..5829eddb 100644 --- a/9.3.md +++ b/9.3.md @@ -1,5 +1,5 @@ ##9.3 避免XSS攻击 -随着互联网技术的发展,现在的Web应用都含有大量的动态内容以提高用户体验。所谓动态内容,就是根据用户环境和需要,Web应用程序能够输出相应的内容。动态站点会受到一种名为“跨站脚本攻击”(Cross Site Scripting, 安全专家们通常将其缩写成 XSS)的威胁,而静态站点则完全不受其影响。 +随着互联网技术的发展,现在的Web应用都含有大量的动态内容以提高用户体验。所谓动态内容,就是,Web应用程序能够根据用户环境和需要,输出相应的内容。动态站点会受到一种名为“跨站脚本攻击”(Cross Site Scripting, 安全专家们通常将其缩写成 XSS)的威胁,而静态站点则完全不受其影响。 ##什么是XSS XSS攻击:跨站脚本攻击(Cross-Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。不同于大多数攻击(一般只涉及攻击者和受害者),XSS涉及到三方,即攻击者、客户端与Web应用。XSS的攻击目标是为了盗取客户端的cookie或者其他网站用于识别客户端身份的敏感信息。获取到合法用户的信息后,攻击者甚至可以假冒最终用户与网站进行交互。 @@ -10,23 +10,23 @@ XSS目前主要的手段和目的如下: - 盗用cookie,获取敏感信息。 - 利用植入Flash,通过crossdomain权限设置进一步获取更高权限;或者利用Java等得到类似的操作。 -- 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击者)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作,前段时间新浪微博就遭遇过一次XSS。 +- 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击者)用户的身份执行一些管理动作,或执行一些如:发微博、加好友、发私信等常规操作,前段时间新浪微博就遭遇过一次XSS。 - 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。 - 在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果 ##XSS的原理 -XSS漏洞产生的原因是由于Web应用对用户提交请求的数据未做充分的检查过滤,允许用户在提交的数据中掺入HTML代码(最主要的是“>”、“<”),然后未加编码地输出到第三方用户的浏览器,这些攻击者恶意提交代码会被受害用户的浏览器解释执行。 +Web应用未对用户提交请求的数据做充分的检查过滤,允许用户在提交的数据中掺入HTML代码(最主要的是“>”、“<”),并将未经转义的恶意代码输出到第三方用户的浏览器解释执行,是导致XSS漏洞的产生原因。 接下来以反射性XSS举例说明XSS的过程:现在有一个网站,根据参数输出用户的名称,例如访问url:"http://127.0.0.1/?name=astaxie",就会在浏览器输出如下信息: hello astaxie -那么如果我们传递这样的url:"http://127.0.0.1/?name=",这个时候你就会发现你的浏览器跳出一个弹出框,这说明站点已经存在了XSS漏洞,那么用户如何来获取Cookie呢?也是类似上面的代码,输入如下的url:"http://127.0.0.1/?name=",这样就可以把当前的cookie发送到指定www.xxx.com站点。这样攻击者就可以把类似这样的url进行短域名服务缩短url,然后把这些url通过途径传播开来,被攻击用户一旦点击了这样的url,相应数据就会被发送到收集cookie的脚本中。这样就获得了cookie信息,然后利用Websleuth之类的工具来检查是否能盗取那个账户。 +如果我们传递这样的url:"http://127.0.0.1/?name=alert('astaxie,xss')",这时你就会发现浏览器跳出一个弹出框,这说明站点已经存在了XSS漏洞。那么恶意用户是如何盗取Cookie的呢?与上类似,如下这样的url:"http://127.0.0.1/?name=",这样就可以把当前的cookie发送到指定的站点:www.xxx.com。你也放会说,这样的URL一看就有问题,怎么会有人点击?,是的,这类的URL会让人怀疑,但如果使用短网址服务将之缩短,你还看得出来么?,攻击者将缩短过后的url通过某些途径传播开来,被攻击用户一旦点击了这样的url,相应cookie数据就会被发送事先设定好的站点,这样就盗得了cookie信息,然后就可以利用Websleuth之类的工具来检查是否能盗取那个可怜的用户的账户信息了。 -更加详细的关于XSS的分析大家可以参考这篇文章:http://www.rising.com.cn/newsletter/news/2011-08-18/9621.html 新浪微博XSS事件分析 +更加详细的关于XSS的分析大家可以参考这篇叫做《新浪微博XSS事件分析》的文章(http://www.rising.com.cn/newsletter/news/2011-08-18/9621.html) ##如何预防XSS -其实这个问题很简单,坚决不要相信任何用户输入并过滤所有特殊字符。这样就能消灭绝大部分的XSS攻击。 +答案很简单,坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。这样就能消灭绝大部分的XSS攻击。 目前防御XSS主要有如下几种方式: @@ -42,7 +42,7 @@ XSS漏洞产生的原因是由于Web应用对用户提交请求的数据未做 这样就可以让浏览器解析javascript代码,而不会是html输出。 ##总结 -通过上面的介绍我们发现了XSS漏洞是相当有危害的,我们在开发我们的Web应用的时候,一定要记住过滤数据,特别是在输出到客户端之前,这个是现在行之有效的防止XSS的手段。 +XSS漏洞是相当有危害的,在开发Web应用的时候,一定要记住过滤数据,特别是在输出到客户端之前,这是现在行之有效的防止XSS的手段。 ## links * [目录]() diff --git a/9.5.md b/9.5.md index d6f33844..4c404aa1 100644 --- a/9.5.md +++ b/9.5.md @@ -1,4 +1,87 @@ ##9.5 存储密码 +过去一段时间来, 许多的网站遭遇用户密码数据库泄露事件, 这其中包括顶级的互联网企业–Linkedin, 国内诸如CSDN近600万用户帐号密码外泄,该事件横扫整个国内互联网,并且随后又爆出多玩游戏800万用户资料被泄露 ,另有传言人人网、开心网、天涯社区、世纪佳缘、百合网等社区都有可能成为黑客下一个目标。层出不穷的类似事件对用户会造成巨大的影响,因为人们往往习惯在不同网站使用相同的密码,一家“暴库”,全部遭殃。 + +那么我们作为一个Web应用开发者,在选择密码存储方案时, 容易掉入哪些陷阱, 以及如何避免这些陷阱? + +##普通方案 +目前我们用的最多的密码存储方案是将明文密码做单向哈希后存储,单向哈希算法有一个特征:无法通过哈希后的摘要(digest)恢复原始数据,这也是“单向”二字的来源。常用的单向哈希算法包括SHA-256, SHA-1, MD5等。 + +Go语言对这三种加密算法的实现如下所示: + + //import "crypto/sha256" + h := sha256.New() + io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.") + fmt.Printf("% x", h.Sum(nil)) + + //import "crypto/sha1" + h := sha1.New() + io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.") + fmt.Printf("% x", h.Sum(nil)) + + //import "crypto/md5" + h := md5.New() + io.WriteString(h, "需要加密的密码") + fmt.Printf("%x", h.Sum(nil)) + +单向哈希有两个特性: + +- 1)同一个密码进行单向哈希,得到的总是唯一确定的摘要。 +- 2)计算速度快。随着技术进步,一秒钟能够完成数十亿次单向哈希计算。 + +结合上面两个特点,考虑到多数人所使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合, 然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为`rainbow table`。 + +因此通过单向加密之后存储的数据,和明文存储没有多大区别。因此,一旦网站的数据库泄露,所有用户的密码本身就大白于天下。 +##进阶方案 +通过上面介绍我们知道黑客可以用`rainbow table`来破解哈希后的密码,很大程度上是因为加密时使用的哈希算法是公开的。如果黑客不知道加密的哈希算法是什么,那他也就无从下手了。 + +一个直接的解决办法是,自己设计一个哈希算法。然而,一个好的哈希算法是很难设计的——既要避免碰撞,又不能有明显的规律,做到这两点要比想象中的要困难很多。因此实际应用中更多的是利用已有的哈希算法进行多次哈希。 + +但是单纯的多次哈希,依然阻挡不住黑客。两次 MD5、三次 MD5之类的方法,我们能想到,黑客自然也能想到。特别是对于一些开源代码,这样哈希更是相当于直接把算法告诉了黑客。 + +没有攻不破的盾,但也没有折不断的矛。现在安全性比较好的网站,都会用一种叫做“加盐”的方式来存储密码,也就是常说的 “salt”。他们通常的做法是,先将用户输入的密码进行一次MD5(或其它哈希算法)加密;将得到的 MD5 值前后加上一些只有管理员自己知道的随机串,再进行一次MD5加密。这个随机串中可以包括某些固定的串,也可以包括用户名(用来保证每个用户加密使用的密钥都不一样)。 + + //import "crypto/md5" + //假设用户名abc,密码123456 + h := md5.New() + io.WriteString(h, "需要加密的密码") + + //a等于e10adc3949ba59abbe56e057f20f883e + pwmd5 :=fmt.Sprintf("%x", h.Sum(nil)) + + //指定两个 salt: salt1 = @#$% salt2 = ^&*() + salt1 := "@#$%" + salt2 := "^&*()" + + //salt1+用户名+salt2+MD5拼接 + io.WriteString(h, salt1) + io.WriteString(h, "abc") + io.WriteString(h, salt2) + io.WriteString(h, pwmd5) + + last :=fmt.Sprintf("%x", h.Sum(nil)) + +在两个salt没有泄露的情况下,黑客如果拿到的是最后这个加密串,就几乎不可能推算出原始的密码是什么了。 + +##专家方案 +也许在几年前上面的进阶方案也许是足够安全的方案,因为攻击者没有足够的资源建立这么多的rainbow table。 但是,在今日,因为并行计算能力的提升,这种攻击已经完全可行。 + +故意增加密码计算所需耗费的资源和时间,使得任何人都不可获得足够的资源建立所需的`rainbow table`。 + +这类方案有一个特点,算法中都有个因子,用于指明计算密码摘要所需要的资源和时间,也就是计算强度。计算强度越大,攻击者建立`rainbow table`越困难,以至于不可继续。 + +这里推荐`scrypt`方案,scrypt是由著名的FreeBSD黑客Colin Percival为他的备份服务Tarsnap开发的。 + +目前Go语言里面支持的库http://code.google.com/p/go/source/browse?repo=crypto#hg%2Fscrypt + + dk := scrypt.Key([]byte("some password"), []byte(salt), 16384, 8, 1, 32) + +通过上面的的方法可以获取唯一的相应的密码值,这是目前为止最难破解的。 + +##总结 +看到这里,如果你产生了危机感,那么就行动起来: + +- 1)如果你是普通用户,那么我们建议使用LastPass进行密码存储和生成,对不同的网站使用不同的密码; +- 2)如果你是开发人员, 那么我们强烈建议你采用专家方案进行密码存储。 ## links * [目录]()