Web安全基础攻防技术


前言

写在开篇

二进制的计算机世界中黑白之中的灰色地带,一场剑与盾的战争悄然上演!
没有战火,没有硝烟,只有无数暗流涌动,这就是Web安全

更新日志

2022/01/25
开始学习

2002/01/26
初步记录完毕

跨站脚本攻击XSS

概述

Cross-Site Script,本该简称CSS,但为了避免歧义,所以就叫XSS
(X就是Cross嘛)
是最常见的一种攻击手段

有如下几种常见的类型:

  1. Stored XSS
    存储型XSS,恶意脚本存到数据库中,在访问页面并进行数据读取时发动攻击,伤害最大,对全部用户可见
  2. Reflected XSS
    反射型XSS,从URL上攻击,将恶意脚本填入URL参数的值中,在执行GET请求时发动
  3. DOM-Based XSS
    基于DOM的XSS,不需要服务器参与,全程在浏览器完成。注入原理同反射型XSS,但是执行条件是JS利用URL参数创建DOM
  4. Mutation-based XSS
    基于变化的XSS,利用浏览器渲染DOM的特性,比如在标签的title属性中注入XSS,在渲染时进行攻击,作用于不同浏览器时可能会有差异
    这种注入方式最为复杂,需要攻击者非常了解浏览器的渲染规则——同时也是最难防御的XSS攻击

示例

<script>alert('XSS')</script>

这段代码放到 数据库 或者 URL参数的值中则可以造成XSS攻击

分析

用户提交的string转为DOM的过程中,可能使用到了下述代码片段

document.write()
element.innerHTML = ''
// 或者使用了 SSR类的操作

而XSS攻击具有以下特点:

  1. 通常难以从UI上感知
  2. 能窃取cookie/token等信息
  3. 绘制UI(如植入弹窗),欺骗用户填写、点击

防御

核心思想

永远不要相信用户提交的内容
不要直接把用户提交内容转为DOM,尽可能转为字符串等相对安全的类型
小心类似于 “需要动态生成DOM” 这种客户需求

防御工具

前端

  1. 主流框架默认防御XSS
  2. google-closure-library

服务端(指Node)

  1. DOMPurify

注意事项

  1. string类型注意转义内容
  2. 如果允许用户上传SVG文件等,需要先预处理
  3. 小心自定义跳转连接,因为这样是可以传递JS代码的
  4. 小心自定义样式,因为CSS的URL也可能包含GET请求

跨站请求伪造CSRF

概述

Cross-Site Request Forgery
(翻译是跨站请求伪造,但是口头上也常称为跨站伪造请求..总感觉一个是名词一个是动宾短语…)

这里举出一些较为特殊的CSRF:

  1. iframe攻击
    由于iframe中发起请求是同源请求,所以检测是否来自安全源的防御机制对此近乎无效,而且攻击者可能更加高明,会利用事件冒泡\事件捕获等JS特性在看似安全的按钮等事件对象的背后隐藏恶意的事件对象

  2. anti-pattern攻击

    这是由于程序员本身因为疏忽(更大概率是因为懒),设置GET请求也可以作为POST请求使用,导致攻击者可以直接利用GET请求篡改数据

示例

  1. 用户访问到了恶意页面,并输入、提交了个人信息
  2. 恶意页面利用这些信息设置cookie,请求另一个域名下的银行转账接口,由于cookie信息是有效的,转账的请求也被认为是有效的
  3. 请求执行成功,转账完毕,用户权益受到侵害

这些恶意的脚本可能隐藏在a、img等标签的属性中,或者直接不隐藏而是构建一个表单。
它们会在被点击时触发GET请求发动攻击

分析

跨站请求伪造有如下几个特点:

 1. 用户不知情为前提
 2. 利用用户的权限(cookie)
 3. 构造指定的HTTP请求,窃取/修改信息

防御

核心思想

(大部分情况下)尽可能判断请求的来源,如果来源异常,那么对其进行限制

注意事项

前端

  1. 同源请求中,GET、HEAD不会发送Origin字段,这种情况
    判断来源的话就比较麻烦,所以同源请求尽量避免GET、HEAD

  2. 也可以结合Referer字段来进行判断

  3. 使用token和用户进行绑定,并设置过期时间,这样避免了token被他人利用,也避免了持续时间较长的攻击

  4. 对于iframe攻击,需要在服务器响应头部设置X-Frame-Options的值为DENY,意味着当前页面的值不能作为iframe进行加载;或者设置为SAMEORIGIN,意味着这个页面本身必须和当前页面同源,才能作为iframe加载

  5. CSRF是因为Cookie被携带导致的,那么设置SameSite Cookie使得特定页面的Cookie只能在该页面生效,也就能从根源上解决CSRF
    (这里要注意区分SameSite和CORS的区别,前者是和第三方域与页面域的Cookie相关;后者是和资源域与页面域间资源读写的白名单相关)

    后端(偏指Node)

    构建中间件(Middlewares)专门做CSRF防御

