diff --git a/8.3.md b/8.3.md index 33718b3a..b3f6b86c 100644 --- a/8.3.md +++ b/8.3.md @@ -96,15 +96,10 @@ Go没有为REST提供直接支持,但是因为RESTful是基于HTTP协议实现 http.ListenAndServe(":8088", nil) } - - -上面的代码我们演示如何编写一个REST的应用,我们访问的资源是用户,然后我们通过不同的method来访问不同的函数,这里我们使用了一个第三方库`github.com/drone/routes`,这个库实现了方便的路由规则映射,我们在上面章节也介绍过可以实现自定义的路由器,这个库就实现了自定义的路由,我们可以很方便的实现REST的架构。通过上面的代码我们知道REST就是根据不同的method访问同一个资源的时候实现不同的逻辑处理。 +上面的代码演示了如何编写一个REST的应用,我们访问的资源是用户,我们通过不同的method来访问不同的函数,这里使用了第三方库`github.com/drone/routes`,在前面章节我们介绍过如何实现自定义的路由器,这个库实现了自定义路由和方便的路由规则映射,通过它,我们可以很方便的实现REST的架构。通过上面的代码可知,REST就是根据不同的method访问同一个资源的时候实现不同的逻辑处理。 ##总结 -REST是一种架构风格,汲取了WWW的成功经验:无状态,以资源为中心,充分利用HTTP协议和URI协议,提供统一的接口定义,使得它作为一种设计Web服务的方法而变得流行。在某种意义上,通过强调URI和HTTP等早期Internet标准,REST是对大型应用程序服务器时代之前的Web方式的回归。目前Go对于REST的支持还是很简单的,通过实现自定义的路由规则,我们就可以实现不同的method实现不同的handle,这样就实现了REST的架构。 - - - +REST是一种架构风格,汲取了WWW的成功经验:无状态,以资源为中心,充分利用HTTP协议和URI协议,提供统一的接口定义,使得它作为一种设计Web服务的方法而变得流行。在某种意义上,通过强调URI和HTTP等早期Internet标准,REST是对大型应用程序服务器时代之前的Web方式的回归。目前Go对于REST的支持还是很简单的,通过实现自定义的路由规则,我们就可以为不同的method实现不同的handle,这样就实现了REST的架构。 ## links * [目录]() diff --git a/9.1.md b/9.1.md index d946379e..6d2ee627 100644 --- a/9.1.md +++ b/9.1.md @@ -1,11 +1,94 @@ -##9.1 预防session定置 -我们在前面小节介绍过session,它是用来实现在不同的请求之间的会话状态持续,为了保证session有效,用户的每一次请求都必须包含一个能够唯一标识回话的sessionID。 +##9.1 预防CSRF攻击 +##什么是CSRF +CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。 +那么CSRF到底能够干嘛呢?你可以这样简单的理解:攻击者可以盗用你的登陆信息,以你的身份模拟发送各种请求。攻击者只要借助少许的社会工程诡计,例如通过QQ聊天软件发送的链接(有些还伪装成短域名,用户无法分辨),攻击者就能迫使一个Web应用程序的用户去执行攻击者选择的操作。例如,如果用户登录网络银行去查看其存款余额,他没有退出网络银行系统就点击了一个QQ好友发给他的一个链接地址,那么该用户在网络银行帐户中的资金就有可能被转移到攻击者指定的帐户中。 + +所以当CSRF针对普通用户发动攻击时,将对终端用户的数据和操作指令构成严重的威胁;当受攻击的终端用户具有管理员帐户的时候,CSRF攻击将危及整个Web应用程序。 + +##CSRF的原理 +下图简单阐述了CSRF攻击的思想 + +![](images/9.1.csrf.png?raw=true) + +从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤 : + +- 1.登录受信任网站A,并在本地生成Cookie 。 +- 2.在不登出A的情况下,访问危险网站B。 + +看到这里,读者也许会问:“如果我不满足以上两个条件中的一个,就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生: + +- 你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站,特别现在浏览器都是支持多tab的。 +- 你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。 +- 上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。 + +因此对于用户来说很难避免在登陆一个网站之后点击一些链接进行其他操作,所以随时可能成为CSRF的受害者。 + +CSRF攻击主要是因为Web的隐式身份验证机制,Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。 + +##如何预防CSRF +通过上面的介绍读者是否觉得这个攻击很恐怖,意识到恐怖是个好事情,这样会促使你接着往下看如何改进和防止类似的漏洞出现。 + +我总结了一下看到的资料,CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。 + +服务端的CSRF方式方法很多样,但总的思想都是一致的,预防CSRF主要从2个方面入手,分别是: + +- 1、正确使用GET,POST和Cookie; +- 2、在非GET请求中增加伪随机数; + +我们上一章介绍过REST方式的Web应用,一般而言,普通的Web应用都是以GET、POST为主,还有一种请求是Cookie方式。我们设计应用的时候一般都是如下方式设计: + +1、GET常用在查看,列举,展示的时候; + +2、POST常用在下达订单,改变一个资源的属性或者做其他一些事情; + +那么我们就指定死我们需要访问的资源的访问方式,我就以Go语言举例来说明如何怎么来限制访问的某些方法只能为POST或者GET: + + mux.Get("/user/:uid", getuser) + mux.Post("/user/:uid", modifyuser) + +这样做好之后,我们上面图示中GET方式的CSRF就可以防止了,因为我们限定了修改只能使用POST,当GET方式请求时我们不响应,这样就能解决问题了吗?当然不是,因为POST也是可以模拟的。 + +那么我们就需要实施第二步,在非GET方式的请求中增加随机数,这个大概有三种方式来进行: + +- 为每个用户生成一个唯一的cookie token,所有表单都包含同一个伪随机值,这种方案最简单,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败,但是由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,所以这个方案必须要在没有XSS的情况下才安全。 +- 每个请求使用验证码,这个方案是完美的,但是在实施过程中就不大可能,易用性上面相当的差。 +- 不同的表单包含一个不同的伪随机值,这个我们在4.4小节介绍过如何防止表单多次递交,我们可以复用那边的代码,实现如下: + + 生成随机数token + + h := md5.New() + io.WriteString(h, strconv.FormatInt(crutime, 10)) + io.WriteString(h, "ganraomaxxxxxxxxx") + token := fmt.Sprintf("%x", h.Sum(nil)) + + t, _ := template.ParseFiles("login.gtpl") + t.Execute(w, token) + + 输出token + + + + 验证token + + r.ParseForm() + token := r.Form.Get("token") + if token != "" { + //验证token的合法性 + } else { + //不存在token报错 + } + +这样基本就实现了安全的POST,但是也许你会说如果破解了token的算法呢,按照理论上是,但是实际上破解是基本不可能的,因为有人曾计算过,暴力破解该串大概需要2的11次方时间。 + +##总结 +跨站请求伪造,即CSRF,是一种非常危险的Web安全威胁,它被Web安全界称为“沉睡的巨人”,其威胁程度由此“美誉”便可见一斑。本小节不仅对跨站请求伪造本身进行了简单介绍,还详细说明造成这种漏洞的原因所在,然后以此提了一些防范该攻击的建议,希望对读者编写安全的Web应用能够有所启发。 + ## links * [目录]() * 上一节: [安全与加密](<9.md>) - * 下一节: [避免SQL注入](<9.2.md>) + * 下一节: [确保输入过滤](<9.2.md>) ## LastModified * $Id$ \ No newline at end of file diff --git a/9.2.md b/9.2.md index 55735cfb..307e8e23 100644 --- a/9.2.md +++ b/9.2.md @@ -1,9 +1,9 @@ -##9.2 避免SQL注入 +##9.2 确保输入过滤 ## links * [目录]() - * 上一节: [预防session定置](<9.1.md>) - * 下一节: [避免跨站点脚本](<9.3.md>) + * 上一节: [预防CSRF攻击](<9.1.md>) + * 下一节: [避免XSS攻击](<9.3.md>) ## LastModified * $Id$ \ No newline at end of file diff --git a/9.3.md b/9.3.md index 2f07c469..e7f05f88 100644 --- a/9.3.md +++ b/9.3.md @@ -1,9 +1,9 @@ -##9.3 避免跨站点脚本 +##9.3 避免XSS攻击 ## links * [目录]() - * 上一节: [避免SQL注入](<9.2.md>) - * 下一节: [确保输入过滤](<9.4.md>) + * 上一节: [确保输入过滤](<9.2.md>) + * 下一节: [避免SQL注入](<9.4.md>) ## LastModified * $Id$ \ No newline at end of file diff --git a/9.4.md b/9.4.md index 385587d0..bff4612b 100644 --- a/9.4.md +++ b/9.4.md @@ -1,8 +1,8 @@ -##9.4 确保输入过滤 +##9.4 避免SQL注入 ## links * [目录]() - * 上一节: [避免跨站点脚本](<9.3.md>) + * 上一节: [避免XSS攻击](<9.3.md>) * 下一节: [存储密码](<9.5.md>) ## LastModified diff --git a/9.md b/9.md index 64a669a3..4e33aa05 100644 --- a/9.md +++ b/9.md @@ -1,21 +1,21 @@ ##9 安全与加密 无论是开发Web应用的开发者还是企图利用Web应用漏洞的攻击者,对于Web程序安全这个话题都给予了越来越多的关注。特别是最近CSDN密码泄露事件,更是让我们对Web安全这个话题更加重视,所有人都谈密码色变,都开始检测自己的系统是否存在漏洞。那么我们作为一名Go程序的开发者,一定也需要知道我们的应用程序随时会成为众多攻击者的目标,并提前做好防范的准备。 -很多Web应用程序中的安全问题都是由于轻信了第三放提供的数据造成的。比如对于用户的输入数据,在对其进行验证之前都应该将其视为不安全的数据。如果直接把这些不安全的数据输出到客户端,就可能造成跨站脚本攻击(XSS)的问题。如果把不安全的数据用于数据库查询,那么就可能造成SQL注入问题,我们将会在9.2、9.3小节介绍如何避免这些问题。 +很多Web应用程序中的安全问题都是由于轻信了第三放提供的数据造成的。比如对于用户的输入数据,在对其进行验证之前都应该将其视为不安全的数据。如果直接把这些不安全的数据输出到客户端,就可能造成跨站脚本攻击(XSS)的问题。如果把不安全的数据用于数据库查询,那么就可能造成SQL注入问题,我们将会在9.3、9.4小节介绍如何避免这些问题。 -在使用第三方提供的数据,包括用户提供的数据时,首先检验这些数据的合法性非常重要,这个过程叫做过滤,我们将在9.4小节介绍如何保证对所有输入的数据进行过滤处理。 +在使用第三方提供的数据,包括用户提供的数据时,首先检验这些数据的合法性非常重要,这个过程叫做过滤,我们将在9.2小节介绍如何保证对所有输入的数据进行过滤处理。 -过滤输入和转义输出并不能解决所有的安全问题,我们将会在9.1讲解的session定置攻击,会导致受骗者使用攻击者选定的sessionID实施攻击破坏行为。 +过滤输入和转义输出并不能解决所有的安全问题,我们将会在9.1讲解的CSRF攻击,会导致受骗者发送攻击者指定的请求从而造成一些破坏。 与安全加密相关的,能够增强我们的Web应用程序的强大手段就是加密,CSDN泄密事件就是因为密码保存的是明文,使得攻击拿手库之后就可以直接实施一些破坏行为了。不过,和其他工具一样,加密手段也必须运用得当。我们将在9.5小节介绍如何存储密码,如何让密码存储的安全。 加密的本质就是扰乱数据,某些不可恢复的数据扰乱我们称为单项加密或者散列算法。另外还有一种双向加密方式,也就是可以对加密后的数据进行解密。我们将会在9.6小节介绍如何实现这种双向加密方式。 ## 目录 - * 1 [预防session定置](9.1.md) - * 2 [避免SQL注入](9.2.md) - * 3 [避免跨站点脚本](9.3.md) - * 4 [确保输入过滤](9.4.md) + * 1 [预防CSRF攻击](9.1.md) + * 2 [确保输入过滤](9.2.md) + * 3 [避免XSS攻击](9.3.md) + * 4 [避免SQL注入](9.4.md) * 5 [存储密码](9.5.md) * 6 [加密和解密数据](9.6.md) * 7 [小结](9.7.md) @@ -23,7 +23,7 @@ ## links * [目录]() * 上一章: [第八章总结](<8.5.md>) - * 下一节: [预防session定置](<9.1.md>) + * 下一节: [预防CSRF攻击](<9.1.md>) ## LastModified * $Id$ \ No newline at end of file diff --git a/images/9.1.csrf.png b/images/9.1.csrf.png new file mode 100644 index 00000000..8fd35a0a Binary files /dev/null and b/images/9.1.csrf.png differ diff --git a/preface.md b/preface.md index 82a087c5..70d7ff48 100644 --- a/preface.md +++ b/preface.md @@ -53,10 +53,10 @@ - 8.4 [RPC](8.4.md) - 8.5 [小结](8.5.md) * 9.[安全与加密](9.md) - - 9.1 [预防session定置](9.1.md) - - 9.2 [避免SQL注入](9.2.md) - - 9.3 [避免跨站点脚本](9.3.md) - - 9.4 [确保输入过滤](9.4.md) + - 9.1 [预防CSRF攻击](9.1.md) + - 9.2 [确保输入过滤](9.2.md) + - 9.3 [避免XSS攻击](9.3.md) + - 9.4 [避免SQL注入](9.4.md) - 9.5 [存储密码](9.5.md) - 9.6 [加密和解密数据](9.6.md) - 9.7 [小结](9.7.md)