一、前言
浏览器安全可以分为三大块:
- Web 页面安全
- 浏览器网络安全
- 浏览器系统安全
Web 世界是开放的,任何资源都可以接入其中,我们的网站可以加载并执行别人网站的脚本文件、图片、音频、视频等资源,甚至可以下载其他站点的可执行文件。
但是 Web 世界不能绝对自由,例如打开一个银行站点,不小心又打开一个恶意站点:
- 修改银行站点的 DOM、CSSOM 等信息;
- 在银行站点内部插入 JavaScript 脚本;
- 劫持用户登录的用户名和密码;
- 读取银行站点的 Cookie、IndexDB 等数据;
- 甚至还可以将这些信息上传至自己的服务器,这样就可以在你不知情的情况下伪造一些转账请求等信息。
所以,在没有安全保障的 Web 世界中,我们是没有隐私的,因此需要安全策略来保障我们的隐私和数据的安全。
这就引出了页面中最基础、最核心的安全策略:同源策略(Same-origin policy)。
二、同源策略
2.1 什么是同源策略
所谓 源,可以指 URL。
而所谓的同源,是指 协议、域名、端口 一致的情况下,才属于同源。
浏览器默认两个相同的源之间是可以相互访问资源和操作 DOM 的。两个不同的源之间若想要相互访问资源或者操作 DOM,那么会有一套基础的安全策略的制约,我们把这称为同源策略。
2.2 为什么需要同源策略
同源策略主要表现在 DOM、Web 数据和网络这三个层面。
- 第一个,DOM 层面
同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。
当你在 A 页面,通过 <a href=”xxx” target=”_blank”> 的形式打开 B 页面,经过下面 2 行代码可以将 A 页面的内容给隐藏掉:
let pdom = opener.document;
pdom.body.style.display = "none";
这就是同源情况下 DOM 的一个操作。
而不同源的是无法操作的。
- 第二个,数据层面
同源策略限制了不同源的站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据。
由于同源策略,我们依然无法通过 B 页面的 opener 来访问 A 页面中的 Cookie、IndexDB 或者 LocalStorage 等内容。
- 第三个,网络层面
同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。
三、XSS
3.1 概览
本章目标:看到下面概览可以大略描述说出 XSS 攻击、XSS 攻击类型以及 XSS 防御措施。
- XSS 攻击类型
- 存储型
- 反射型
- 文档型
- XSS 防范措施
- 输入检查
- 利用 CSP
- 利用 HttpOnly
3.2 介绍
XSS(Cross Site Script)跨站脚本攻击。指的是攻击者向网页注入恶意的客户端代码,通过恶意的脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。
例如:
- 可以窃取 Cookie 信息。恶意 JavaScript 可以通过 document.cookie 获取 Cookie 信息,然后通过 XMLHttpRequest 或者 Fetch 加上 CORS 功能将数据发送给恶意服务器。恶意服务器拿到用户的 Cookie 信息之后,就可以在其他电脑上模拟用户的登录,然后进行转账等操作。
- 可以监听用户行为。恶意 JavaScript 可以使用 addEventListener 接口来监听键盘事件,比如可以获取用户输入的信用卡等信息,将其发送到恶意服务器。黑客掌握了这些信息之后,又可以做很多违法的事情。
- 可以通过修改 DOM 伪造假的登录窗口,用来欺骗用户输入用户名和密码等信息。
- 可以在页面内生成浮窗广告,这些广告会严重地影响用户体验。
注入恶意脚本分 3 种方式:
- 存储型:即攻击被存储在服务端,常见的是在评论区插入攻击脚本,如果脚本被储存到服务端,那么所有看见对应评论的用户都会受到攻击。例如 2015 年喜马拉雅的专辑名称允许用户编写 <script> 标签。
- 反射型:攻击者将脚本混在 URL 里,服务端接收到 URL 将恶意代码当做参数取出并拼接在 HTML 里返回,浏览器解析此 HTML 后即执行恶意代码。例如 Q 群或者邮件中发送恶意链接,用户点击恶意链接,然后解析 URL 执行恶意代码。
- DOM 型:攻击者通过各种手段将恶意脚本注入用户的页面中。例如通过网络劫持(WiFi 路由器劫持、本地恶意软件劫持等)在页面传输过程中修改 HTML 页面内容。
3.3 防御
防御 XSS 攻击:
- 输入检查:对输入内容中的 script 和 <iframe> 等标签进行转义或者过滤
- 设置 httpOnly:设置此属性可防止 JavaScript 获取 Cookie,只能在 HTTP 请求过程中使用 Cookie
- 开启 CSP 白名单:即开启白名单,可阻止白名单以外的资源加载和运行
四、CSRF
4.1 概览
本章目标:看到下面概览可以大略描述说出 CSRF 攻击、CSRF 攻击方式以及 CSRF 防御措施。
- CSRF 攻击方式
- 利用用户的登录状态,并通过第三方的站点来做一些坏事
- 自动发 GET 请求
- 自动发 POST 请求
- 诱导点击发送 GET 请求
- CSRF 防范措施
- 验证 Token
- 验证 Referer
- 验证 Samesite
4.2 介绍
CSRF 攻击(Cross-site request forgery)即跨站请求伪造。
是一种劫持受信任用户向服务器发送非预期请求的攻击方式,通常情况下,它是攻击者借助受害者的 Cookie 骗取服务器的信任,但是它并不能拿到 Cookie,也看不到 Cookie 的内容,它能做的就是给服务器发送请求,然后执行请求中所描述的命令,以此来改变服务器中的数据,也就是并不能窃取服务器中的数据。
CSRF 攻击就是黑客利用用户的登录状态,并通过第三方的站点来做一些坏事。
打开攻击者提供的页面后,攻击者有 3 种方式实施 CSRF 攻击:
方法一:自动发起 Get 请求
<!DOCTYPE html>
<html>
<body>
<h1>黑客的站点:CSRF 攻击演示</h1>
<img src="https://jsliang.top/index.html?user=hacker&number=100">
</body>
</html>
黑客将转账的请求接口隐藏在 img 标签内,欺骗浏览器这是一张图片资源。
当该页面被加载时,浏览器会自动发起 img 的资源请求,如果服务器没有对该请求做判断的话,那么服务器就会认为该请求是一个转账请求,于是用户账户上的 100 块就被转移到黑客的账户上去了。
方法二:自动发起 POST 请求
<!DOCTYPE html>
<html>
<body>
<h1>黑客的站点:CSRF 攻击演示</h1>
<form id='hacker-form' action="https://jsliang.top" method=POST>
<input type="hidden" name="user" value="hacker" />
<input type="hidden" name="number" value="100" />
</form>
<script>
document.getElementById('hacker-form').submit();
</script>
</body>
</html>
在页面中构建了一个隐藏的表单,该表单的内容就是极客时间的转账接口。
当用户打开该站点之后,这个表单会被自动执行提交;当表单被提交之后,服务器就会执行转账操作。
因此使用构建自动提交表单这种方式,就可以自动实现跨站点 POST 数据提交。
方法三:引诱用户点击链接
<div>
<img width=150 src=http://images.xuejuzi.cn/1612/1_161230185104_1.jpg>
</div>
<div>
<a href="https://jsliang.top?user=hacker&number=100" taget="_blank">
点击下载美女照片
</a>
</div>
传说中的色诱,或者 “点击即送 100w 元” 之类的。
4.3 防御
防御 CSRF 攻击:
- 验证 Token:浏览器请求服务器时,服务器返回一个 token,之后每个请求都需要同时带上 token 和 Cookie 才会被认为是合法请求
- 验证 Referer:通过验证请求头的 Referer 来验证来源站点,但请求头很容易伪造
- 设置 SameSite:设置 Cookie 的 SameSite,可以让 Cookie 不随跨站请求发出,但浏览器兼容不一
五、SQL注入
已有代码:
<form action="/login" method="POST">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="登陆" /></p>
</form>
后端的登录语句:
let querySQL = `
SELECT *
FROM user
WHERE username='${username}'
AND psw='${password}'
`;
// 接下来就是执行 sql 语句...
攻击者输入的信息是:
- 用户名:jsliang’ OR 1 = 1 –
- 密码:随意,例如 123456
预想输入和现在输入变成:
SELECT * FROM user WHERE username='jsliang' AND psw='123456'
SELECT * FROM user WHERE username='jsliang' OR 1 = 1 --' AND psw='xxxx'
我们先拆解这条 SQL 语句,避免有些小伙伴看不懂:
- SELECT:查找
- *:所有信息
- FROM:来源于某个表(From xxx)
- user:用户表
- username=’xxx’:用户名是 xxx
- AND:和
- OR:或
- –:注释,跟我们 JS 的 // 一样
所以上面代码的意思是:
- 第一条:查找 user 表,其中 username 为 jsliang,并且密码是 123456
- 第二条:查找 user 表,其中 username 为 jsliang,或者 1 = 1
这样,第二条的 SQL 查询条件就必定是真的啦,我们就可以登录这个账号了。
这就是 SQL 注入。
怎么预防?这里我们不理会,属于后端需要注意的范畴。
当然后端可能要求前端帮忙防范,比如用户名不能包含 -、_ 等~
六、流量劫持
流量劫持基本分两种:DNS 劫持 和 HTTP 劫持,目的都是一样的,就是当用户访问 github.com 的时候,给你展示的并不是或者不完全是 github.com 提供的 “内容”。
6.1 DNS 劫持
DNS 劫持,也叫做域名劫持。
当用户通过某一个域名访问一个站点的时候,被篡改的 DNS 服务器返回的是一个恶意的钓鱼站点的 IP,用户就被劫持到了恶意钓鱼站点,然后继而会被钓鱼输入各种账号密码信息,泄漏隐私。
这类劫持:
要不就是网络运营商搞的鬼,一般小的网络运营商与黑产勾结会劫持 DNS
要不就是电脑中毒,被恶意篡改了路由器的 DNS 配置,基本上做为开发者或站长却是很难察觉的,除非有用户反馈。
6.2 HTTP 劫持
HTTP 劫持主要是当用户访问某个站点的时候会经过运营商网络,而不法运营商和黑产勾结能够截获 HTTP 请求返回内容,并且能够篡改内容,然后再返回给用户,从而实现劫持页面。
轻则插入小广告,重则直接篡改成钓鱼网站页面骗用户隐私,就好比 jsliang 访问某 XXDN 网站,会出现 Google 广告,实际上问了其他人的是不会有这个的。
能够实施流量劫持的根本原因,是 HTTP 协议没有办法对通信对方的身份进行校验以及对数据完整性进行校验。如果能解决这个问题,则流量劫持将无法轻易发生。
所以防止 HTTP 劫持的方法只有将内容加密,让劫持者无法破解篡改,这样就可以防止 HTTP 劫持了。
HTTPS 是基于 SSL 协议的安全加密网络应用层协议,相当于 HTTP + SSL,可以很好地防止 HTTP 劫持。
七、浏览器网络安全
HTTP 在传输过程中的每一个环节,数据都有可能被窃取或者篡改,这也意味着你和服务器之间还可能有个中间人,在通信过程中的一切内容都在中间人的掌握中。
使用 HTTP 传输的内容很容易被中间人窃取、伪造和篡改,通常我们把这种攻击方式称为中间人攻击。
具体来讲,在将 HTTP 数据提交给 TCP 层之后,数据会经过用户电脑、WiFi 路由器、运营商和目标服务器,在这中间的每个环节中,数据都有可能被窃取或篡改。
比如用户电脑被黑客安装了恶意软件,那么恶意软件就能抓取和篡改所发出的 HTTP 请求的内容。
或者用户一不小心连接上了 WiFi 钓鱼路由器,那么数据也都能被黑客抓取或篡改。
八、浏览器系统安全
浏览器本身的漏洞是单进程浏览器的一个主要问题,如果浏览器被曝出存在漏洞,那么在这些漏洞没有被及时修复的情况下,黑客就有可能通过恶意的页面向浏览器中注入恶意程序。
其中最常见的攻击方式是利用缓冲区溢出,不过需要注意这种类型的攻击和 XSS 注入的脚本是不一样的。
- XSS 攻击只是将恶意的 JavaScript 脚本注入到页面中,虽然能窃取一些 Cookie 相关的数据,但是 XSS 无法对操作系统进行攻击。
- 通过浏览器漏洞进行的攻击是可以入侵到浏览器进程内部的,可以读取和修改浏览器进程内部的任意内容,还可以穿透浏览器,在用户的操作系统上悄悄地安装恶意软件、监听用户键盘输入信息以及读取用户硬盘上的文件内容。
渲染进程需要执行 DOM 解析、CSS 解析、网络图片解码等操作,如果渲染进程中存在系统级别的漏洞,那么以上操作就有可能让恶意的站点获取到渲染进程的控制权限,进而又获取操作系统的控制权限。
基于此,在渲染进程和操作系统之间建一道墙,即便渲染进程由于存在漏洞被黑客攻击,但由于这道墙,黑客就获取不到渲染进程之外的任何操作权限。
将渲染进程和操作系统隔离的这道墙就是安全沙箱。