前端中的安全问题
几类和前端息息相关的安全问题
前端开发者在开发过程中可能会遇到许多安全问题,主要包括以下几类:
- 网络协议攻击:这块主要包括 HTTP,HTTPS(证书过期,中间人劫持),DNS 劫持等问题
- 跨站脚本攻击(XSS):这是最常见的前端安全问题之一。攻击者通过注入恶意的 JavaScript 脚本,企图破坏网站的功能或者窃取用户的数据。
- 跨站请求伪造(CSRF):在这种攻击中,攻击者诱使用户去请求一个他们并不期望的网站,以此来执行一些恶意的操作。
- 点击劫持:攻击者通过透明的元素或者弹窗,诱使用户在不知情的情况下点击一些链接或者按钮,以此来执行一些恶意的操作。
- 混合内容问题:如果一个使用 HTTPS 协议的网站中,包含了使用 HTTP 协议的资源(如图片、脚本等),可能会导致用户的数据被窃取。这是因为 HTTP 协议的数据传输不是加密的,攻击者可以通过监听网络传输,来窃取这些数据。
- 第三方库的安全问题:许多前端开发者在开发过程中,会使用一些第三方的库或者框架。如果这些库或者框架存在安全问题,或者被恶意修改,可能会引入一些安全风险。
- 不安全的数据存储:在前端开发中,有时需要在用户的浏览器中存储一些数据。如果这些数据包含敏感信息,如密码、Token 等,并且存储方式不安全(如直接保存在 localStorage 等),可能会被攻击者窃取。
接下来我们分别介绍这几类的攻防策略
网络协议攻击
HTTP
HTTP 是一种无状态的明文协议,数据在传输过程中并不加密,容易被中间人攻击。攻击者可以轻易地监听、捕获和篡改传输中的数据,包括敏感信息如用户名、密码、session ID 等。信道安全是最大问题
HTTPS
HTTPS 是基于 SSL/TLS 的 HTTP 加密版本,提供了数据的机密性、完整性和身份认证。然而,如果实施不当,HTTPS 也可能有安全隐患。例如,如果服务器的 SSL/TLS 版本过旧或配置不当,可能会遭受“中间人攻击”。此外,如果网站的 HTTPS 证书不合法或过期,也可能导致安全问题。
中间人攻击
中间人攻击(Man-in-the-Middle Attack,简称 MITM)
是一种网络攻击手段,攻击者插入到通信的两端之间,截取和可能篡改他们的通信。
在这种攻击中,攻击者让通信的双方认为他们正在直接和对方通信,但实际上,所有的通信都通过了攻击者。这样,攻击者就可以监听和捕获所有传输的信息,包括敏感信息,如登录凭证、信用卡号等。如果攻击者愿意,他们甚至可以更改通信的内容。
以下是几种常见的中间人攻击:
攻击者发送伪造的 ARP 消息到局域网,欺骗其他设备,让它们将网络数据发送到攻击者控制的设备上,而不是正确的目标设备。通过这种方式,攻击者可以拦截、窃取甚至篡改被传输的数据,以获取敏感信息或进行其他恶意活动。
攻击者通过篡改 DNS 查询的响应,将用户导向错误的 IP 地址。攻击者可以劫持 DNS 查询并发送虚假的响应,将用户引导到恶意站点,这可能是一个伪装的登录页面、钓鱼站点或包含恶意软件的网站。这种攻击可能导致用户受到欺骗、信息泄露或恶意软件感染。DNS Spoofing 通常发生在未经加密的网络上,例如公共 WiFi 网络,因为攻击者能够在这些网络上拦截和篡改通信。
攻击者创建一个伪造的 HTTPS 网站,将用户的流量引导到这个网站,从而窃取用户的信息。在 HTTPS 通信中,数据被加密以确保传输的安全性和隐私性。攻击者可能使用欺骗性手段,如仿冒合法网站、通过钓鱼邮件或欺诈性广告等方式,诱使用户访问这个伪造的 HTTPS 网站。一旦用户访问了这个伪造网站,攻击者就能够窃取用户的敏感信息,例如登录凭据、个人信息、支付信息等。HTTPS Spoofing 攻击是一种严重的安全威胁,因为用户通常会认为 HTTPS 连接是安全的,从而信任访问的网站。因此,防范此类攻击需要用户提高警惕,确保访问的网站是可信的,并且使用安全的网络连接。
为了防止中间人攻击,可以使用以下几种方法:
- 使用加密的连接,如 HTTPS、VPN。这可以确保数据在传输过程中的安全,即使被攻击者截获也无法直接读取。
- 检查 SSL 证书。如果浏览器提示 SSL 证书有问题,那可能是正在遭受中间人攻击。不要忽视这些警告。
- 使用安全的 DNS 解析,如 DNSSEC,防止 DNS Spoofing。
- 使用网络安全工具,如防火墙,IDS 等,监控异常的网络行为。
DNS 劫持
DNS 劫持是一种网络攻击方式。攻击者通过篡改 DNS(Domain Name System)查询的响应,将用户的域名解析请求指向错误的 IP 地址,通常是攻击者控制的恶意网站或服务器。这样一来,用户访问的网站实际上是攻击者控制的网站,可能导致用户的个人信息泄露、账户被盗、恶意软件感染等安全问题。
DNS 劫持攻击是一种比较隐蔽且危害较大的攻击方式,因为它直接影响了用户对网络资源的访问。DNSSEC
(DNS Security Extensions)是一种用于加强 DNS 安全性的协议,它能够提供数据的完整性和认证性,有效防止 DNS 记录被篡改或 DNS 劫持攻击。然而,并非所有的网站和 ISP(Internet Service Provider,互联网服务提供商)都启用了DNSSEC
,这导致 DNS 劫持仍然是一个存在的安全威胁。
XSS 安全
概念
XSS(跨站脚本攻击)
是一种常见的网络攻击手段。在这种攻击中,攻击者通过注入恶意的 JavaScript 脚本来攻击网站的用户
攻击
XSS 攻击主要有以下几种类型:
- 存储型 XSS 攻击:攻击者将恶意的 JavaScript 脚本存储在网站的服务器上(例如,在一个评论区中发布含有恶意脚本的评论)。当其他用户浏览到包含这些脚本的页面时,就会执行这些脚本。
- 反射型 XSS 攻击:在这种攻击中,攻击者会将恶意脚本包含在 URL 中。当用户点击这个 URL 时,恶意脚本会被网站的页面反射(即,直接在页面中输出),然后在用户的浏览器中执行。
- DOM 型 XSS 攻击:这种攻击是通过修改页面的 DOM 结构,使得恶意脚本得以执行。
防御
对抗 XSS 攻击的防御方法有多种,以下是一些常见的方法:
- 数据输出时进行转义:对所有的用户输入进行 HTML 转义,可以有效防止 XSS 攻击。例如,将
<
转义为<
,将>
转义为>
等。这样做的目的是防止浏览器将用户输入的数据误认为是 HTML 代码或者 JavaScript 脚本。 - 使用内容安全策略(CSP):内容安全策略是一种通过设置 HTTP 头部来告知浏览器哪些资源可以加载的安全机制。通过配置 CSP,可以限制页面加载外部资源的来源,包括脚本、样式表、图片等。这样即使 XSS 攻击者成功注入恶意脚本,浏览器也会拒绝执行来自非法来源的脚本,从而有效地减轻 XSS 攻击的危害。
- 使用 HTTP-only cookies:将 cookies 设置为 HTTP-only 可以防止 JavaScript 通过
document.cookie
API 读取这些 cookies。这样,即使攻击者注入了恶意脚本,也无法窃取用户的 cookies。 - 使用最新的 JavaScript 框架:许多现代的 JavaScript 框架(如 React、Vue.js 等)内置了 XSS 防御机制。
前端框架集成等防范措施
现代 JavaScript 框架。如 React、Vue.js 等,都有一些内置的防御机制,来帮助开发者避免 XSS 攻击。下面是一些具体的防御机制:
- 默认的数据绑定是安全的:在这些框架中,数据绑定到视图的方式通常是安全的。例如,在 Vue 和 React 中,使用双大括号
{{ }}
或 JSX 的{}
来插入数据时,框架会自动对其进行转义,以防止数据被解析为 HTML 或 JavaScript。这样,即使数据中包含有潜在的 XSS 攻击代码,也不会被执行。 - 提供安全的编码函数:当需要在视图中插入未转义的 HTML 时,这些框架通常会提供安全的方法。例如,React 的
dangerouslySetInnerHTML
,Vue 的v-html
指令。虽然这些方法允许插入未转义的 HTML,但它们的名称都强调了这种操作的危险性,提醒开发者需要谨慎使用。 - Content Security Policy (CSP) 支持:许多现代框架也支持内容安全策略 (CSP),这是一种防止 XSS 攻击的安全措施。CSP 可以限制网页中能执行的脚本的来源,有效地阻止 XSS 攻击。
虽然这些框架提供了一些内置的防御机制,但仍然需要开发者了解 XSS 攻击的原理,并在编写代码时遵循一些最佳实践,如对用户输入进行校验,使用 HTTP-only cookies 等,才能更有效地防止 XSS 攻击。
CSRF
攻击
CSRF(跨站请求伪造)
是一种网络攻击手段,主要是攻击者利用用户已登录的身份,伪造用户去请求服务器。这种攻击方式可以诱导用户执行攻击者预设的操作,如修改密码、购买商品等。
假设一个场景:用户在一家银行的网站上登录了自己的账户。如果该网站存在 CSRF 漏洞,攻击者可以设置一个陷阱,比如在论坛中发帖附带一个链接,这个链接是银行网站的一个转账接口,而且指定了收款人和转账金额。如果用户点击了这个链接,那么银行网站可能会认为是用户自己发起的转账请求,从而进行转账。
这种攻击方法的关键在于,用户并不知道自己发起了这个请求,而服务器也无法分辨这个请求是不是用户本人意愿发起的,这就给攻击者留下了可乘之机。
CSRF 攻击有一定的局限性,它必须基于用户已经登录了目标网站,并且该网站有 CSRF 漏洞存在。此外,攻击者也不能预知 CSRF 攻击的具体结果,因为这取决于被攻击的网站的业务逻辑。
防御
为了防御 CSRF 攻击,我们可以使用一些方法,例如使用 CSRF token,验证 HTTP Referer 字段,或者使用 SameSite Cookie 等。
一种常见的 CSRF 防御机制是使用 CSRF token。
以下是一个简单的 JavaScript 的 CSRF token 生成和验证的例子。
首先,我们需要一个函数来生成 CSRF token:
1 | function generateCSRFToken() { |
在实际应用中,服务器在响应客户端的请求时,会生成一个 CSRF token,并在响应中将其发送给客户端。客户端在发送请求时,会将这个 token 作为一部分请求数据发送给服务器。
服务器在收到请求时,会验证请求中的 token 是否和服务器发送的 token 一致。以下是一个简单的验证函数:
1 | function verifyCSRFToken(serverToken, clientToken) { |
于是在现代前端框架中 CSRF 的开启往往也是个 config 选项透出
点击劫持问题(Clickjacking)
概念
点击劫持(Clickjacking)
是一种常见的网络攻击手段,也被称为“UI 覆盖攻击”。在这种攻击中,攻击者将一个透明的、恶意的网页覆盖在一个用户期望看到的网页上面。当用户在页面上进行操作(如点击按钮)时,他们实际上是在点击攻击者的透明页面,从而触发了攻击者预设的行为。这个行为在实际业务开发中会被忽视,但是基建团队一般也都会在构建 config 里给我们配置上类似 X-Frame-Options
和csp
的选项为了防止这些问题。
防御策略
-
使用
X-Frame-Options HTTP
响应头:这是一种 HTTP 响应头,可以防止你的网页被嵌入到其他网页的 iframe 中。你可以将这个响应头设置为 DENY(禁止所有的域嵌入你的网页),或者SAMEORIGIN
(只允许相同域名的网页嵌入你的网页)。 -
使用 Content Security Policy (CSP):CSP 是一种控制网页内容的安全策略,你可以使用
frame-ancestors
指令,来限制哪些网页可以嵌入你的网页。 -
使用 JavaScript 检测:你可以在你的网页中添加 JavaScript 代码,检测你的网页是否被嵌入到 iframe 中。如果是,那么可以让网页跳出 iframe,显示在顶层窗口。
需要注意的是,虽然上述方法可以有效防止点击劫持,但没有任何一种方法是绝对安全的。因此,作为开发者,我们应该尽量使用多种防御策略,以增加攻击者的攻击成本。
基本防御 case
1 | if (top !== self) { |
这段代码的作用是,如果当前页面不是顶层窗口(被嵌入到了其他页面的 iframe 中),那么就将顶层窗口的地址设置为当前页面的地址,使得当前页面显示在顶层窗口,从而跳出 iframe。
混合内容问题
混合内容问题指的是一个使用 HTTPS 协议的网页,包含了使用 HTTP 协议的资源。由于 HTTP 是明文传输,这种情况下,即使主页面是 HTTPS,但包含的 HTTP 资源在传输过程中仍可能被窃取或篡改,从而导致用户的信息泄露或被欺骗。特别是在使用框架页面时,可能需要引入其他来源的内容,容易出现混合内容问题。因此,我们应该时刻注意网站是否存在混合内容问题,并及时进行修复。
防御
- 使用 HTTPS 来加载所有资源:这是最直接、最有效的解决方法。无论是图片、脚本、样式表,还是其他任何类型的资源,都应该使用 HTTPS 来加载。
- 使用相对 URL:如果你的网站同时支持 HTTP 和 HTTPS,那么可以使用相对 URL 来引用资源,如
"/path/to/my/script.js"
,而不是"http://example.com/path/to/my/script.js"
。这样,浏览器会使用和主页面相同的协议来加载资源。 - 使用 Content Security Policy (CSP):CSP 是一种用来控制网页可以加载哪些资源的安全策略。你可以设置 CSP 的
upgrade-insecure-requests
指令,来自动将所有的 HTTP 请求升级到 HTTPS。 - 使用 HTTP Strict Transport Security (HSTS) 头:HSTS 是一种安全策略,它告诉浏览器,这个网站只能通过 HTTPS 访问。开启 HSTS 后,浏览器会自动将所有的 HTTP 请求升级到 HTTPS。
第三方库的安全问题
问题
我想许多公司的业务代码架构治理都在解决这个问题。当我们一个迭代项目中依赖的包存在安全问题,或者这个包已经不推荐无人维护,或者这个包直接被恶意篡改(投毒),都会引入安全风险。
防御
在实际的业务治理过程中,架构师通常会制定精品库,由专门的团队负责维护并将其集成到团队的业务框架中,例如标准化的业务线库(如 stdlib)。同时,团队会提供代码扫描工具,通过持续集成等时机不断扫描项目,发现老旧库或不推荐使用的库并及时进行告警。这样可以及时发现和解决潜在的安全问题,提高项目的安全性和稳定性。
不安全的数据存储
问题
在 web 开发中,不安全的数据存储可以引起许多安全问题。如果攻击者能够访问或者修改存储的数据,可能会泄露敏感信息,或者造成其他的安全问题。
防御
- 使用安全的 cookie 设置:对于存储在 cookie 中的数据,应该使用
Secure
和HttpOnly
标志来保护它们。Secure 标志可以确保 cookie 只通过 HTTPS 发送,HttpOnly 标志可以防止 JavaScript 访问 cookie。 - 敏感信息加密存储:对于敏感信息,如密码,应该进行哈希和加盐存储,而不是明文存储。哈希可以确保即使数据库被泄露,攻击者也无法直接获取到原始的密码。加盐可以进一步增加破解的难度。
- 避免在 localStorage 中存储敏感信息:localStorage 是持久性的,并且在同源的所有页面中都可访问。因此,如果你在 localStorage 中存储敏感信息,可能会有被 XSS 攻击窃取的风险。你应该避免在 localStorage 中存储敏感信息,或者至少对它们进行加密。
- 限制并监控数据的访问:应该限制谁可以访问存储的数据以及他们可以进行的操作。对于敏感操作,如数据的修改和删除,应该进行记录和监控。
安全的数据存储需要多方面的考虑和措施,包括传输的安全,存储的安全,以及访问的安全。
本文参考: