attack-surface-mapping

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Attack Surface Mapping

攻击面测绘

Given one target and one application, draw the surface from what that application already exposes. Then stop. Testing lives in other skills.
This skill is the fast path. Success is a portrait plus a host/API inventory plus a key table plus response-class labels plus an object graph. A probe count is not success.
Field patterns for where the rest of the surface actually lives: SURFACE_PATTERNS.md.
给定一个目标和一个应用,从该应用已经暴露的内容绘制攻击面,然后停止。测试属于其他 skill。
本 skill 是快速路径。成功意味着一份画像 + 主机/API 清单 + 密钥表 + 响应类别标记 + 对象图。探测次数不是成功。
其余攻击面实际所在位置的字段模式:SURFACE_PATTERNS.md。

When

何时使用

  • A new URL, a new app, or "I only see a login page"
  • Need to know what to test before loading injection / auth / upload skills
  • The agent is about to brute directories, spray quotes, or expand to unrelated hosts
Do not use this skill to expand an organization-wide host universe. Map the current application cluster. Finish it. Then, if scope allows, take the next cluster.
Authorization and destruction bounds: hack start gate. Stay in scope.
  • 一个新 URL、一个新应用,或“我只看到登录页面”
  • 在加载 injection / auth / upload 等 skill 之前,需要知道要测什么
  • agent 正要爆破目录、喷洒引号或扩展到无关主机
不要使用本 skill 去扩展组织级的主机范围。只测绘当前应用集群,完成它。然后,如果授权范围允许,再处理下一个集群。
授权与破坏边界:以 hack 的起始门禁为准。保持在授权范围内。

What must exist (not a file tree)

必须具备的事实(不是文件树)

Before any vulnerability skill, these facts must be retrievable. Persist them in whatever the local workspace already uses for notes and evidence — an existing task folder, a proxy project, session notes, a ticket. Do not invent a new directory layout when one is already in play.
FactKeep
Portrait3–5 sentences, not an essay
HostsBusiness hosts, gateways, API domains this app already named
EndpointsMethod, path, params, auth required?
KeysSigning salt, ciphertext id + frontend pubkey, hidden/admin route, hardcoded demo account. Record
none
per row if absent
Response classLogin-gate / differential / unauthenticated exception
Object graphlist → detail → attachment / export / approval
Requests, diffs, and screenshots stay where they were captured when that store is already the working set. Empty inventory plus "I will brute paths next" is a failed mapping.
在任何漏洞 skill 之前,这些事实必须可检索。将它们持久化到本地工作区已经用于笔记和证据的地方——现有任务文件夹、代理项目、会话笔记、工单。如果已有目录结构,不要另建新的目录布局。
事实保留内容
画像3–5 句话,不是一篇长文
主机该应用已提到的业务主机、网关、API 域名
端点方法、路径、参数、是否需要认证
密钥签名盐、密文 ID + 前端公钥、隐藏/管理后台路由、硬编码演示账号。若没有,每行记录
none
响应类别登录门禁 / 差异响应 / 未认证异常
对象图列表 → 详情 → 附件 / 导出 / 审批
请求、差异和截图保留在它们被捕获的地方,只要该存储已经是工作集合。空清单加上“我接下来要爆破路径”就是失败的测绘。

Fast path

快速路径

Portrait
  → find the business plane (login is a shell)
  → inventory from the app (JS / traffic / docs), keys not just paths
  → classify responses
  → grow the object graph from responses
  → same-skin / same-gate collapse
  → surface-done → hand off
Do not insert directory brute, full-template scanning, or password spraying into this loop.
Portrait
  → find the business plane (login is a shell)
  → inventory from the app (JS / traffic / docs), keys not just paths
  → classify responses
  → grow the object graph from responses
  → same-skin / same-gate collapse
  → surface-done → hand off
不要在这个循环中插入目录爆破、全模板扫描或密码喷洒。

1. Portrait (mandatory, before any request spray)

1. 画像(强制,在任何请求喷洒之前)

Three to five sentences:
  • Who uses this (consumer / merchant / operator)
  • Core objects (order, ticket, coupon, document, tenant)
  • Which fields hold money, privilege, or state
  • What an unauthenticated caller can already touch
Cannot write it → capture one real page's traffic first. Do not scan into a blank portrait.
Mini-program, native app, GraphQL, WebSocket, batch export, agent-with-tools, template preview, file convert, command RPC: treat as this site's surface, not a sidenote.
3–5 句话:
  • 谁在使用(消费者 / 商家 / 运营者)
  • 核心对象(订单、票据、优惠券、文档、租户)
  • 哪些字段包含金钱、权限或状态
  • 未认证调用者已经可以触及什么
写不出来 → 先捕获一个真实页面的流量。不要对着空白的画像开始扫描。
小程序、原生应用、GraphQL、WebSocket、批量导出、带工具的 agent、模板预览、文件转换、命令 RPC:都视为本站点攻击面,不是边角料。

2. Find the business plane

2. 找到业务平面

A login page is a shell. The surface is the post-login business host or the same-host gateway behind the form. Seeing a login page is not a reason to change assets.
Find the plane without logging in:
  • Query:
    service=
    /
    redirect_uri=
    /
    callback=
    /
    returnUrl=
    /
    jumpUrl=
    /
    next=
  • Client:
    env.js
    /
    baseURL
    /
    apiHost
    /
    /prod-api
    /
    VUE_APP_*
    /
    REACT_APP_*
  • Transport: 302
    Location
    ,
    X-Frame-Options: ALLOW-FROM
  • Naming: same-product
    api
    /
    admin
    /
    gateway
    / product host
Someone else's SSO / CAS / OAuth page: do not audit the identity product. Follow it back to this product's business plane. Criterion: the login page's owner is not this business.
Alive vs dead:
Treat as aliveTreat as dead
401, 403, login wall, admin challengeTimeout, parking page, no business response
Management console challengeDefault CDN / empty static shell with no script
Alive ≠ grind the form. Captcha OCR, slider farms, and login-box dictionaries are not mapping.
Form checks that are in-scope for mapping (once, then stop): empty password, skip-password step, extra fields on the login API (
tenant
/
corpId
/
moduleId
), business paths already visible next to the form (list / detail / stats). Username and password boxes are not business parameters.
登录页只是一个外壳。攻击面是登录后的业务主机,或表单背后的同主机网关。看到登录页不是更换资产的理由。
不登录也能找到业务平面:
  • Query:
    service=
    /
    redirect_uri=
    /
    callback=
    /
    returnUrl=
    /
    jumpUrl=
    /
    next=
  • Client:
    env.js
    /
    baseURL
    /
    apiHost
    /
    /prod-api
    /
    VUE_APP_*
    /
    REACT_APP_*
  • Transport: 302
    Location
    ,
    X-Frame-Options: ALLOW-FROM
  • Naming: same-product
    api
    /
    admin
    /
    gateway
    / product host
别人的 SSO / CAS / OAuth 页面:不要审计身份产品。沿它回到本产品的业务平面。判断标准:登录页的所有者不是本业务。
存活 vs 无效:
视为存活视为无效
401、403、登录墙、管理挑战超时、停放页、无业务响应
管理控制台挑战默认 CDN / 没有脚本的空静态壳
存活 ≠ 死磕表单。验证码 OCR、滑块农场和登录框字典都不是测绘。
在测绘范围内允许的表单检查(只做一次,然后停止):空密码、跳过密码步骤、登录 API 上的额外字段(
tenant
/
corpId
/
moduleId
)、表单旁边已经可见的业务路径(list / detail / stats)。用户名和密码框不是业务参数。

3. Inventory from the application

3. 从应用建立清单

