一、XSS攻击
1、解释
xss是指攻击者在目标网站的网页上植入恶意代码,从而对正常用户进行劫持、获取用户隐私信息。
2、案例
假设有一个博客网站,允许用户输入评论,然后别的用户可以获取其他用户的评论。
前端页面:
<!DOCTYPE html> <html> <head> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script>function addComment() { var kkk = $("#add").val() $.ajax({ url: "http://localhost:8081/add", type: 'post', dataType: 'text', data: kkk, success: function() { alert("提交成功") }, error: function(msg) { alert("error:" + msg); } }) }</script> </head> <body> <h1>xss:</h1> <div> <input type="text" id="add" placeholder="输入评论"> <button type="button" onclick="addComment()">提交</button></div> </body>
</html>
func main() {
//简单起见,充当数据库 var comment string http.HandleFunc("/get", func(writer http.ResponseWriter, request *http.Request) { header := writer.Header() header.Add("Content-Type","text/html; charset=UTF-8") header.Add("Access-Control-Allow-Origin","*") header.Add("Access-Control-Allow-Methods","POST,GET") writer.WriteHeader(http.StatusOK) _, _ = writer.Write([]byte(comment)) }) http.HandleFunc("/add", func(writer http.ResponseWriter, request *http.Request) { s,_ := ioutil.ReadAll(request.Body) comment = string(s) header := writer.Header() header.Add("Content-Type","text/html; charset=UTF-8") header.Add("Access-Control-Allow-Origin","*") header.Add("Access-Control-Allow-Methods","POST,GET") writer.WriteHeader(http.StatusOK) }) http.ListenAndServe(":8081",nil)
}
攻击者评论时,输入以下评论内容:
然后一个正常用户通过url(http://localhost:8081/get)访问该评论,导致被攻击
3、防范
通过前面的介绍可以得知,XSS 攻击有两大要素:
- 攻击者提交恶意代码。
- 浏览器执行恶意代码。
所有可以从以下方面进行防范:
1、对于用户的输入参数和服务端输出到HTML的结果都进行检查,进行必要的转义;
2、改成纯前端渲染,把代码和数据分隔开。
纯前端渲染的过程:
- 浏览器先加载一个静态 HTML,此 HTML 中不包含任何跟业务相关的数据。
- 然后浏览器执行 HTML 中的 JavaScript。
- JavaScript 通过 Ajax 加载业务数据,调用 DOM API 更新到页面上。
在纯前端渲染中,我们会明确的告诉浏览器:下面要设置的内容是文本(.innerText
),还是属性(.setAttribute
),还是样式(.style
)等等。浏览器不会被轻易的被欺骗,执行预期外的代码了。
但纯前端渲染还需注意避免 DOM 型 XSS 漏洞(例如 onload
事件和 href
中的 javascript:xxx
等,请参考下文”预防 DOM 型 XSS 攻击“部分)。
3、CSP
CSP的意义:防XSS等攻击的利器。CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置。CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。
二、CSRF攻击
1、解释
CSRF(Cross-site request forgery)跨站请求伪造:攻击者通过邮件、广告链接诱导受害者进入第三方网站。在第三方网站中,攻击者向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证(cookie),一般网站都是直接根据cookie判断是否是合法登录,由于受害者的cookie已经被获取了,所以被攻击网站就会认为是合法用户。这样就完成了冒充用户,并且对被攻击的网站执行某项操作的目的。
一次典型的CSRF攻击有着如下的流程:
- 李四登录了网站 helloworld.com,并保留了登录凭证在浏览器中(Cookie)。
- 法外狂徒张三通过邮件、小广告等手段引诱李四访问了网站 csrf.com。
- 法外狂徒张三通过网站 csrf.com 向 helloworld.com 发送了一个请求:helloworld.com/action=xx。这…
- helloworld.com 接收到请求后,根据cookie对请求者进行身份验证,由于cookie是合法的,helloworld.com就是认为是合法用户。
- 法外狂徒张三就以受害者的名义执行了请求。
- 攻击完成,法外狂徒张三在受害者不知情的情况下,冒充受害者执行了操作。例如转账等高危操作。
2、案例
首先我们写一个服务端响应:
func main() { var num = 10
http.HandleFunc("/reduce", func(writer http.ResponseWriter, request *http.Request) { //验证cookie,成功num-- cookie,_ := request.Cookie("id") if nil == cookie{ writer.WriteHeader(http.StatusOK) fmt.Fprint(writer,"cookie is nil") } else if cookie.Value == "hahaha"{ num-- writer.WriteHeader(http.StatusOK) fmt.Fprint(writer,num) } })
// 这里假设用户是登录成功了,进入页面后,服务端种了一个cookie
http.HandleFunc("/view", func(writer http.ResponseWriter, request *http.Request) {
http.SetCookie(writer,&http.Cookie{
Name: "id",
Value: "hahaha",
})
writer.WriteHeader(http.StatusOK)
fmt.Fprint(writer,num)
})http.ListenAndServe(":8081",nil)
}
第一步:
我们将如下链接="http://localhost:8081/reduce"通过邮件发送给被攻击用户,假设用户点击了,结果将如下:
请求失败了,然后假设用户先访问了链接="http://localhost:8081/view",再访问的上述链接呢?
成功让值减一了,达到了攻击目的。
3、防范
- CSRF(通常)发生在第三方域名。
- CSRF攻击者不能获取到Cookie等信息,只是使用。
针对这两点,我们可以专门制定防护策略,如下:
- 阻止不明外域的访问
- 同源检测
- Samesite Cookie
- 提交时要求附加本域才能获取的信息
- CSRF Token
- 双重Cookie验证
同源检测
既然CSRF大多来自第三方网站,那么我们就直接禁止外域(或者不受信任的域名)对我们发起请求。
在HTTP协议中,每一个异步请求都会携带两个Header,用于标记来源域名:
- Origin Header
- Referer Header
这两个Header在浏览器发起请求时,大多数情况会自动带上,并且不能由前端自定义内容。 服务器可以通过解析这两个Header中的域名,确定请求的来源域。
==虽然CSRF大多数情况下来自第三方域名,但并不能排除本域发起。如果攻击者有权限在本域发布评论(含链接、图片等,统称UGC),那么它可以直接在本域发起攻击,这种情况下同源策略无法达到防护的作用。==
CSRF Token
前面讲到CSRF的另一个特征是,攻击者无法直接窃取到用户的信息(Cookie,Header,网站内容等),仅仅是冒用Cookie中的信息。
而CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,也可以防范CSRF的攻击。
原理
CSRF Token的防护策略分为三个步骤:
1.将CSRF Token输出到页面中
2.页面提交的请求携带这个Token
3.服务器验证Token是否正确