前言
本文作为作者学习内容,会持续更新,主要是补充自己的浏览器&http知识体系,供大家参考,如果有不同的想法,欢迎大家留言区提出。
XSS攻击
xss攻击是指浏览器中执行恶意脚本。从而导致用户信息泄露。 恶意脚本可以做那些事:
- 窃取cookie信息
- 监听用户行为,比如可以获取用户输入的信用卡等信息,将其发送到恶意服务器
- 通过修改 DOM 伪造假的登录窗口,用来欺骗用户输入用户名和密码等信息
- 在页面内生成浮窗广告,这些广告会严重地影响用户体验
恶意脚本注入的三种方式
储存型 XSS攻击
这种类型是将恶意脚本存储到了服务端,然后客户端执行这些脚本,从而达到攻击的效果。
例如2015 年喜马拉雅就被曝出了存储型 XSS 漏洞。用户在设置专辑名称时,对关键字过滤不严格,用户可以输入script内容,从而导致用户点击专辑后,从而获取到用户的cookie信息。
反射型 XSS攻击
恶意脚本网络请求的一部分。
http://localhost:3000/?xss=<script>alert('你被攻击了')</script>
用户将一段含有恶意代码的请求提交给 Web 服务器,Web 服务器接收到请求时,又将恶意代码反射给了浏览器端,这就是反射型 XSS 攻击。 与存储型XSS攻击不同的是,服务器端不会储存恶意脚本。
基于DOM 型 XSS攻击
不会牵扯到服务器端。通过各种手段将恶意脚本注入到用户的页面中。
这样的劫持方式有很多:WIFI路由器劫持、本地恶意软件等。它们的共同点是在 Web 资源传输过程或者在用户使用页面的过程中修改 Web 页面的数据。
阻止XSS攻击
对输入脚本进行过滤或转码
将关键字符和符号进行转码编译,就不会再执行恶意脚本。
将<script>编译为<script>,恶意脚本中的内容也不会被执行了。
利用HttpOnly
如果cookie中设置了HttpOnly属性,那么通过js脚本无法获取到cookie,这样能有效的防止XSS攻击。
CSP网页安全政策
Content Security Policy,缩写 CSP
CSP实质就是白名单制度,明确告诉客户端,哪些外部资源可以加载,等于提供一个白名单,它的实现和执行全部由浏览器完成,开发者只是提供配置。
www.ruanyifeng.com/blog/2016/0…
- 限制其他域下的资源加载。
- 禁止向其它域提交数据。
- 禁止执行内联脚本和未授权的脚本
- 提供上报机制,能帮助我们及时发现 XSS 攻击。
CSRF攻击
“别点那个链接,小心有病毒”
CSRF(Cross-site request forgery), 即跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前的登录状态发起跨站请求,从而可以做一些坏事。
和 XSS 不同的是,CSRF 攻击不需要将恶意代码注入用户的页面,仅仅是利用服务器的漏洞和用户的登录状态来实施攻击。
攻击流程
1.用户打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B(跳转页面是会携带cookie信息的);
4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行(比如转账)。
实现CSRF攻击的三种方式
自动发送GET请求
<img src="https://×××.com/api?user=hacker&ip=122" />
用户登录过的安全页面,进入恶意页面后,页面自动加载,浏览器会自动发起img请求资源,自动发送了 get 请求,这个请求会自动带上关于 xxx.com 的 cookie 信息(如果你已经在 xxx.com 中登录过)。
如果服务器端没有对请求做出判断的话,它可能认为发请求的是一个正常的用户,因为携带了相应的 cookie,然后进行相应的各种操作,可以是转账汇款以及其他的恶意操作。
自动POST请求
<!-- 自动提交脚本 -->
<form id='hacker-form' action="https://xxx.com/info" method="POST">
<input type="hidden" name="user" value="hhh" />
<input type="hidden" name="number" value="100" />
</form>
<script>document.getElementById('hacker-form').submit();</script>
在页面中构建了一个隐藏的表单,用户打开页面后,表单会自动被执行,然后请求a网站的接口,进行一些操作。
引诱用户点击链接
<a href="https://xxx/info?user=hhh&number=100" taget="_blank">点击查看美女图片</a>
点击后,自动发送 get 请求,接下来和自动发 GET 请求部分同理。
发起CSRF攻击的三个必要条件
• 目标站点一定有CSRF漏洞
• 用户要登录过目标站点,并且在浏览器上保持有该站点的登录状态
• 需要用户打开一个第三方站点,可以是黑客的站点,也可以是一些论坛
防止CSRF攻击方法
利用Cookie的SameSite属性
CSRF 攻击都是从第三方站点发起的,要防止 CSRF 攻击,我们最好能实现从第三方站点发送请求时禁止 Cookie 的发送,因此在浏览器通过不同来源发送 HTTP 请求时,有如下区别:
• 如果是从第三方站点发起的请求,那么需要浏览器禁止发送某些关键 Cookie 数据到服务器;
• 如果是同一个站点发起的请求,那么就需要保证 Cookie 数据正常发送。 Cookie 的SameSite属性用来限制第三方 Cookie。
set-cookie: 1P_JAR=2019-10-20-06; expires=Tue, 19-Nov-2019 06:36:21 GMT; path=/; domain=.google.com; SameSite=none
SameSite可以设置为三个值,Strict、Lax和None。
a. Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。
b. 在Lax模式,就宽松一点了,但是只能在 get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。
c. 在None模式下,也就是默认模式,请求会自动携带上 Cookie。
验证来源站点
在服务器端验证请求来源的站点.由于 CSRF 攻击大多来自于第三方站点,因此服务器可以禁止来自第三方站点的请求。
这就需要要用到请求头中的两个字段: Origin和Referer。
Referer 是 HTTP 请求头中的一个字段,记录了该 HTTP 请求的来源地址;虽然可以通过 Referer 告诉服务器 HTTP 请求的来源,但是有一些场景是不适合将来源 URL 暴露给服务器的,因此浏览器提供给开发者一个选项,可以不用上传 Referer 值,具体可参考 Referrer Policy。
Origin 属性只包含了域名信息,并没有包含具体的 URL 路径,这是 Origin 和 Referer 的一个主要区别。Origin 的值之所以不包含详细路径信息,是有些站点因为安全考虑,不想把源站点的详细路径暴露给服务器。
服务器的策略是优先判断 Origin,如果请求头中没有包含 Origin 属性,再根据实际情况判断是否使用 Referer 值。 当然,这两者都是可以伪造的,通过 Ajax 中自定义请求头即可,安全性略差。
CSRF Token
CSRF Token一般可以分为两步: 第一步,在浏览器向服务器发起请求时,服务器生成一个 CSRF Token(服务器生成的字符串)。然后将该字符串植入到返回的页面中。
<!DOCTYPE html>
<html>
<body>
<form action="https://time.geekbang.org/sendcoin" method="POST">
<input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn">
<input type="text" name="user">
<input type="text" name="number">
<input type="submit">
</form>
</body>
</html>
第二步,在浏览器端要发送请求,就必须带上 CSRF Token,然后服务器会验证该 Token 是否合法。如果是从第三方站点发出的请求,那么将无法获取到 CSRF Token 的值,所以即使发出了请求,服务器也会因为 CSRF Token 不正确而拒绝请求。
点击劫持攻击
点击劫持是⼀种视觉欺骗的攻击⼿段。攻击者将需要攻击的⽹站通过 iframe 嵌套的⽅式嵌⼊⾃⼰的⽹⻚中,并将 iframe 设置为透明,在⻚⾯中透出⼀个按钮诱导⽤户点击。
防范措施
判断当前窗口是不是顶层窗口
网站1
<script>
// self 是对当前窗口自身引用 与window属性是等价的
// top返回顶层窗口 即浏览器窗口
// 判断的是self与top是不是都指向的window对象,如果是被iframe引用的话,top值是报错的。
if(self === top){
// 随意展示
}else{
document.body.innerHTML='hi!我的页面是不允许iframe访问的'
// top.location = self.location // 返回网站1这个网页
}
</script>
X-FRAME-OPTIONS响应头
X-FRAME-OPTIONS是⼀个 HTTP 响应头。这个 HTTP 响应头就是为了防御⽤ iframe嵌套的点击劫持攻击。
该响应头有三个值可选,分别是:
- DENY,表示⻚⾯不允许通过 iframe 的⽅式展示
- SAMEORIGIN,表示⻚⾯可以在相同域名下通过 iframe 的⽅式展示
- ALLOW-FROM,表示⻚⾯可以在指定来源的 iframe 中展示