Frontend present: open a business page → collect scripts (including async chunks and sourcemaps) → extract APIs and keys → capture traffic to fill gaps → persist endpoints and keys in the local evidence store.
JS extracts more than
/api/
paths. For each row, write the value or
none
:
ExtractWhy it is surface
/api/
paths, RPC cmd numbers, GraphQL operations
Endpoint list
Signing salt, hardcoded key,
sign
that does not need a cookie
Replay without a session
Ciphertext id + frontend public key (
modulus
/ JSEncrypt)
Neighbor-id is encryptable
Hidden / admin routes in the router, unpublished chunksAPIs the UI never shows
Hardcoded demo account, test tenant, experience entryA key, not a login-form dictionary
Command / template / expression / file-convert / RPC-with-exec / agent toolsExecution plane; do not invent params if none exist
No frontend / JS blocked: Swagger, OpenAPI, captured traffic, HTML inline, known gateway prefixes. Do not idle waiting for a full JS dump.
Frontend present but inventory empty → directory brute is forbidden.
Docs and debug planes, if this app already linked them: api-recon-and-docs. Exposed VCS / backups: insecure-source-code-management. Both are this cluster's extra planes, not a new search.
有前端: 打开一个业务页面 → 收集脚本(包括异步 chunk 和 sourcemap)→ 提取 API 和密钥 → 捕获流量补缺口 → 将端点和密钥持久化到本地证据存储。
JS 能提取的不只是
/api/
路径。对每一行,写下值或
none
:
提取项为什么它是攻击面
/api/
路径、RPC 命令号、GraphQL 操作
端点列表
签名盐、硬编码密钥、不需要 cookie 的
sign
无会话重放
密文 ID + 前端公钥(
modulus
/ JSEncrypt)
相邻 ID 可被加密
路由中的隐藏 / 管理后台路由、未发布的 chunkUI 从不展示的 API
硬编码演示账号、测试租户、体验入口是一个密钥,不是登录框字典
命令 / 模板 / 表达式 / 文件转换 / 带执行的 RPC / 工具类 agent执行平面;如果没有参数就不要编造参数
没有前端 / JS 被阻止: 使用 Swagger、OpenAPI、已捕获流量、HTML 内联、已知网关前缀。不要空等完整的 JS 转储。
有前端但清单为空 → 目录爆破是被禁止的。
如果该应用已经链接了文档和调试平面:api-recon-and-docs。暴露的 VCS / 备份:insecure-source-code-management。两者都是本集群的额外平面,不是新的搜索。

4. Classify responses before any probe

4. 在任何探测前先对响应分类

ResponseClassMapping action
One sentence "please log in" /
NotLogin
, no list / total / roster / detail
Login gateDo not mark as an injection surface
Has list / total / business fields, even
total=0
DifferentialKeep on the test list
Error, 500, timeout, or length/timing off baselineDifferentialKeep; unstable diff → stop after one or two compares
Missing a parameter dumps a roster or detailUnauthenticated exceptionHighest-priority unauth surface
An empty list is "structure returned, count is 0", not a login gate.
响应类别测绘动作
一句话“请登录” /
NotLogin
,没有列表 / total / 花名册 / 详情
登录门禁不要标记为注入攻击面
有列表 / total / 业务字段,即使
total=0
差异响应保留在测试列表中
报错、500、超时,或长度/时间偏离基线差异响应保留;差异不稳定 → 比较一两次后停止
缺少参数就返回花名册或详情未认证异常最高优先级的未认证攻击面
空列表是“返回了结构,计数为 0”,不是登录门禁。

5. Object graph is surface

5. 对象图就是攻击面

Identifiers in any field name (
id
/
userId
/
tenantId
/
fileKey
/
openid
/ ciphertext PK) are surface.
Walk, and write it down:
list → detail → attachment / export / preview / approval
Parent authorized, child often not. After a list passes, the next surface is the attachment, not a new host.
Anything a response newly names — id, download URL, token, internal host, role field — goes onto this site's queue immediately. Do not drop it when changing pages.
任何字段名中的标识符(
id
/
userId
/
tenantId
/
fileKey
/
openid
/ 密文主键)都是攻击面。
遍历并记录下来:
list → detail → attachment / export / preview / approval
父级已授权,子级往往没有。列表通过后,下一个攻击面是附件,而不是新主机。
响应中新出现的任何东西——id、下载 URL、token、内部主机、角色字段——立即加入本站点的队列。切换页面时不要丢掉它。

6. Collapse same-skin and same-gate

6. 合并同皮肤与同网关

Fingerprint-same (title, skeleton, build hash, API prefix, login chain): pick 2–3 representatives. Siblings only get a glance: new path / new port / another app / another
jump
/
service=
/
moduleId
business plane. No new plane → do not open a full matrix.
Same-gate (all four):
  1. Business paths already extracted
  2. Unauthenticated exceptions already probed
  3. Remaining business endpoints return the same login-code family
  4. No unauthenticated other-subject data, and no missing-param dump