注入攻击Injection

概述

通过发送注入 SQL语句的参数 的请求,使后端获取这些恶意的参数而执行恶意的SQL操作,导致数据库信息被修改
常见的注入攻击有以下几类:

  1. SQL
  2. CLI
  3. OS command
  4. SSRF(Server-Side Request Forgery) 服务端伪造请求,严格意义上不算注入,但是原理类似

示例

SQL注入示例

假设现在后端有如下SQL语句:

SELECT username FROM users;

SQL注入:

fetch('/api',{
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        users: 'table1;DROP TABLE users;'
    	// SQL注入关键语句
    })
})

后端收到请求后,SQL会被解析为:

SELECT username FROM table1;DROP TABLE users;

结果就是数据库信息被删除

OS command注入示例

const command = 'convert-cli video -o && rm -rf xxx'

SSRF示例

  1. 请求用户自定义的callback URL
  2. 利用内网访问权限(前提是要有),此时访问acllback即可能暴露内网信息

(说实话这个没看太懂,不过还是先记下来吧)

不知道是哪一类的注入示例

  1. 篡改nginx.conf文件中的代理服务器
  2. 把该网站流量转发到第三方服务器
  3. 第三方服务器流量突增,可能无法继续支撑,从而崩溃

防御

  1. 使用prepared statement
  2. 遵循最小权限原则,所有命令都不要通过sudo执行
  3. 建立允许名单,并进行过滤,避免rm这种高危操作
  4. (针对SSR注入)对URL类型参数进行协议、域名、ip等限制

拒绝服务攻击DoS

概述

Denial of Server

通过某种方式(构造特定请求),导致服务器资源被显著消耗,来不及响应更多请求,导致请求挤压,进而雪崩,
大概有如下几种常见类型:

  1. ReDoS
    正则表达式拒绝服务攻击,利用贪婪模式的正则表达式的回溯操作
  2. DDoS
    分布式拒绝服务攻击,直接发送大量请求

示例

正则表达式拒绝服务攻击

类似的情况可以在正则匹配的过程中遇到

在贪婪模式下,正则表达式的运作规律如下:

正则表达式: /^((ab)*)+$/
试图匹配字符: ‘ababaa’

先尝试用3个ab去匹配,发现不匹配;
再尝试用2个ab去匹配,发现不匹配;
再尝试用1个ab去匹配,发现不匹配;
最终判断为不匹配

当这样的串长度非常大、并且数量非常多时,会使得响应时间极大地变长,吞吐量极大地下降,,那么服务器可能就有崩溃的风险

分布式拒绝服务攻击

没什么技巧,就靠数量打人海战术

可以访问任意IP、任意API,不区分接口,消耗大量的带宽

洪水攻击(SYN Flood)就属于DDoS的一种:
利用三次握手,发送大量SYN,服务器来不及确认响应进而崩溃

防御

流量治理

  1. 负载均衡 —— 过滤
  2. API网关 —— 过滤
  3. CDN —— 抗量

快速自动扩容 —— 抗量

非核心服务降级 —— 抗量

中间人攻击MITM

概述

Man-in-the-Middle Attack,简称MITM

基于传输层,在浏览器和服务器之间进行伪装:

浏览器<–交互–>中间人<–交互–>服务器

中间人的身份可以有很多种,包括伪劣路由器、恶意网络服务提供商等,但浏览器和服务器却都没有察觉到中间人的存在

分析

这种攻击有三个特点

  1. 明文传输:未加密的信息可以被直接获取
  2. 信息篡改不可知:浏览器和服务器没有有效地验证信息
  3. 身份未验证:没有验证交互对象的身份

防御

HTTPS

(HTTP3(QUIC)内置了TLS1.3,所以非常安全,但是这里不提这个,太超前了,这里依旧介绍HTTPS)

HTTPS具有如下特性:

  1. 可靠性(加密)

  2. 完整性 (MAC验证)

  3. 不可抵赖性 (私钥和内容可以加密生成数字签名,公钥可以解密;证书校验也是前面这个原理)

HSTS
HTTP Strict-Transport-Security,强制安全传输
前提是一定要有一次HTTPS请求

HSTS示意图

SRI
Subresource Integrity,静态资源完整性

能够有效针对静态资源劫持,校验原理是原始内容hash对比实际内容hash

Featrue Policy/Permission Policy
能够限制一个源(页面),可以使用那些功能,比如camera、microphone、autoplay

后记

web安全,不论攻防都振奋人心
安全没有小事可言,以上例举的内容只是九牛之一毛,web还存在太多潜在的风险,甚至使用的依赖(npm package)或者说作为中间服务器的Node,都可能成为出现问题的一环

web安全的学习到此就要告一段落了,但是学习的步伐不会就此停滞

前方是星辰大海


文章作者: Serio
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Serio !
  目录