[面试专题]前端须要知道的web安全知识

前端须要知道的web安全知识

标签(空格分隔): 未分类javascript


安全

  • [Doc] Crypto (加密)html

  • [Doc] TLS/SSL前端

  • [Doc] HTTPSjava

  • [Point] XSSnode

  • [Point] CSRFgit

  • [Point] 中间人攻击github

  • [Point] Sql/Nosql 注入攻击web

Crypto

Node.js 的 crypto 模块封装了诸多的加密功能, 包括 OpenSSL 的哈希、HMAC、加密、解密、签名和验证函数等.sql

加密是如何保证用户密码的安全性?mongodb

在客户端加密, 是增长传输的过程当中被第三方嗅探到密码后破解的成本. 对于游戏, 在客户端加密是防止外挂/破解等. 在服务端加密 (如 md5) 是避免管理数据库的 DBA 或者攻击者攻击数据库以后直接拿到明文密码, 从而提升安全性.

TLS/SSL

早期的网络传输协议因为只在大学内使用, 因此是默认互相信任的. 因此传统的网络通讯能够说是没有考虑网络安全的. 早年的浏览器大厂网景公司为了应对这个状况设计了 SSL (Secure Socket Layer), SSL 的主要用途是:

  1. 认证用户和服务器, 确保数据发送到正确的客户机和服务器;

  2. 加密数据以防止数据中途被窃取;

  3. 维护数据的完整性, 确保数据在传输过程当中不被改变.

存在三个特性:

  • 机密性:SSL协议使用密钥加密通讯数据

  • 可靠性:服务器和客户都会被认证, 客户的认证是可选的

  • 完整性:SSL协议会对传送的数据进行完整性检查

1999年, SSL 由于应用普遍, 已经成为互联网上的事实标准. IETF 就在那年把 SSL 标准化/强化. 标准化以后的名称改成传输层安全协议 (Transport Layer Security, TLS). 不少相关的文章都把这二者并列称呼 (TLS/SSL), 由于这二者能够视做同一个东西的不一样阶段.

HTTPS

在网络上, 每一个网站都在各自的服务器上, 想要确保你访问的是一个正确的网站, 而且访问到这个网站正确的数据 (没有被劫持/篡改), 除了须要传输安全以外, 还须要安全的认证, 认证不能由目标网站进行, 不然恶意/钓鱼网站也能够本身说本身是对的, 因此为了能在网络上维护网络之间的基本信任, 早期的大厂们协力推进了一项名为 PKI 的基础设施, 经过第三方来认证网站.

公钥基础设施 (Public Key Infrastructure, PKI) 是一种遵循标准的, 利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范. 其基础建置包含认证中心 (Certification Authority, CA) 、注册中心 (Register Authority, RA) 、目录服务 (Directory Service, DS) 服务器.

由 RA 统筹、审核用户的证书申请, 将证书申请送至 CA 处理后发出证书, 并将证书公告至 DS 中. 在使用证书的过程当中, 除了对证书的信任关系与证书自己的正确性作检查外, 并透过产生和发布证书废止列表 (Certificate Revocation List, CRL) 对证书的状态作确认检查, 了解证书是否因某种缘由而遭废弃. 证书就像是我的的身分证, 其内容包括证书序号、用户名称、公开金钥 (Public Key) 、证书有效期限等.

在 TLS/SLL 中你可使用 OpenSSL 来生成 TLS/SSL 传输时用来认证的 public/private key. 不过这个 public/private key 是本身生成的, 而经过 PKI 基础设施能够得到权威的第三方证书 (key) 从而加密 HTTP 传输安全. 目前博客圈子里比较流行的是 Let's Encrypt 签发免费的 HTTPS 证书.

须要注意的是, 若是 PKI 受到攻击, 那么 HTTPS 也同样不安全. 能够参见 HTTPS 劫持 - 知乎讨论 中的状况, 证书由 CA 机构签发, 通常浏览器遇到非权威的 CA 机构是会告警的 (参见 12306), 可是若是你在某些特殊的状况下信任了某个未知机构/证书, 那么也可能被劫持.

此外有的 CA 机构以邮件方式认证, 那么当某个网站的邮件服务收到攻击/渗透, 那么攻击者也可能以此从 CA 机构获取权威的正确的证书.