Then stop this gate. Siblings with the same
baseURL
+ same code: glance for new paths or a code change. Auth endpoints (issue session / reset / rebind / ticket-swap) still go on the list if present; they are not "please log in, so skip".
Same host is not same-skin. Extra paths on the same host always expand.
No business script, default server page, or leftover behind the same login-code family: falsify once and leave. Do not pad with a full matrix.
指纹相同(标题、骨架、构建哈希、API 前缀、登录链):选 2–3 个代表。兄弟节点只扫一眼:新路径 / 新端口 / 另一个应用 / 另一个
jump
/
service=
/
moduleId
业务平面。没有新平面 → 不要铺开完整矩阵。
同网关(全部四条):
  1. 业务路径已被提取
  2. 未认证异常已被探测
  3. 其余业务端点返回同一登录码族
  4. 没有未认证的其他主体数据,也没有缺参转储
然后停止这个网关。相同
baseURL
+ 相同代码的兄弟节点:扫一眼新路径或代码变化。认证端点(发会话 / 重置 / 重新绑定 / 票据交换)如果存在仍要列入清单;它们不是“请登录,所以跳过”。
同主机不是同皮肤。同一主机上的额外路径总是要扩展。
同一登录码族后面没有业务脚本、默认服务器页面或遗留物:证伪一次然后离开。不要用完整矩阵凑数。

7. Surface-done (then hand off)

7. 攻击面完成(然后交接)

Mapping is done when:
  1. Portrait exists, or this is recorded as a shell with no business object
  2. Endpoint inventory exists (full or degraded); keys have values or
    none
    — in the local evidence store, not a prescribed path
  3. Response classes labeled; unauthenticated exceptions ticked
  4. Object graph recorded, or recorded as unlistable
  5. Same-skin / same-gate leftovers glanced, not rematrixed
  6. Auth endpoints listed if the inventory has issue-session / reset / rebind / ticket-swap / 2FA — listed, not yet exploited
Then load hack for effort order and the matching category skill. Do not start testing inside this file.
满足以下条件时测绘完成:
  1. 画像存在,或已被记录为没有业务对象的外壳
  2. 端点清单存在(完整或降级);密钥有值或
    none
    ——保存在本地证据存储中,不是指定的路径
  3. 响应类别已标记;未认证异常已勾选
  4. 对象图已记录,或记录为不可列举
  5. 同皮肤 / 同网关残留已扫一眼,没有重新铺矩阵
  6. 如果清单中有发会话 / 重置 / 重新绑定 / 票据交换 / 2FA,则列出认证端点——只列出,尚未利用
然后加载 hack 以确定投入顺序和匹配的分类 skill。不要在这个文件里开始测试。

Handoff

交接

Surface you drewLoad
Unauthenticated other-subject data, object idsauth-sec, idor-broken-object-authorization
Issue-session / reset / rebind / ticket-swapauthbypass-authentication-flaws
Differential filters, URL-fetch params, templatesinjection-checking
Upload / preview / convertupload-insecure-files
Money / coupon / stock / approvalbusiness-logic-vuln
REST / GraphQL / gateway docsapi-sec
Public middleware adminunauthorized-access-common-services
你绘制的攻击面加载
未认证的其他主体数据、对象 IDauth-sec、idor-broken-object-authorization
发会话 / 重置 / 重新绑定 / 票据交换authbypass-authentication-flaws
差异过滤、URL 拉取参数、模板injection-checking
上传 / 预览 / 转换upload-insecure-files
金钱 / 优惠券 / 库存 / 审批business-logic-vuln
REST / GraphQL / 网关文档api-sec
公开中间件管理后台unauthorized-access-common-services

Anti-patterns

反模式

  • Opening with directory brute or full-template scanning
  • Grinding captcha / default passwords on login HTML
  • Seeing a login page and changing assets
  • Script extracted only paths; salts, ciphertext ids, hidden routes, demo accounts unread
  • Treating 401 / 403 / login wall as dead
  • Pouring a full matrix into the same login-code family
  • Expanding to a new cluster while this application's live surface is unfinished
  • Calling mapping "done" because the homepage returned 200
  • Minting a new notes tree when the workspace or proxy project already holds the evidence
  • 以目录爆破或全模板扫描开头
  • 死磕登录 HTML 上的验证码 / 默认密码
  • 看到登录页就更换资产
  • 脚本只提取了路径;盐、密文 ID、隐藏路由、演示账号未读取
  • 把 401 / 403 / 登录墙视为无效
  • 对同一登录码族铺开完整矩阵
  • 当前应用的活跃攻击面尚未完成时就扩展到新集群
  • 因为首页返回 200 就宣称测绘“完成”
  • 当工作区或代理项目已经持有证据时,新建一套笔记目录