Web 开发的安全之旅(防御篇)| 青训营笔记

179 阅读5分钟

这是我参与「第四届青训营 」笔记创作活动的的第6天

👋本文分享要点:防御篇( 防御XSS/CSRF/Injection/Dos/中间人的攻击 )

🤔上一篇笔记我们作为攻击者了解到了多种攻击方式,那我们应该怎样去防止别人的攻击呢?

防御XSS攻击

两个要点

  • 永远不信任用户的提交内容
  • 不要将用户提交内容直接转换成DOM

Snipaste_2022-07-30_23-13-20.png

防御XSS的现成工具

前端

  • 主流框架默认防御XSS
  • google-closure-library

服务端(Node)

  • DOMPurify

😈如果用户需求必须动态生成DOM呢? 😅那就要小心这几个地方了

🚨 1. string ——>DOM

new DOMParser();

这时候我们要对string进行转义

🚨 2. 上传 SVG

<svg>
    <script>alert('xss')</script>
</svg>

因为svg标签可以插入<script>标签,所以要对其做一次过滤

🚨 3. 自定义跳转链接

<a href="javascript:alert('xss')" ></a>

尽量不要让用户做自定义跳转链接的行为,如果一定要,就要做好过滤

🚨 4. 自定义样式

Snipaste_2022-07-30_23-29-46.png 只有指定收入的用户选择,才会发出这个get请求,这个用户的收入情况就会暴露给恶意攻击者,所以如果允许这种自定义样式的行为,就要对能够设置URL背景图片、字体文件额外的留意

👋为了下面的内容讲解,先插播讲解一下:Same-origin Policy(同源策略)和Content Security Policy(CSP) 内容安全策略

Same-origin Policy(同源策略)

同源:确保两个URL上的协议、域名、端口号统统相等
一般来说,同源请求都是没有问题的,但如果非同源、跨域的话往往是不可行的,更多的是要看你请求的类型和对应服务器的配置

Snipaste_2022-07-30_23-35-31.png

Content Security Policy(CSP) 内容安全策略

CSP

  • 哪些源(域名)被认为是安全的
  • 来自安全源的脚本可以执行,否则直接抛错
  • 对eval+inline script说❌

Snipaste_2022-07-30_23-43-30.png

防御CSRF攻击

Snipaste_2022-07-30_23-45-25.png

🤔除了Origin+Referrer,还有其他判断【请求来自于合法来源】的方式吗?


先有页面,后有请求:

Snipaste_2022-07-30_23-48-02.png
具体的实现思路:CSRF——token

image.png

  1. 用户绑定:攻击者也可以是注册用户===可以获取自己的token
  2. 过期时间:【前向保密】 ,保证攻击者获取到历史的token也不奏效

🚨CSRF——iframe攻击

Snipaste_2022-07-30_23-57-31.png iframe发出的请求不是跨域请求,而是同源请求,点击了button完成一次CSRF攻击

🤔那我们该怎么防御呢?

有一个http响应头部可以被利用到,具体是指X-Frame-Options响应头部

X-Frame-Options:DENY/SAMEORIGIN

image (1).png
如果可以在服务器进行编码的话,则可以对所有的页面设置这个X-Frame-Options响应头部,有两个值可以选择:DENY/SAMEORIGIN DENY:当前页面不能作为iframe进行加载 SAMEORIGIN:必须是同源的页面才能加载这个iframe

🚨GET !== GET + POST

有时候开发者为了偷懒,将GET请求实现为既能GET(获取数据)又能POST(修改数据)

image (2).png 如果被攻击到了,用户的隐私不仅会被泄露,而且还会被篡改(一石二鸟) 所以一定要避免这种操作!!!

😇再来看看另一种防御CSRF的策略

避免⽤户信息被携带:SameSite Cookie

image (3).png 从根源上解决了CSRF的攻击方式

😇我们来看一下具体SameSite Cookie的含义

image (4).png 限制的是:①Cookie domain②页面域名

🤔那依赖Cookie的第三方服务怎么办?

如:我们做了一个页面,引了一个X站播放器,但因为第三方Cookie不能识别用户登录的状态,导致用户发不了弹幕,用户体验极差,怎么办?
当然,SameSite Cookie已经想到了如何应对这种方式

Snipaste_2022-07-31_00-18-56.png 不对SameSite 做任何限制,但同时标明这个cookie是Secure以确保安全

SameSite vs CORS(跨站资源共享)

image (5).png

防御CSRF的正确姿势

因为防御CSRF的方式很多,case by case防御不太现实,所以防御的正确姿势是先做一个中间件(专门去生成防御CSRF的策略),就在一处完成web的CSRF的防御

防御Injection攻击

  1. 找到项目中查询SQL的地方
  2. 使用prepared statement(将SQL语句进行提前的编译)

Snipaste_2022-07-31_10-37-57.png

除了SQL注入之外,针对其他攻击还有其他的措施

  • 最小权限原则

    • ❌sudo || root
  • 建立允许名单 + 过滤

    • ❌ rm
  • 对URL类型参数进行协议、域名、ip等限制

    • ❌访问内网

防御Dos攻击

针对正则表达式的Dos

  • Code Review(❌/(ab*]+/)
  • 代码扫描 + 正则性能测试
  • ❌用户提供的使用正则

针对DDos

关键的防御思路:

Snipaste_2022-07-31_10-44-47.png

传输层——防御中间人攻击

Snipaste_2022-07-31_10-47-21.png 防御方案:使用HTTPS协议

HTTPS

HTTPS的特性

  1. 可靠性:加密、(避免了明文传输)
  2. 完整性:MAC 验证、(确保信息没有被篡改)
  3. 不可抵赖性:数字签名(确保双方身份可被信任)

HTTPS大概流程(TLS握手)

Snipaste_2022-07-31_10-56-07.png

HTTPS——完整性

Snipaste_2022-07-31_10-58-43.png 接收方会对接受的信息重新进行一次哈希计算,和传递过来的哈希值进行对比,如果两者相等就说明没有被篡改。

扩:数字签名

image (6).png 数字签名的过程:
签名执行者使用私钥对一些指定内容进行一些数学计算,生成一个对应的签名,凡是具有公钥的人都可以都签名进行一次校验,如果是私钥生成的签名,则校验通过

HTTPS——不可抵赖:数字签名

Snipaste_2022-07-31_14-14-38.png 数字签名在HTTPS中是这样工作的: (非对称加密过程中)

  1. 加密过程:内容 [服务的元信息 + 公钥(sessionKesy)] + CA私钥(进行签名) === 生成 服务器证书 ——>传递到浏览器中
  2. 验证过程:浏览器用 CA颁发的公钥对证书进行校验 如果校验通过,说明证书合法(证书签发者身份可信)

HSTS

就是如何将HTTP请求升级到HTTPS请求 image (8).png

总结

今天通过防御者的角度去防御XSS/CSRF/Injection/Dos/中间人的攻击,我们要知道:

  • 安全无小事

  • 使用的依赖(npm package,甚至是NodeJS)可能成为最薄弱的一环

    • left-pad 事件
    • eslint-scope 事件(npm install 除了带来了黑洞,还可以带来漏洞)
    • event-stream 事件
  • 保持学习心态