XSS

跨站脚本 (Cross-Site Scripting, XSS) 是一种代码注入方式, 为了与 CSS 区分因此被称做 XSS. 早期常见于网络论坛, 原由是网站没有对用户的输入进行严格的限制, 使得攻击者能够将脚本上传到帖子让其余人浏览到有恶意脚本的页面, 其注入方式很简单包括但不限于 JavaScript / VBScript / CSS / Flash 等.

当其余用户浏览到这些网页时, 就会执行这些恶意脚本, 对用户进行 Cookie 窃取/会话劫持/钓鱼欺骗等各类攻击. 其原理, 如使用 js 脚本收集当前用户环境的信息 (Cookie 等), 而后经过 img.src, Ajax, onclick/onload/onerror 事件等方式将用户数据传递到攻击者的服务器上. 钓鱼欺骗则常见于使用脚本进行视觉欺骗, 构建假的恶意的 Button 覆盖/替换真实的场景等状况 (该状况在用户上传 CSS 的时候也可能出现, 如早起淘宝网店装修, 使用 CSS 拼接假的评分数据等覆盖在真的评分数据上误导用户).

  • 反射型XSS:非持久化,欺骗用户去点击连接,攻击代码包含在url中,被用户点击以后执行攻击代码.

  • 存储型XSS:持久型,攻击提交恶意代码到服务器,服务器存储该段代码,这样当其余用户请求后,服务器返回gai'go'n并发给用户,用户浏览此类页面时就可能受到攻击。例如:恶意用户的HTML或JS输入服务器->进入数据库->服务器响应时查询数据库->用户浏览器。

  • 防范与过滤

    • 输入编码过滤:对于每个输入,在客户端和服务器端验证是否合法字符,长度是否合法,格式是否正确,对字符进行转义.非法字符过滤.

    • 输出编码过滤:对全部要动态输出到页面的内容,进行相关的编码和转义.主要有HTML字符过滤和转义,JS脚本转义过滤.url转义过滤.

    • 设置http-only,避免攻击脚本读取cookie.

CPS 策略

在百般无奈, 没有统一解决方案的状况下, 厂商们推出了 CPS 策略.

以 Node.js 为例, 计算脚本的 hashes 值:

const crypto = require('crypto');

function getHashByCode(code, algorithm = 'sha256') {
  return algorithm + '-' + crypto.createHash(algorithm).update(code, 'utf8').digest("base64");
}

getHashByCode('console.log("hello world");'); // 'sha256-wxWy1+9LmiuOeDwtQyZNmWpT0jqCUikqaqVlJdtdh/0='

设置 CSP 头:

content-security-policy: script-src 'sha256-wxWy1+9LmiuOeDwtQyZNmWpT0jqCUikqaqVlJdtdh/0='
<script>console.log('hello geemo')</script> <!-- 不执行 -->
<script>console.log('hello world');</script> <!-- 执行 -->

策略指令能够参见 CSP Policy Directives以及阮一峰的博文, 屈大神的博文

CSRF

跨站请求伪造 (Cross-Site Request Forgery) 是一种伪造跨站请求的攻击方式. 例如利用你在 A 站 (攻击目标) 的 cookie / 权限等, 在 B 站 (恶意/钓鱼网站) 拼装 A 站的请求.

已知某站点 A 删除的接口是 get 到某个地址, 并指定一个帖子的 id. 在网站 B 上组织一个删除A站某文章的get请求. 而后A站用户访问B站,触发该请求. 就能够不知情的状况下删除某个帖子.

同源策略是最先用于防止 CSRF 的一种方式, 即关于跨站请求 (Cross-Site Request) 只有在同源/信任的状况下才能够请求. 可是若是一个网站群, 在互相信任的状况下, 某个网站出现了问题:

a.public.com
b.public.com
c.public.com
...

以上状况下, 若是 c.public.com 上没有预防 xss 等状况, 使得攻击者能够基于此站对其余信任的网站发起 CSRF 攻击.

另外同源策略主要是浏览器来进行验证的, 而且不一样浏览器的实现又各自不一样, 因此在某些浏览器上能够直接绕过, 并且也能够直接经过短信等方式直接绕过浏览器.

