这是我参与「第四届青训营 」笔记创作活动的的第5天
Web开发的安全之旅
Web安全一窥
Web安全这个概念实际上比我们想象的要常见的多,比如说在谷歌搜索引擎搜索data leak关键词,就能随随便便搜到上亿条搜索结果。
安全问题“很常见”,会危害用户的隐私,公司的利益受损,最重要的也可能导致我们程序员丢工作,所以我们一定要重视。
两个角度看Web安全
- 假如你是一个hacker——攻击
- 假如你是一个开发者——防御
攻击篇
要点:
Cross-Site Scripting(XSS)跨站脚本攻击
<script>alert("xss");</script>
XSS主要利用了
XSS=盲目信任用户的提交内容+string→DOM
- document.write
- element.innerHTML=anyString;
- SSR(user_data)//伪代码
XSS的一些特点
- 通常难以从UI上感知(暗地执行脚本)
- 窃取用户信息(cookie/token)
- 绘制UI(例如弹窗),诱骗用户点击/填写表单
XSS的性质——1.Stored XSS
- 恶意脚本被存在数据库中
- 访问页面→读数据≡被攻击
- 危害最大,对全部用户可见
比如说,假如某个视频网站存在一个XSS漏洞,有人上传一段视频,之中插入了一个XSS的恶意脚本,那当用户看这个视频的时候,所有观看这个页面的用户都会被XSS攻击到,所有的用户的隐私信息都可能被泄露,那么电商、网商可能就会搜到你的一个爱奇艺的账户,而且你还有可能被账户踢出,就是这么可怕。
XSS的性质——2.Reflected XSS
- 不涉及数据库
- 从URL上攻击
host/path/?param=<script>alert('123')</script>
XSS的性质——3.DOM——based XSS
- 不需要服务器的参与
- 恶意攻击的发起+执行,全在浏览器完成
(与上相同的URL)
Reflected vs DOM——based
Reflected XSS和DOM——based XSS其实很类似,但它俩有一个非常重要的区别,就是完成注入脚本的地方。反射型恶意脚本其实是在Server也就是服务端注入,而基于DOM的XSS攻击实际上是完全由浏览器这一侧来完成整个闭环。
XSS的性质——4.Mutation——based XSS
- 利用了浏览器渲染DOM的特性(独特优化)
- 不同浏览器,会有区别(按浏览器进行攻击)
Cross-site request forgery(CSRF) 跨站伪造请求
- 在用户不知情的前提下
- 利用用户权限(cookie)
- 构造指定HTTP请求,窃取或修改用户敏感信息
demo
CSRF——GET
<a>
<img>
<form method="POST">
<input type="hidden">
Injection
SQL Injection
Injection不止于SQL
- CLI
- OS command
- Server-Side Request Forgery(SSRF),服务端伪造请求
-
- 严格而言,SSRF不是Injection,但是原理相似
Denial of Service(DoS)
通过某种方式(构造特定请求),导致服务器资源被显著消耗,来不及响应更多请求,导致请求挤压,进而雪崩效应。
正则表达式——贪婪模式
重复匹配时「?」 vs 「no?」:满足“一个”即可vs尽量多
ReDoS:基于正则表达式的DoS
贪婪:n次不行?n-1次再试试?——回溯
响应时间延长
接口吞吐量下降
Distributed DoS(DDoS)
短时间内,来自大量僵尸设备的请求流量,服务器不能及时完成全部请求,导致请求堆积,进而雪崩效应,无法响应新请求。
「不搞复杂的,量大就完事儿了」
攻击特点
- 直接访问IP
- 任意API
- 消耗大量带宽(耗尽)
demo
传输层
中间人攻击
为什么会发生?
①明文传输
②信息篡改不可知
③对方身份未验证
防御篇
XSS
- 永远不信任用户的提交内容
- 不要将用户提交内容直接转成DOM
XSS——现成工具
前端
- 主流框架默认防御xss
- google-closure-library
服务端(Node)
- DOMPurify
XSS——耗子尾汁
!!【用户需求】不讲武德,必须动态生成DOM
1.!!string→DOM
new DOMparser();
2.!!上传svg
<svg>
<script>alert("xss");</script>
</svg>
3.!!自定义跳转链接
<a href="javascript:alert('xss')"></a>
4.自定义样式
插播:Same-origin Policy
Content Security Policy(CSP)
- 哪些源(域名)被认为是安全的
- 来自安全源的脚本可以执行,否则直接抛错
- 对eval+inline script说no no
CSRF的防御
CSRF——token
除了Origin+Referrer,其他判断【请求来自于合法来源】的方式
- if(请求来自合法页面)
- then(服务器接收过页面请求)
- then(服务器可以标识)
先有页面,后有请求
①用户绑定:攻击者也可以是注册用户===可以获取自己的token
②过期时间:【前向保密】
CSRF——iframe攻击
CSRF anti-pattern
GET!==GET+POST
所以,我们以后在写代码的时候一定要避免偷懒行为,我们一定还是要按照功能去把各个接口按照职责划分开,应该是GET的行为就是get的请求,应该是POST的请求就是单独另外一个接口,一定要区分开。
避免用户信息被携带:SameSite Cookie
限制的是:
①Cookie domain
②页面域名
依赖Cookie的第三方服务怎么办?
内嵌一个X站播放器,识别不了用户登录态,发不了弹幕
Set-Cookie:SameSite-None;Secure;
SameSite vs CORS
防御CSRF的正确姿势
从node这一层角度来讲,我们应该应该做一个中间栈,这个中间栈就专门去生成各种防御CSRF的策略,就在余处保证我们整个Web app都能完成对CSRF的防御。
Injection
- 找到项目中查询SQL的地方
- 使用prepared statement
Injection beyond SQL
Regex DoS
DDoS
传输层——防御中间人
HTTPS的一些特性
HTTPS的大致流程
HTTPS——1.完整性
数字签名
HTTPS——不可抵赖:数字签名
HTTP Strict-Transport-Security(HSTS)
Subresource Integrity(SRI)
demo
补充
尾声
- 安全无小事
- 使用的依赖(npm package,甚至是NodeJS)可能成为最薄弱的一环
-
- left-pad事件
-
- eslint-scope事件
-
- event-stream事件
!!npm install除了带来了黑洞,还可以带来漏洞
- 保持学习的心态