一、输入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 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部