Web开发的安全之旅 |青训营笔记
这是我参与「第四届青训营」笔记创作活动的的第8天
Web安全一窥
我们常常可以在新闻上看到、“某某公司被侵入损失几万元”等等消息,这些问题都是来自
Web安全问题。
安全问题“很常见”,会危害:
- 用户
- 公司
- 程序员
两个角度看Web安全
我们来按照两个角度去看Web安全:
- 攻击者角度 - 假如你是一个hacker - 攻击
- 开发者角度 - 假如你是一个开发者 - 防御
攻击者角度
跨站脚本攻击:XSS
-
解释:制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
-
利用原因:构成XSS攻击的原因是开发者盲目信任用户提交的内容,让其直接转化成DOM,比如:
-
document.write
-
Element.innerHTML = anyString;
-
SSR(user_data)//伪代码
-
特点:
-
通常难以从UI上感知(因为暗地执行脚本)
-
窃取用户信息(cookie/token)
-
绘制UI(例如弹窗),诱骗用户点击/填写表单
-
-
示例代码:
-
//开发者代码 public async submit(ctx) { const {content,id} = ctx.request.body; //没有对content过滤 await db.sava({ content, id }); } public async render(ctx) { const {content} = await db.query({ id : ctx.query.id }) //没有对contetn过滤 ctx.body = `<div>${content}</div>` } -
//攻击者代码 fetch("/submit",{ body : JSON.stringify({ id : "1", content:`<script>alert("xss");</script>` }); });
-
-
性质:
- 恶意脚本被存在数据库中
- 访问页面 -》读数据 === 被攻击
- 危害最大,对全部用户可见
-
反射性XSS攻击:
- 不设计数据库
- 从URL上攻击
- 示例:
-
基于DOM的XSS攻击:
- 不需要服务器的参数
- 恶意攻击的发起 + 执行 , 全在浏览器完成
- 示例:
-
两者完成注入脚本的地方比较:
-
基于mutation的XSS攻击:
-
利用了浏览器的DOM特性(独特优化)
-
不同浏览器,会有区别(按浏览器进行攻击)
-
示例:
Denial of Service(DoS)攻击:
- 解释:通过某种方式(构造特定请求),导致服务器资源被显著消耗,来不及响应更多请求,导致请求挤压,进而雪崩效应。
- 基于正则表达式的DoS:贪婪,用容易发生回溯行为的字符串进行不断匹配
Distributed DoS(DDoS)攻击:
- 解释:短时间内,来自大量僵尸设备的请求流量,服务器不能及时完成全部请求,导致请求堆积,进而雪崩效应,无法响应新请求。
- 特点:
- 直接访问IP
- 任意API
- 消耗大量带块(耗尽)
- 示例
中间人攻击:
-
解释:中间人攻击是一种 间接的 入侵攻击方式,这种攻击模式是将一台计算机虚拟放置在网络连接中的两台通信计算机之间,这台计算机就称为“中间人”。
-
-
利用方式:
- 明文传输
- 信息篡改不可知
- 对方身份未验证
跨站伪造请求:CSRF
- 特点:
- 在用户不知情的前提下
- 利用用户权限(cookie)
- 构造制定HTTP请求,窃取或修改用户敏感信息
注入攻击(injection):
-
SQL攻击:
-
攻击方式:
- 读取请求字段
- 直接以字符串的形式拼接SQL
-
其他注入攻击:
-
CLI
-
OS command
-
Server-side Request Forgery(SSRF),服务端伪造请求
- 严格而言,SSRF不是injection,但是原理类似
开发者角度
XSS跨站脚本攻击防御:
- 永远不信任用户的提交内容
- 不要将用户提交的内容转换成DOM
防御工具:
- 前端:
- 主流框架防御XSS
- google-closure-library
- 服务端(Node)
- DOMPurify
注意点:【用户需求】不讲武德,必须动态生成DOM
- 如果我们要使用用户传入的数据转换成DOM,那么一定要转译
- 如果我们允许用户上传SVG图片,那么我们扫描一下SVG
- 尽量不让用户自定义跳转链接,如果用,那么做好过滤
- 尽量不让用户自定义样式,如果用,那么做好过滤
Content Security policy(CSP)防御
- 哪些源(域名)被认为是安全的
- 来自安全源的脚本可以执行,否则直接抛错
- 对eval + inline script 说 “ 不”!
CSRF的防御
其他方式:
-
token及其防御机制
-
-
iframe攻击:
-
-
我们可以用响应头部:DENY/SAMEORIGIN来防御
-
-
GET !== GET + POST
- 我们在日常开发中偷懒把get请求和post请求一起写,这样导致攻击者利用CSRF去攻击所以在日常开发中千万不要偷懒,把GET请求和POST请求分开两个接口去写。
-
避免用户信息被携带: SameSite Cookie
- 如果CSRF利用用户权限,而用户权限在页面的cookie之中 那我们的请求不带cookie 就能防御攻击,从根源上解决CSRF攻击
sameSite VS CORS
注入攻击防御
-
SQL注入:
-
找到项目中查询SQL的地方
-
使用 prepared statement
-
-
其他的注入防御方式:
- 最小权限原则
- sudo || root
- 建立允许名单+过滤
- rm
- 对URL类型参数进行协议、域名、ip等限制
- 访问内网
- 最小权限原则
防御DoS
- 完善code Review的工作,避免使用贪婪模式
- 代码扫描 +正则性能测试
- 拒绝使用用户提供的使用正则
防御DDoS
-
过滤
- 流量治理
- 负载均衡
- API网关
- CDN
- 流量治理
-
抗量
- 快速扩容
- 非核心业务降级
防御中间人
这里就需要我们的HTTS来防御
HTTPS具有的特点:
-
可靠性:加密 (避免了明文传输)
-
完整性:MAC验证(确保了数据不被篡改)
- 所有传输的信息除了加密的信息外,还要额外传输加密信息对应的hash,所有的接收方要对加密信息重新计算一次哈希值,会和传递过来的哈希值进行对比,如果相等,没有被篡改,没有相等,说明被篡改了。
-
不可抵赖性 :数字签名 (身份验证,确保双方身份可被信任)
-
-
但是当签名算法不够健壮的时候,是可以被暴力破解的。
-
-
将HTTP主动升级到HTPPS
SRI防御
为了防止我们的静态资源被劫持篡改,利用SRI防御
SRI功能:
- 标签哈希值(原始内容hash)和实际内容哈希值对比
总结
- 安全无小事
- 使用的依赖(npm package ,甚至是NodeJs)可能成为最薄弱的一环
- 保持学习心态