web security: 安全的本质&浏览器安全&XSS&CSRF&点击劫持&HTML5 安全

2024-01-10

前言

记录一下学习web安全的旅程,不过话又说回来,主要是看《白帽子讲web安全》的书,做一下自己感觉有用的记录(🦑
话又说回来,现在看这本书,只能用于了解web常见的安全问题和道哥的思路了,实践里面的内容已经不太可能,毕竟过去10年了。

1. 安全的本质

从安全的角度来看,我们将不同重要程度的区域划分出来: 通过一个安全检查(过滤、净化)的过程,可以梳理未知的人或物,使其 变得可信任。被划分出来的具有不同信任级别的区域,我们称为信任域, 划分两个不同信任域之间的边界,我们称为信任边界。
数据从高等级的信任域流向低等级的信任域,是不需要经过安全检查的; 数据从低等级的信任域流向高等级的信任域,则需要经过信任边界的安全 检查。
安全问题的本质是信任的问题
一切的安全方案设计的基础,都是建立在信任关系上的。我们必须相信一 些东西,必须有一些最基本的假设,安全方案才能得以建立;如果我们否 定一切,安全方案就会如无源之水,无根之木,无法设计,也无法完成

1.1 安全三要素

机密性(confidentiality):即要求数据不会被泄露
完整性(integrity): 即要求数据不会被篡改
可用性(avaliablity):即服务可用,不会被打挂

1.2 安全评估

分析安全问题,主要分为四个阶段
资产等级划分、威胁分析、风险分析、确认解决方案。

1.2.1 资产等级划分

资产等级划分,顾名思义了,以互联网公司为例,最重要的资产当然是用户数据,其次就是代码、员工信息,等等
虽然这些资产都很重要,但是我们也需要分出三六九等
当完成资产等级划分后,对要保护的目标已经有了一个大概的了解,接下来就是要划分信任域和信任边界了。通常我们用一种最简单的划分方式,就是从网络逻辑上来划分。比如最重要的数据放在数据库里,那么把数据库的服务器圈起来;Web应用可以从数据库中读/写数据,并对外提供服务,那再把Web服务器圈起来;最外面是不可信任的Internet。
在这种情况,就需要再每个边界进行安全检查。

1.2.2 威胁分析

可能造成危害的来源叫做威胁
什么是威胁分析?威胁分析就是把所有的威胁都找出来。怎么找?一般是采用头脑风暴法。
当然,也有一些比较科学的方法,比如使用一个模型,帮助我们去想,在哪些方面有可能会存在威胁,这个过程能够避免遗漏,这就是威胁建模。
比如微软的STRIDE模型,它把威胁分为六类:

1.2.3 风险分析

可能出现的损失叫做风险
DREAD模型用于衡量风险大小

1.2.4 确认解决方案

安全评估的产出物,就是安全解决方案。解决方案一定要有针对性,这种 针对性是由资产等级划分、威胁分析、风险分析等阶段的结果给出的
一个优秀的安全方案应该具备以下特点:

• 能够有效解决问题;
• 用户体验好;
• 高性能;
• 低耦合;
• 易于扩展与升级。

1.3 对解决方案有帮助的几个原则

1.3.1 Secure By Default原则

本质上是多使用白名单而不是黑名单
在选择使用白名单时,需要注意避免出现类似通配符的问题。

1.3.2 最小权限原则

最小权限原则要求系统只授予主体必要的权限,而不要过度授权,这样能有效地减少系统、网络、应用、数据库出错的机会。
说白了,就是没必要的权限不要给

1.3.3 纵深防御原则

纵深防御包含两层含义:
首先,要在各个不同层面、不同方面实施安全方案,避免出现疏漏,不同安全方案之间需要相互配合,构成一个整体;其次,要在正确的地方做正确的事情,即:在解决根本问题的地方实施针对性的安全方案。

1.3.4 数据与代码分离原则

字面意思
数据不能与代码放在一起

1.3.5 不可预测性原则

不可预测性(Unpredictable),能有效地对抗基于篡改、伪造的攻击,像ASLR就是不可预测性的最直接展示

2. 浏览器安全

2.1 同源策略

同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也最基 本的安全功能
浏览器的同源策略,限制了来自不同源的“document”或脚本,对当 前“document”读取或设置某些属性。
这一策略极其重要,试想如果没有同源策略,可能a.com的一段JavaScript脚本,在b.com未曾加载此脚本时,也可以随意涂改b.com的页面(在浏览器的显示中)。
同源其实指的是相同的访问协议、相同的域名、相同的端口
需要注意的是,对于当前页面来说,页面内存放JavaScript文件的域并不 重要,重要的是加载JavaScript页面所在的域是什么
换言之,a.com通过以下代码:

<script src=http://b.com/b.js ></script>

加载了b.com上的b.js,但是b.js是运行在a.com页面中的,因此对于当前 打开的页面(a.com页面)来说,b.js的Origin就应该是a.com而非 b.com。
在浏览器中,<script>、<img>、<iframe>、<link>等标签都可以 跨域加载资源,而不受同源策略的限制。
这些带“src”属性的标签每次加载时,实际上是由浏览器发起了一次GET请求。不同于XMLHttpRequest的是, 通过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读写返回的内容。(这句话指的是:当你在自己网页通过<script src=http://b.com/b.js></script>调用b.js时,不能读取,或者修改b.js的内容)。
对于XMLHttpRequest而言,可以访问来自同源对象的内容,它需要通过目标域返回的HTTP头来授权是否允许跨域访问,因为HTTP头对于JavaScript来说一般是无法控制的,所以认为这个方案可以实施
对于浏览器来说,除了DOM(document object model,一种js的API,可用于操作和访问页面内容)、Cookie、XMLHttpRequest(一种js api,负责)会受到同源策略的限制外,浏览器加载的一些第三方插件也有各自的同源策略。最常见的一些插件如Flash、Java Applet、Sil-verlight、Google Gears等都有自己的控制策略

2.2 浏览器沙箱

这种在网页中插入一段恶意代码,利用浏览器漏洞执行任意代码的攻击方 式,在黑客圈子里被形象地称为“挂马”。
在大量的黑客攻击下,浏览器结合系统(比如windows的DEP,aslr safeSEH等功能)的保护抵抗内存攻击,还发展出了多进程架构,从安全性上有了很大的提高。
浏览器的多进程架构,将浏览器的各个功能模块分开,各个浏览器实例分 开,当一个进程崩溃时,也不会影响到其他的进程。
Sandbox即沙箱,计算机技术发展到今天,Sandbox已经成为泛指“资源隔离类模块”的代名词。Sandbox的设计目的一般是为了让不可信任的代码运行在一定的环境中,限制不可信任的代码访问隔离区之外的资源。如果一定要跨越Sandbox边界产生数据交换,则只能通过指定的数据通道,比如经过封装的API来完成,在这些API中会严格检查请求的合法性。

2.3 恶意网址拦截

恶意网址拦截的工作原理很简单,一般都是浏览器周期性地从服务器端获取一份最新的恶意网址黑名单,如果用户上网时访问的网址存在于此黑名单中,浏览器就会弹出一个警告页面
常见的恶意网址分为两类:一类是挂马网站,这些网站通常包含有恶意的脚本如JavaScript或Flash,通过利用浏览器的漏洞(包括一些插件、控件漏洞)执行shellcode,在用户电脑中植入木马;另一类是钓鱼网站,通过模仿知名网站的相似页面来欺骗用户。
要识别这两类恶意网址需要做建模,但这些模型放在客户端,一来攻击者也可以看到,就可以分析绕过;二来还会侵犯用户隐私;所以一般不这么干,就只能用黑名单的办法

3. XSS

跨站脚本攻击,英文全称是Cross Site Script,本来缩写是CSS,但是为了和层叠样式表(Cas-cading Style Sheet,CSS)有所区别,所以在安全领域叫做“XSS”
XSS攻击,通常指黑客通过“HTML注入”篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击

3.1 反射型XSS

需要黑客诱使用户去点击网址,也叫做非持久型XSS”(Non-persistent XSS)
DOM Based XSS是反射型XSS的一种类别,通过修改页面的DOM节点形成的XSS,称之为DOM Based XSS

3.2 存储型XSS

存储型XSS会把用户输入的数据“存储”在服务器端。这种XSS具有很强的稳定性。
比较常见的一个场景就是,黑客写下一篇包含有恶意JavaScript代码的博客文章,文章发表后,所有访问该博客文章的用户,都会在他们的浏览器中执行这段恶意的JavaScript代码。黑客把恶意的脚本保存到服务器端
也叫做持久型XSS(Persistent XSS)

3.3 从攻击的角度看XSS

XSS攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器。这些用以完成各种具体功能的恶意脚本,被称为“XSS Payload”。
XSS Payload的本质就是JavaScript脚本啦
通常情况下,攻击者会让被攻击者的浏览器加载一个js脚本,真正的代码协助这个js脚本里,从而避免在url中写入太多东西
XSS Payload能做到很多事情,比如cookie劫持、构造GET/POST请求、钓鱼、识别用户浏览器、识别用户安装的软件、获取真实的IP地址等等,最猛的还可以生成蠕虫
有一些不错的XSS平台可以用
https://github.com/beefproject/beef

3.4 调试js代码

因为要写一个好的XSS程序,js调试能力是必不可少的
https://zh.javascript.info/debugging-chrome介绍了如何用chrome浏览器调试js代码

3.5 xss构造技巧

  1. 利用字符编码:利用GBK/GB2312和Unicode之间的变换来绕过检测
  2. 使用标签:<base>标签定义页面上的所有使用“相对路径”标签的hosting地址,
  3. window.name : window.name对象是一个很神奇的东西。对当前窗口的window.name对象赋值,没有特殊字符的限制。因为window对象是浏览器的窗体,而并非document对象,因此很多时候window对象不受同源策略的限制。攻击者利用这个对象,可以实现跨域、跨页面传递数据。在某些环境下,这种特性将变得非常有用
  4. 绕过长度限制:利用location.hash来绕过长度限制
  5. javascript框架也存在xss漏洞

还有很多xss构造的奇技淫巧,但是目前就是过整个架构的阶段,等到实际运用的时候再来补上

3.6 xss防御手段

  1. httpOnly: 这个办法用来防止xss导致的cookie劫持攻击,通过对重要的cookie(一个网站的cookie不止一个添加该属性,添加了该属性的cookie,在使用js脚本尝试读取时,会被浏览器禁止)
  2. 输入检查: 字面意思,常见的Web漏洞如XSS、SQL Injection等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户不会用到的,所以输入检查就有存在的必要了
  3. 输出检测:一般来说,除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。
  4. 正确的防御XSS :为了更好地设计XSS防御方案,需要认清XSS产生的本质原因。
    XSS的本质还是一种“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了原本的语义,产生了新的语义。
    如果网站使用了MVC架构,那么XSS就发生在View层——在应用拼接变量到HTML页面时产生。所以在用户提交数据处进行输入检查的方案,其实并不是在真正发生攻击的地方做防御。
    想要根治XSS问题,可以列出所有XSS可能发生的场景,再一一解决
  5. 处理富文本: 有些时候,网站需要允许用户提交一些自定义的HTML代码,称之为“富文本”。比如一个用户在论坛里发帖,帖子的内容里要有图片、视频,表格等,这些“富文本”的效果都需要通过HTML代码来实现。

4. CSRF(跨站请求伪造)

CSRF的全名是Cross Site RequestForgery,翻译成中文就是跨站点请求伪造
你不小心登录了黑客写得恶意网址b,b中的代码访问了正常网址a的内容,这就造成了csrf攻击

4.1 浏览器的cookie策略

浏览器所持有的Cookie分为两种:一种是Session Cookie,又称“临时Cookie”;另一种是Third-party Cookie,也称为“本地Cookie”。
这两者的区别就是,Session Cookie是临时cookie,浏览器进程关闭后就消失,该cookie放在浏览器的进程空间中。
Third-party Cookie是本地cookie,它会保存在用户的硬盘中,即使浏览器关闭也不会消失(服务器下放本地cookie时,会设置该cookie的留存时间)。
你访问了攻击者的b网址,b网址中向a网址发送了请求,a网址会设定你的cookie,因为浏览器同源策略,这时候设定的cookie是无效的

4.2 P3P的副作用

尽管有些CSRF攻击实施起来不需要认证,不需要发送Cookie,但是不可否认的是,大部分敏感或重要的操作是躲藏在认证之后的。因此浏览器拦截第三方Cookie的发送,在某种程度上来说降低了CSRF攻击的威力。可是这一情况在“P3P头”介入后变得复杂起来
P3P头允许跨域访问隐私数据,从而可以跨域Set-Cookie成功。

4.3 GET/POST

其实GET POST请求都能触发CSRF攻击,在你设置了一个用POST方法提交的表单时,如果采用GET方法提交,服务器没有做响应的方法校验,也是可以提交的

4.4 防御CSRF

  1. 验证码:验证码被认为是对抗CSRF攻击最简洁而有效的防御方法
  2. Referer Check:常见的互联网应用,页面与页面之间都具有一定的逻辑关系,这就使得每个正常请求的Referer具有一定的规律。 比如一个“论坛发帖”的操作,在正常情况下需要先登录到用户后台,或者访问有发帖功能的页面。在提交“发帖”的表单时,Referer的值必然是发帖表单所在的页面。如果Referer的值不是这个页面,甚至不是发帖网站的域,则极有可能是CSRF攻击。
  3. Anti CSRF Token: 现在业界针对CSRF的防御,一致的做法是使用一个Token。 CSRF为什么能够攻击成功?其本质原因是重要操作的所有参数都是可以被攻击者猜测到的。
    攻击者只有预测出URL的所有参数与参数值,才能成功地构造一个伪造的请求;反之,攻击者将无法攻击成功。
    出于这个原因,可以想到一个解决方案:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值。也就是token
    token在使用中,有如下注意事项:
1. 防御CSRF的Token,是根据“不可预测性原则”设计的方案,所以Token的生成一定要足够随机,需要使用安全的随机数生成器生成Token。

2. 此外,这个Token的目的不是为了防止重复提交。所以为了使用方便,可以允许在一个用户的有效生命周期内,在Token消耗掉前都使用同一个
Token。但是如果用户已经提交了表单,则这个Token已经消耗掉,应该再次重新生成一个新的Token。

3. 如果Token保存在Cookie中,而不是服务器端的Session中,则会带来一个新的问题。如果一个用户打开几个相同的页面同时操作,当某个页面消耗掉Token后,其他页面的表单内保存的还是被消耗掉的那个Token,因此其他页面的表单再次提交时,会出现Token错误。在这种情况下,可以考虑生成多个有效的Token,以解决多页面共存的场景。

4. 最后,使用Token时应该注意Token的保密性

5. 点击劫持

点击劫持(ClickJacking)是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上

5.1 攻击手法

常见的点击劫持攻击手法有:flash点击劫持,图片覆盖攻击(Cross Site Image Overlaying,简称XSIO),拖拽劫持与数据窃取,ClickJacking 3.0:触屏劫持

5.2 防御手段

如下所示:

1. frame busting: 通常可以写一段JavaScript代码,以禁止iframe的嵌套

2. X-Frame-Options: 一个HTTP——X-Frame-Options可以说是为了解决Click-Jacking而生的,它有三个值:
• DENY
• SAMEORIGIN
• ALLOW-FROM origin
当值为DENY时,浏览器会拒绝当前页面加载任何frame页面;
若值为SAMEORIGIN,则frame页面的地址只能为同源域名下的页面;
若值为AL-LOW-FROM,则可以定义允许frame加载的页面地址。

6. HTML5 安全

HTML 5是W3C制定的新一代HTML语言的标准,(现在已经很普及了),新的标准带来了新的安全挑战

6.1 HTML 5新标签

  1. <video> 标签,这个标签可以在网页中远程加载一段视频。
  2. iframe的sandbox: <iframe>标签一直以来都为人所诟病。挂马、XSS、ClickJacking等攻击中都能看到它不光彩的身影 中都能看到它不光彩的身影,HTML 5中新增了 sandbox属性
  3. Link Types:noreferrer : 在HTML 5中为<a>标签和<area>标签定义了一个新的Link Types:noreferrer。顾名思义,标签指定了noreferrer后,浏览器在请求该标签指定的地址时将不再发送Referer,
  4. Canvas:Canvas可以说是HTML 5中最大的创新之一。不同于<img>标签只是远程加载一个图片,<canvas>标签让JavaScript可以在页面中直接操作图片对象,也可以直接操作像素,构造出图片区域。
    这个功能很强大,但是也带来了响应的安全问题,Canvas提供的强大功能,甚至可以用来破解验证码

6.2 其他安全问题

Cross-Origin Resource Sharing:
浏览器实现的同源策略(Same Origin Policy)限制了脚本的跨域请求。但互联网的发展趋势是越来越开放的,因此跨域访问的需求也变得越来越迫切。
http://a.comhttp://b.com发送跨源请求时,请求报文会附上Origin: http://www.a.com
Origin Header用于标记HTTP发起的“源”,服务器端通过识别浏览器自动带上的这个OriginHeader,来判断浏览器的请求是否来自一个合法的“源”。Origin Header可以用于防范CSRF,它不像Referer那么容易被伪 造或清空。
当然,http://b.com返回时,也会附上相应的回复:比如Access-Control-Allow-Origin: *


另外一个有趣的是postMessage——跨窗口传递
postMessage允许每一个window(包括当前窗口、弹出窗口、iframes等)对象往其他的窗口发送文本消息,从而实现跨窗口的消息传递。这个功能是不受同源策略限制的。of-course,很危险


Web Storage是最后一个有趣的东西
为什么要有Web Storage呢?过去在浏览器里能够存储信息的方法有以下 几种:
• Cookie • Flash Shared Object • IE UserData 其中,Cookie主要用于保存登录凭证和少量信息,其最大长度的限制决定了不可能在Cookie中存储太多信息。而Flash Shared Object和IE User-Data则是Adobe与微软自己的功能,并未成为一个通用化的标准。因此W3C委员会希望能在客户端有一个较为强大和方便的本地存储功能,这就 是Web Storage。
Web Storage分为Session Storage 和 LocalStorage。Session Storage关闭浏览器就会失效,而Local Storage则会一直存在
Web Storage也受到同源策略的约束,每个域所拥有的信息只会保存在自 己的域下
Web Storage让Web开发更加的灵活多变,它的强大功能也为XSS Payload大开方便之门。攻击者有可能将恶意代码保存在Web Storage中,从而实现跨页面攻击。