From 3f7c3a4394069e25423352dbe5700a52c19ee262 Mon Sep 17 00:00:00 2001 From: xiemengjun Date: Tue, 16 Oct 2012 20:56:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=86=85=E5=AE=B9=EF=BC=8C=E5=AE=8C=E6=88=90=E4=BA=86=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E5=B0=8F=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 9.2.md | 40 +++++++++++++++++++++------------------- 9.3.md | 3 ++- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/9.2.md b/9.2.md index 6b07ac14..6fbfaf2e 100644 --- a/9.2.md +++ b/9.2.md @@ -1,36 +1,36 @@ ##9.2 确保输入过滤 -用户数据的过滤是Web应用安全的基础。它是你验证数据合法性的过程。通过在输入时确认对所有的数据进行过滤,这样就可以避免攻击的数据在你的程序中被误信及误用。大多数Web应用的漏洞最终都是因为没有对用户输入进行恰当过滤造成的。 +过滤用户数据是Web应用安全的基础。它是验证数据合法性的过程。通过对所有的输入数据进行过滤,可以避免恶意数据在程序中被误信或误用。大多数Web应用的漏洞都是因为没有对用户输入的数据进行恰当过滤所引起的。 -这里所指的过滤数据是指三个不同的步骤: +我们介绍的过滤数据分成三个步骤: -- 识别数据,搞清楚需要过滤的数据来自于哪里 -- 过滤数据,弄明白我们需要怎么样的数据 -- 区分已过滤及被污染数据,保证如果存在攻击数据那么过滤之后可以让我们使用更安全的数据 +- 1、识别数据,搞清楚需要过滤的数据来自于哪里 +- 2、过滤数据,弄明白我们需要什么样的数据 +- 3、区分已过滤及被污染数据,如果存在攻击数据那么保证过滤之后可以让我们使用更安全的数据 ##识别数据 -我把识别输入作为第一步是因为如果你不知道它是什么,来自于哪里,你也就不能正确地过滤它。输入是指所有源自外部的数据。例如,所有来自客户端的数据是输入,但客户端并不是唯一的外部数据源,其它如数据库和第三方提供的接口数据等也是外部数据源。 +“识别数据”作为第一步是因为在你不知道数据是什么,它来自于哪里,的前提下,你也就不能正确地过滤它。数据是指所有源自外部的数据。例如:所有来自客户端的数据,但客户端并不是唯一的外部数据源,数据库和第三方提供的接口数据等也可以是外部数据源。 -由用户输入的数据我们通过Go非常容易识别,Go通过`ParseForm`之后,把用户POST和GET的数据全部放在了`r.Form`里面。其它的输入要难识别得多,例如,`r.Header`中的很多元素是由客户端所操纵的。常常很难确认其中的哪些元素组成了输入,所以,最好的方法是把整个map看成用户输入。 +由用户输入的数据我们通过Go非常容易识别,Go通过`r.ParseForm`之后,把用户POST和GET的数据全部放在了`r.Form`里面。其它的输入要难识别得多,例如,`r.Header`中的很多元素是由客户端所操纵的。常常很难确认其中的哪些元素组成了输入,所以,最好的方法是把里面所有的数据都看成是用户输入。(例如`r.Header.Get("Accept-Charset")`这样的也看做是用户输入,虽然这些大多数是浏览器操纵的) ##过滤数据 -在知道数据来源之后,就可以过滤它了。过滤是一个有点正式的术语,它在平时表述中有很多同义词,如验证、清洁及净化。尽管这些大家平时所用的术语稍有不同,但它们都是指的同一个处理:防止非法数据进入你的应用。 +在知道数据来源之后,就可以过滤它了。过滤是一个有点正式的术语,它在平时表述中有很多同义词,如验证、清洁及净化。尽管这些术语稍有不同,但它们都是指的同一个处理:防止非法数据进入你的应用。 -过滤数据有很多种方法,其中有一些安全性较,但最好的方法是把过滤看成是一个检查的过程,在你使用数据之前都检查一下是否符合你的设计。请不要试图好心地去纠正非法数据,要让你的用户按你的规则去做,历史证明了试图纠正非法数据往往会导致安全漏洞。这里举个例子:最近建设银行系统升级之后,密码后面两位是0的,只要输入前面四位就能登录系统一样,这是一个非常严重的漏洞,这个漏洞应该就是纠正非法数据引起的,这种安全漏洞是非常严重的。 +过滤数据有很多种方法,其中有一些安全性较差,最好的方法是把过滤看成是一个检查的过程,在你使用数据之前都检查一下看它们是否是符合设计的合法数据。请不要试图好心地去纠正非法数据,而要让用户按你制定的规则去输入,历史证明了试图纠正非法数据往往会导致安全漏洞。这里举个例子:“最近建设银行系统升级之后,密码后面两位是0的,只要输入前面四位就能登录系统”,这是一个非常严重的漏洞。 -一般过滤数据主要采用如下一些库来操作: +过滤数据主要采用如下一些库来操作: -- strconv包下面的字符串转换,因为我们`r.Form`返回的是字符串,我们有些时候需要固定的整数,就需要使用改包来转换,例如Atoi、ParseBool、ParseFloat、ParseInt等函数。 -- string包下面的一些过滤函数Trim、ToLower、ToTitle等函数,能够获取我们想要的格式信息。 -- regexp包来判断一些复杂的需求,例如是否是Email、生日之类的 +- strconv包下面的字符串转化相关函数,因为从Request中的`r.Form`返回的是字符串,而有些时候我们需要将之转化成整/浮点数,`Atoi`、`ParseBool`、`ParseFloat`、`ParseInt`等函数就可以派上用场了。 +- string包下面的一些过滤函数`Trim`、`ToLower`、`ToTitle`等函数,能够帮助我们按照指定的格式获取信息。 +- regexp包用来处理一些复杂的需求,例如判定输入是否是Email、生日之类。 -过滤数据除了检查验证之外,还可以在可能时用白名单方法。白名单是指你需要假定你正在检查的数据是非法的,除非你能证明它是合法的。使用这个方法,如果出现错误只会导致把合法的数据当成是非法的,尽管不想犯任何错误,但这样总比把非法数据当成合法数据要安全得多。 +过滤数据除了检查验证之外,在特殊时候,还可以采用白名单。即假定你正在检查的数据都是非法的,除非能证明它是合法的。使用这个方法,如果出现错误,只会导致把合法的数据当成是非法的,而不会是相反,尽管我们不想犯任何错误,但这样总比把非法数据当成合法数据要安全得多。 ##区分过滤数据 -如果完成了上面的两步,数据过滤的工作就基本完成了,但是在编写Web应用的时候我们还需要区分已过滤和被污染数据,因为这样可以保证过滤数据的完整性,而不影响输入的数据。我们约定把所有经过滤的数据放入一个叫全局的Map变量中(CleanMap)。你需要用两个重要的步骤来防止被污染数据的注入: +如果完成了上面的两步,数据过滤的工作就基本完成了,但是在编写Web应用的时候我们还需要区分已过滤和被污染数据,因为这样可以保证过滤数据的完整性,而不影响输入的数据。我们约定把所有经过过滤的数据放入一个叫全局的Map变量中(CleanMap)。这时需要用两个重要的步骤来防止被污染数据的注入: - 每个请求都要初始化CleanMap为一个空Map。 - 加入检查及阻止来自外部数据源的变量命名为CleanMap。 -接下来为了巩固这些概念,我们通过一个例子来说明这些概念,请看下面这个表单 +接下来,让我们通过一个例子来巩固这些概念,请看下面这个表单
我是谁: @@ -42,7 +42,7 @@
-在处理这个表单的编程逻辑中,非常容易犯的错误是认为只能提交三个选择中的一个。其实攻击可以模拟POST操作,递交`name=attack`这样的数据,所以我们在处理的时候需要做类似白名单的处理 +在处理这个表单的编程逻辑中,非常容易犯的错误是认为只能提交三个选择中的一个。其实攻击者可以模拟POST操作,递交`name=attack`这样的数据,所以在此时我们需要做类似白名单的处理 r.ParseForm() name := r.Form.Get("name") @@ -51,7 +51,8 @@ CleanMap["name"] = name } -上面代码中我们初始化了一个CleanMap的变量,当判断获取的name在astaxie、herry、marry三个之后,我们把数据存储到了CleanMap之中,这样就可以确保CleanMap["name"]中的数据是合法的,从而在代码的其它部分使用它。当然我们还可以在else部分增加非法数据的处理,一种可能是再次显示表单并提示错误。但是不要试图为了友好而输出被污染的数据。 +上面代码中我们初始化了一个CleanMap的变量,当判断获取的name是`astaxie`、`herry`、`marry`三个中的一个之后 +,我们把数据存储到了CleanMap之中,这样就可以确保CleanMap["name"]中的数据是合法的,从而在代码的其它部分使用它。当然我们还可以在else部分增加非法数据的处理,一种可能是再次显示表单并提示错误。但是不要试图为了友好而输出被污染的数据。 上面的方法对于过滤一组已知的合法值的数据很有效,但是对于过滤有一组已知合法字符组成的数据时就没有什么帮助。例如,你可能需要一个用户名只能由字母及数字组成: @@ -62,7 +63,8 @@ CleanMap["username"] = username } - +##总结 +数据过滤在Web安全中是一个基石的作用,大多数的安全问题都是用于没有过滤数据,验证数据引起的,例如前面小节的CSRF攻击,以及接下来将要介绍的XSS攻击、SQL注入等都是没有很好的数据过滤引起的,因此我们需要特别重视这部分的内容。 ## links * [目录]() diff --git a/9.3.md b/9.3.md index 877f8d85..3afc480f 100644 --- a/9.3.md +++ b/9.3.md @@ -41,10 +41,11 @@ XSS漏洞产生的原因是由于Web应用对用户提交请求的数据未做 - 使用HTTP头指定类型 - Response.Header.Set("Content-Type","text/javascript") + w.Header().Set("Content-Type","text/javascript") 这样就可以让浏览器解析javascript代码,而不会是html输出。 ##总结 +通过上面的介绍我们发现了XSS漏洞是相当有危害的,我们在开发我们的Web应用的时候,一定要记住过滤数据,特别是在输出到客户端之前,这个是现在行之有效的防止XSS的手段。 ## links * [目录]()