---

title: API安全测试与Fuzz策略最佳实践

keywords:

  • Fuzz
  • 边界值
  • 变异
  • Corpus
  • Schema
  • RateGate
  • 重放
  • 审计
  • 覆盖率
  • 采样

description: 构建可验证的API安全Fuzz方案,包含Schema驱动的输入生成、边界值与变异策略、速率限制与重放能力、审计与简易覆盖统计,附执行器与样例。

categories:

  • 文章资讯
  • 技术教程

---

一、输入Schema与边界

type Str = { type: 'string'; min: number; max: number; pattern?: RegExp }
type Num = { type: 'number'; min: number; max: number; integer?: boolean }
type Field = Str | Num
type Schema = { properties: Record<string, Field>; required?: string[] }

二、生成器与变异

function randInt(min: number, max: number): number { return Math.floor(Math.random() * (max - min + 1)) + min }

function genStr(spec: Str): string {
  const len = randInt(spec.min, spec.max)
  const chars = 'abcdefghijklmnopqrstuvwxyz0123456789_-' + "<>\"'&"
  let s = ''
  for (let i = 0; i < len; i++) s += chars[randInt(0, chars.length - 1)]
  if (spec.pattern && !spec.pattern.test(s)) s = s.replace(/[<>"'&]/g, 'a')
  return s
}

function genNum(spec: Num): number {
  const n = spec.integer ? randInt(spec.min, spec.max) : Math.random() * (spec.max - spec.min) + spec.min
  return Math.min(spec.max, Math.max(spec.min, n))
}

function mutateString(s: string): string {
  const ops = [
    (x: string) => x + "' OR '1'='1",
    (x: string) => `<script>alert(1)</script>` + x,
    (x: string) => x.slice(0, 1),
    (x: string) => x.repeat(10)
  ]
  return ops[randInt(0, ops.length - 1)](s)
}

三、速率限制与重放

class RateGate {
  windowMs: number
  max: number
  hits = new Map<string, number[]>()
  constructor(windowMs: number, max: number) { this.windowMs = windowMs; this.max = max }
  allow(key: string): boolean {
    const now = Date.now()
    const arr = (this.hits.get(key) || []).filter(t => now - t < this.windowMs)
    if (arr.length >= this.max) return false
    arr.push(now); this.hits.set(key, arr); return true
  }
}

type Case = { input: Record<string, any>; id: string }
class Corpus { items: Case[] = []; add(c: Case) { this.items.push(c) } get(i: number) { return this.items[i] } size() { return this.items.length } }

四、执行器与审计

type Req = { path: string; method: string }
type Res = { status: (n: number) => Res; end: (b?: string) => void }
type Target = (input: Record<string, any>, req: Req, res: Res) => void

type Audit = { id: string; caseId: string; route: string; method: string; ok: boolean; timestamp: string }
function nowIso(): string { return new Date().toISOString() }

function run(target: Target, schema: Schema, corpus: Corpus, gate: RateGate, req: Req, res: Res): Audit[] {
  const audits: Audit[] = []
  for (let i = 0; i < corpus.size(); i++) {
    if (!gate.allow(req.path)) break
    const c = corpus.get(i)
    try { target(c.input, req, res); audits.push({ id: String(Date.now()) + i, caseId: c.id, route: req.path, method: req.method, ok: true, timestamp: nowIso() }) }
    catch { audits.push({ id: String(Date.now()) + i, caseId: c.id, route: req.path, method: req.method, ok: false, timestamp: nowIso() }) }
  }
  return audits
}

五、样例与验收

const schema: Schema = { properties: { username: { type: 'string', min: 3, max: 16, pattern: /^[a-z0-9_\-]+$/i }, age: { type: 'number', min: 0, max: 120, integer: true } }, required: ['username'] }

const corpus = new Corpus()
for (let i = 0; i < 50; i++) {
  const u = genStr(schema.properties['username'] as Str)
  const a = genNum(schema.properties['age'] as Num)
  corpus.add({ id: 'case_' + i, input: { username: i % 5 === 0 ? mutateString(u) : u, age: a } })
}
  • 生成策略包含边界值与注入变异;RateGate生效;重放通过caseId与输入快照实现。
  • 审计包含route/method/caseId/ok/timestamp;覆盖统计可基于字段变异率与错误比例。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部