预防:

  1. 在 HTTP 头中自定义属性并验证

  2. 检查 CSRF token.

  3. cookie中加入hash随机数.

  4. 经过检查来过滤简单的 CSRF 攻击, 主要检查一下两个 header:

  • Origin Header

  • Referer Header

中间人攻击

中间人 (Man-in-the-middle attack, MITM) 是指攻击者与通信的两端分别建立独立的联系, 并交换其所收到的数据, 使通信的两端认为他们正在经过一个私密的链接与对方直接对话, 但事实上整个会话都被攻击者彻底控制. 在中间人攻击中, 攻击者能够拦截通信双方的通话并插入新的内容.

目前比较常见的是在公共场所放置精心准备的免费 wifi, 劫持/监控经过该 wifi 的流量. 或者攻击路由器, 连上你家 wifi 攻破你家 wifi 以后在上面劫持流量等.

对于通讯过程当中的 MITM, 常见的方案是经过 PKI / TLS 预防, 及时是经过存在第三方中间人的 wifi 你经过 HTTPS 访问的页面依旧是安全的. 而 HTTP 协议是明文传输, 则没有任何防御可言.

不常见的还有强力的互相认证, 你确认他以后, 他也确认你一下; 延迟测试, 统计传输时间, 若是通信延迟太高则认为可能存在第三方中间人; 等等.

SQL/NoSQL 注入

注入攻击是指当所执行的一些操做中有部分由用户传入时, 用户能够将其恶意逻辑注入到操做中. 当你使用 eval, new Function 等方式执行的字符串中有用户输入的部分时, 就可能被注入攻击. 上文中的 XSS 就属于一种注入攻击. 前面的章节中也提到过 Node.js 的 child_process.exec 因为调用 bash 解析, 若是执行的命令中有部分属于用户输入, 也可能被注入攻击.

SQL

Sql 注入是网站常见的一种注入攻击方式. 其缘由主要是因为登陆时须要验证用户名/密码, 其执行 sql 相似:

SELECT * FROM users WHERE usernae = 'myName' AND password = 'mySecret';

其中的用户名和密码属于用户输入的部分, 那么在未作检查的状况下, 用户可能拼接恶意的字符串来达到其某种目的, 例如上传密码为 '; DROP TABLE users; -- 使得最终执行的内容为:

SELECT * FROM users WHERE usernae = 'myName' AND password = ''; DROP TABLE users; --';

其能实现的功能, 包括但不限于删除数据 (经济损失), 篡改数据 (密码等), 窃取数据 (网站管理权限, 用户数据) 等. 防治手段常见于:

  • 给表名/字段名加前缀 (避免被猜到)

  • 报错隐藏表信息 (避免被看到, 12306 早起就出现过的问题)

  • 过滤能够拼接 SQL 的关键字符

  • 对用户输入进行转义

  • 验证用户输入的类型 (避免 limit, order by 等注入)

  • 等...

NoSQL

看个简单的状况:

let {user, pass, age} = ctx.query;

db.collection.find({
  user, pass,
  $where: `this.age >= ${age}`
})

那么这里的 age 就能够注入了. 另外 GET/POST 还能够传递深层结构 (好比 ?name[0]=alan 传递上来), 经过 qs 之类的模块解析后致使注入, 如 cnodejs 遭遇 mongodb 注入.

DDOS

DDoS即Distributed Denial of Service,分布式拒绝服务。也就是攻击者借助或者利用服务器技术,将多个计算机(肉鸡或僵尸机)联合起来做为攻击平台,对一个或者多个目标服务器,同一时间发送大量垃圾信息,或利用某种干扰信息的方式,致使目标服务器没法及时响应正经常使用户正常请求,或者直接致使目标服务器宕机,从而没法为正经常使用户提供服务的一种攻击行为。

攻击方式:

  • 端口扫描攻击

  • ping洪水(flooding)攻击

  • SYN洪水(flooding)攻击

  • FTP跳转攻击

防范手段:

  • 保证服务器系统的安全,确保服务器软件没有任何漏洞,防止攻击者入侵。

  • 确保服务器采用最新系统,并打上安全补丁。

  • 在服务器上删除未使用的服务,关闭未使用的端口。

  • 对于服务器上运行的网站,确保其打了最新的补丁,没有安全漏洞。

  • 隐藏服务器的真实IP地址

相关文章
相关标签/搜索