ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Hadrian+Vespasian+crAPI:API越权漏洞自动化检测实战

Hadrian+Vespasian+crAPI:API越权漏洞自动化检测实战 这几年做API安全测试越权漏洞一直是最让我头疼的一类。你说它难原理很简单就是把用户A的Token放到用户B的请求里再发一次一句话能讲清楚可你说它简单一旦API接口上百、对象关系绕来绕去手工在两个账号之间来回切换、逐条对比响应一个接口就能测到怀疑人生。所以当我凑齐Hadrian和Vespasian这两个检测工具再配上crAPI靶场之后说实话有点兴奋——终于有一整套能自动完成越权检测的完整链路了。这篇文章把从部署到实战使用的完整过程整理出来给同样在搞API安全测试、或者想把越权检测自动化落地的朋友做个参考。1. 这套组合到底在解决什么问题1.1 越权漏洞为什么在API场景下最难缠先说越权本身。API越权大体分两类水平越权和垂直越权。水平越权也叫BOLABroken Object Level Authorization或IDOR本质是“我能操作与你同级的别人的资源”典型场景就是改一个对象ID比如把帖子ID、订单ID换掉结果拿到了别人的数据垂直越权对应BFLABroken Function Level Authorization本质是“普通用户干了管理员才能干的事”比如普通账号直接请求内部管理接口。这两个问题在传统Web应用时代也存在但在API场景下尤其难搞。原因有三。第一API接口数量增长太快对象ID直接暴露在URL路径或请求体里每一个带ID的接口都可能是穿刺点第二API返回结构化数据越权成功时响应体里会有大量敏感字段手工比对非常累第三很多API采用无状态JWT认证但JWT里只存了userId后端又没有在每个资源操作前校验“这个资源到底属于谁”这种逻辑漏洞在代码Review时不容易发现在黑盒测试时又极度依赖账号切换。传统做法是准备两个测试账号用Burp Suite的Autorize插件或者手动改包来验证。问题在于你需要在每个端点都做一次矩阵测试有多少个接口就要切多少次会话。我见过一个中等规模的平台API端点超过三百个按这个人工验证法测完一批就要一周。自动化就成了刚需。1.2 Hadrian、Vespasian、crAPI各管哪一段这套组合里三个角色的分工非常清楚crAPI是靶场一个故意做成“满身漏洞”的API应用相当于练习用的假想敌。它内置了BOLA、BFLA、批量赋值、竞态条件、SSRF等常见API漏洞用来检验检测工具到底准不准。Hadrian负责前半段叫“攻击面采集”也好叫“接口资产梳理”也好就是把目标API的端点、参数、认证方式先摸清楚形成一张可测试的接口清单。它读取OpenAPI描述文件能解析RESTful接口规范里的路径、请求方法、参数类型、对象ID位置。Vespasian负责后半段是真正的越权判定引擎。它拿着Hadrian整理出的接口清单配合多组测试账号的Token自动做“别人的Token访问我的资源”或者“低权限Token访问高权限接口”这样的替换和请求再根据响应差异判断是否存在越权。这么拆开设计的好处是两个组件可以独立升级也可以在别的项目里单独复用。比如你已经有接口资产清单了完全可以直接把Vespasian抽出来接进去反过来如果你只想要一个接口盘点工具用Hadrian就够了。后面我会具体演示它们怎么配合。2. 核心组件原理与部署前的认知准备2.1 crAPI靶场练手用的“满身漏洞”应用crAPI全称Completely Ridiculous API是OWASP社区维护的一个免费API漏洞靶场。别看它叫“Ridiculous”它里面装的问题一点不可笑车辆信息查看、社区帖子、维修预约、用户资料修改接口设计里故意埋了各种鉴权缺陷。部署起来之后你看到的是一套带Web前端的微服务应用。整站由几个服务组成我整理了一个简表服务默认端口主要作用crAPI主入口8888API网关Web前端测试入口基本都走这里Identity服务8021用户注册、登录、JWT签发与刷新Community服务8022社区帖子、评论相关APIWorkshop服务8023车辆、预约、消息相关APIRepairShop服务8024维修店、技师状态相关APIMailHog8025模拟邮件服务器用于接收验证邮件做越权测试最常用的是Community服务的帖子接口和Identity服务的用户信息接口因为这两个地方最容易出水平越权。比如帖子列表接口返回所有人的帖子ID然后拿A的Token去请求B创建的帖子详情crAPI基本都会老老实实把数据返回来——这就是靶场存在的意义。2.2 Hadrian攻击面采集与接口资产梳理Hadrian的核心思路是“先画地图再打仗”。它做的事情和人工测试时打开API文档一个个看差不多但速度更快、也更全拉取OpenAPI描述文件解析每个路径、方法、参数名和参数位置。提取需要鉴权的接口。它通过识别接口定义里的security配置或者实测请求后是否返回401把公开接口和受限接口分出来。标注对象ID参数。这是后面越权替换的关键。Hadrian会把路径里像 /posts/{postId}、/vehicles/{id} 这类动态段标出来也会尝试从请求体里找“id”、“userId”、“vehicleId”这类字段。保存认证上下文。比如目标API使用JWT Bearer认证还是Cookie认证Token前缀是什么刷新Token的接口是哪个。用Hadrian跑完一遍它会生成一份接口清单格式类似JSON或YAML里面每条记录包含请求方法、路径、参数、是否需要认证、对象ID位置。这份清单既是给Vespasian的“弹药”也可以直接作为API资产台账。2.3 Vespasian越权判定与权限矩阵分析Vespasian承担的是最核心也最容易误报的判定工作。它不是简单地把Token换一下再发请求而是按照一套“权限矩阵”来做正交测试。原理可以这样理解假设你有4个身份普通用户A、普通用户B、管理员、游客。对同一个资源访问Vespasian会做这样的组合请求身份目标资源期望结果可能的漏洞用户A的Token用户A自己的数据成功无用户B的Token用户A被标记为私有的数据应失败水平越权游客Token或未带Token需要登录的接口应失败认证缺失普通用户Token管理功能接口应失败垂直越权关键在“期望结果”怎么定义。Vespasian的做法是先让每个身份访问自己的资源记录基线响应再去访问别人的资源做对比。如果访问别人的资源返回了和访问自己资源类似的业务成功码尤其响应体里还出现了对方的手机号、邮箱、订单号等对象归属字段就判定为疑似越权。这里的难点在于很多API对不存在或无权限的对象会返回同样的业务码比如“操作成功”或者“资源不存在”而不是HTTP 403/404。因此Vespasian设计了多维判定HTTP状态码、业务返回码、响应体大小、敏感字段正则匹配这几个维度综合打分高于阈值才进入最终报告。这也是它比简单“状态码非403即漏洞”那类脚本更实用的原因。2.4 整个架构的数据流转整条链路其实是“模板生成—资产解析—矩阵验证—报告输出”的过程Hadrian从crAPI拉取OpenAPI定义解析出接口资产清单。Vespasian读取这份清单结合用户在配置文件里给定的账号矩阵自动构造检测请求。检测完毕后结果汇总到一个报告里标明每个接口是否存在水平越权或垂直越权并附上请求响应的关键样本。我自己在第一次看这个流程的时候最直观的感受是它把“手工越权测试”这个动作拆成了“配置一次反复执行”的自动化流水线。只要账号矩阵和判定规则不变每天跑一遍都行完全不需要人工介入。3. 完整部署从零拉起一套检测环境3.1 准备Linux环境与资源配置先说一下我本地的部署环境不一定必须完全一样但可以帮你估计需要多少资源操作系统Ubuntu 22.04 LTS配置8核CPU、16GB内存、50GB磁盘Docker版本24.0.xDocker Compose插件版v2.20网络本机测试务必不要把crAPI端口暴露到公网这套组合里最占资源的是crAPI因为它是完整微服务包含数据库、消息队列、邮件模拟服务等。Hadrian和Vespasian本身比较轻容器起来后各占不到200MB内存。如果机器配置比较低12GB内存也能跑但尽量别同时跑太多其他服务。安装Docker这些基础步骤我不展开了直接检查环境docker --version docker compose version如果这两条命令都有正常输出就可以继续。安全上专门提醒一句crAPI是故意不修复漏洞的靶场系统千万不要把它的端口映射到公网或者内网开放给其他人测试完就关掉否则等于主动给别人提供攻击目标。3.2 用Docker Compose部署crAPIcrAPI官方仓库提供了完整的Docker编排文件。部署很简单git clone https://github.com/OWASP/crAPI.git cd crAPI/deploy cp .env.example .env docker compose up -d第一次启动会拉取好几组镜像耗时取决于网络环境通常在5到10分钟。启动完成后用下面的命令看服务状态docker compose ps看到所有服务状态都是Up并且没有restarting基本就成功了。然后访问主入口curl -s http://127.0.0.1:8888/openapi.json | head -c 500如果返回了JSON格式的内容说明crAPI的OpenAPI文档已经可以访问了这是后面Hadrian要用的核心输入。邮箱服务可以通过 http://127.0.0.1:8025 访问MailHog界面注册用户之后的验证邮件都会发到这里。3.3 部署Hadrian与VespasianHadrian和Vespasian的部署方式我习惯用Docker Compose统一管理。假设项目目录结构是这样security-autotest/ ├── docker-compose.hadrian.yml ├── docker-compose.vespasian.yml ├── config/ │ ├── hadrian.yaml │ └── vespasian.yaml └── reports/从项目仓库获取镜像或源码构建后通过Compose启动。以Vespasian为例它的核心配置文件vespasian.yaml包含目标地址、账号矩阵、判定规则三块。下面是一个最简示例target: base_url: http://127.0.0.1:8888 openapi_path: /openapi.json accounts: - name: alice login_url: /identity/api/auth/login username: aliceexample.com password: 123456 - name: bob login_url: /identity/api/auth/login username: bobexample.com password: 123456 - name: admin login_url: /identity/api/auth/login username: adminexample.com password: 123456 policy: auth_header: Authorization token_prefix: Bearer object_id_fields: - id - postId - vehicleId - userId success_codes: [200, 201] sensitive_fields: - email - phone - full_name这里配置了三组账号分别代表两个普通用户和一个管理员。Vespasian启动后会先调用登录接口拿到各自的JWT再根据OpenAPI定义去构造不同的替换请求。启动命令大致是# 启动Hadrian采集接口资产 docker compose -f docker-compose.hadrian.yml up -d # 启动Vespasian执行越权检测 docker compose -f docker-compose.vespasian.yml up -d3.4 部署后的连通性检查部署完不要急着跑全量检测先做一次最小化连通性验证。重点看三件事第一紧盯Vespasian日志确认它能成功登录并且拿到带正确过期时间的Token。如果日志里出现“login failed”需要用配置里的账号密码手动跑一次登录接口确认是否真的能登录。第二确认Hadrian能拉到OpenAPI文档。可以直接用命令验证curl -s http://127.0.0.1:8888/openapi.json | jq .paths | keys如果能看到一堆API路径说明资产采集的基础是通的。第三在crAPI后台注册并验证两个普通账号保证测试环境的数据准备完成。4. 实战用这套工具检测crAPI中的越权漏洞4.1 准备多用户账号矩阵自动化越权检测最核心的准备动作就是账号矩阵。没有多组账号谈不上水平越权测试。我建议最少准备三个身份用户A、用户B、管理员。A和B用于水平越权验证管理员和普通用户用于垂直越权验证。在crAPI里注册入口是Web首页。注册后通过MailHog收验证邮件curl -s http://127.0.0.1:8025/api/v2/messages | jq .[0].Content.Body从邮件里提取验证链接本地模拟浏览器访问一次账号就能激活。手工操作两三分钟一个账号准备好之后把它们填进前面提到的vespasian.yaml。这里有个容易踩的坑越权检测依赖Token有效期。很多API的JWT有效期很短crAPI默认的access token承认只有15分钟刷新Token才是长期有效的。如果配置里只填了登录账号密码每次检测前Vespasian会重新登录一次那问题不大但如果你打算把Token直接写死在配置文件里检测大型接口清单时Token中途失效会得到一大片401误报。所以最好让工具支持在每次请求前自动刷新Token或者干脆每次检测都重新登录。4.2 配置越权检测策略与判定规则账号准备好之后下一步是把判定规则做得精准一点。默认的判定规则是“返回200且响应体出现敏感字段”但实际测试中这个规则会产生不少误报需要结合业务字段做定制。拿crAPI社区帖子功能举例。两个普通用户Alice和BobAlice创建了一个帖子返回的JSON里有“postId”“authorEmail”。Bob的Token去访问Alice的帖子详情如果接口真实返回了Alice的邮箱那不用怀疑就是BOLA水平越权。Vespasian里对应的配置是这样special_rules: - path: /community/api/v2/posts/{postId} method: GET violation: BOLA auth_required: true ownership_field: authorEmail description: 通过他人postId越权查看帖子详情含义是GET /community/api/v2/posts/{postId} 这个接口请求后要校验响应体里的“authorEmail”是否等于当前Token对应用户的邮箱如果不等于就判定为越权。相比泛化的“看到email就算漏洞”这种规则直接绑定资源归属字段准确率更高。还有一个很重要的策略要设置好就是对“被删除或不存在资源”的访问。很多接口在资源不存在时返回200和空体或者在越权失败时返回“内部错误”这些情况容易误导判定。Vespasian里可以加一条“盲区规则”凡是基线响应和越权响应之间没有有效差异的接口都标记为“需人工复核”而不是直接当作安全。4.3 执行自动化检测并解读结果配置完成后执行检测。以我实际跑的流程为例# 第一步Hadrian采集资产 hadrian collect --config config/hadrian.yaml --output assets.json # 第二步Vespasian执行矩阵验证 vespasian verify --assets assets.json --config config/vespasian.yaml --report reports/result.html第一步输出assets.json包含了Hadrian识别出的接口清单。第二步才是真正的检测阶段Vespasian会自动跑一遍全量越权矩阵。检测过程中终端会打日志类似[INFO] login aliceexample.com success, token expires_in900 [INFO] login bobexample.com success, token expires_in900 [TEST] GET /community/api/v2/posts/9b1c2d3e... with bob token [TEST] GET /identity/api/v2/user/profile with bob token [VULN] BOLA found: GET /community/api/v2/posts/9b1c2d3e..., matched authorEmailaliceexample.com [VULN] BFLA found: PATCH /identity/api/v2/update-profile, user role can modify admin profile第二条漏洞是个典型的垂直越权例子。在crAPI里普通用户信息修改接口如果没做角色校验普通用户的Token直接修改其他用户资料后端就会接受。Vespasian能检测到这类问题是因为它把“修改请求”的响应和基线做了对比发现普通用户身份执行了本不该执行的功能。执行完去reports目录打开result.html报告里会按严重等级分类。我发现这类报告最好用的部分是“请求响应样本”它直接保存了当时的请求头、请求体、响应体省去了人工复现时要自己构造请求的麻烦。4.4 报告输出与原理解读报告里每个漏洞条目一般包含以下内容漏洞类型BOLA/BFLA/认证缺失、URL、使用的测试账号、判定依据、原始请求样本、原始响应样本。判定依据这部分最有价值。比如某条记录会写“使用bob的Token访问Alice创建的帖子详情响应码200响应体authorEmailaliceexample.com与当前身份不匹配判定为水平越权”。这种描述既方便安全工程师写报告也方便提交给研发复现。我不建议拿到报告直接提工单。更负责的做法是随机抽查20%的高危条目用Burp Suite或curl手工复现一遍确认不是工具本身的问题。自动化的价值是帮你把三维接口的测试压缩到几分钟但最终的“确认为漏洞”还是需要人来判断。5. 常见问题与排查技巧5.1 认证替换失败导致大量401这种情况最典型。表现是扫描器跑完报告里超过一半接口都是401。原因基本集中在三个地方JWT过期时间太短检测过程中Token失效。API使用自定义认证头比如X-Api-Key、X-User-Id而配置里还按照Authorization Bearer在传。登录接口返回的不是标准JWT而是自签字符串Vespasian没识别出来。排查思路很简单先看日志里登录那一步是否成功再看单接口请求时Header是否真的带上了Token。我自己的习惯是先在配置里把认证方式设为“manual”手工填一个刚登录拿到的Token跑通一个接口后再切到自动刷新模式。5.2 OpenAPI导入报400 invalid schema如果你导入OpenAPI定义时报类似“invalid schema”或者“400 invalid schema for function”的错误先别急着怪工具大多数情况是OpenAPI文件本身有问题。我遇到过几类情况接口描述的parameters为空但required却是true。响应体定义里带了不支持的格式比如乱码。某个schema中type字段缺失或者同时定义了多个type。解决方法是先用OpenAPI官方校验工具查一遍文档npx openapi-schema-validator openapi.json在校验工具能通过之后再让Hadrian重新解析。如果crAPI的文档也报错通常是因为缺口版本太旧先更新crAPI再拉取文档。还有一种情况是文档里写了POST /auth/login 这类登录接口但没定义安全策略导致Hadrian把登录接口也标记为“无需认证”。这不是致命问题只是会多测出一些“逻辑正常但提示未授权”的结果在报告里去重时删掉即可。5.3 误报太多怎么收敛误报是自动化越权检测最劝退人的环节。我见过有人跑完一遍报告上千条“疑似越权”实际上大部分都是设计如此比如部分个人主页本来就是公开可看的。收敛误报最有效的办法是“按资源归属字段判定”而不是按状态码判定。如果一个接口返回公开的用户名但隐藏邮箱那你看到的“响应中有用户信息”根本不算越权。正确做法是把接口的参数、认证身份、响应字段三者绑定只有当前身份和资源归属不一致且响应里暴露了本该隔离的字段才判定为越权。另外Vespasian支持配置“忽略列表”可以把公开接口直接排除。例如crAPI里帖子列表本身就允许游客查看那就没有必要做越权测试把它从资产清单里摘出去报告会干净很多。5.4 并发、限流与稳定性问题把自动化测试用于真实环境时最容易踩的坑是限流。很多API网关会限制单IP的QPSVespasian这种并发扫描器短时间内疯狂发请求很容易触发风控反而拿到一堆假数据。解决办法是在配置里加一个请求间隔同时把并发度调低policy: request_interval_ms: 200 concurrency: 5 retry_on_rate_limit: true200毫秒间隔可以保证一分钟最多300个请求对大多数API来说都不算激进。如果被测系统对数据准确性要求高建议把间隔调到500毫秒以上用时间换稳定。还有个细节带上真实的User-Agent和Accept头有些API会拦截默认的Go/Python客户端指纹。Vespasian提供了自定义Header配置把浏览器身份传进去即可。6. 把自动化越权检测嵌入日常安全工作6.1 与API平台和网关联动做到这一步说明你已经不再满足于在靶场里跑了。回到真实业务环境自动化越权检测最顺滑的接入点是API网关日志。网关通常记录了每次请求的路径、调用方身份、响应码、响应耗时这些数据经过脱敏后可以直接提取出接口资产管理的基础数据。我之前做过一个实践每天凌晨从网关拉取前一天的access log抽出去重后的API路径喂给Hadrian做资产采集下午定时用Vespasian跑一遍越权矩阵。这套流程跑下来新接口上线后最多一天内就能进入越权检测范围不需要手工维护接口清单。6.2 在CI/CD里作为质量门禁更理想的状态是把越权检测塞进CI/CD流水线但这里必须非常谨慎。自动化检测工具在发布流程中容易产生大量误报把功能正常的版本卡住因此我建议采用“阻塞高危”、不阻塞全部的模式只有确认是高危越权时才让流水线失败疑似项一律进入消息通知待人工确认。可以在流水线里加一步vespasian verify --config config/vespasian.yaml --fail-on BOLA --report build/report.html只有出现BOLA这类强信号漏洞才返回非零退出码既保证了安全底线又不会因为误报导致发布阻塞。研发看到漏洞报告后直接在同一个流水线里生成工单修复状态的反馈链路也顺了。6.3 授权边界与合规提醒这部分是我最想强调的。自动化越权检测本质上是“模拟攻击”无论工具多好用都必须限定在你有明确授权的环境内。测试crAPI这样的靶场无所谓但拿Vespasian去扫描一个没有合同约束的第三方平台性质就完全不同了。所以在使用这套工具之前至少要确认三件事第一被测系统是本公司资产或靶场系统第二测试时间段和测试账号已经知会相关团队第三扫描过程中不涉及真实用户敏感数据的导出。做到这三点自动化越权检测才能安全地变成日常安全建设的一部分。前几年做安全测试越权漏洞全靠人工一个接口一个接口地磨磨到最后经常漏得跟筛子一样。现在有了Hadrian和Vespasian这套组合我最大的感受是“越权检测终于可以做例行巡检了”。我个人的习惯是每天凌晨自动跑一遍早上到公司先看报告只花十来分钟审高危项剩下的时间用来跟进真正的业务权限设计问题。这套方案并不是银弹复杂的RBAC和ABAC混合权限模型仍然需要人工参与分析但把普通场景的越权检测自动化之后我能把注意力放到更值得深挖的地方。如果你也在为API越权检测效率发愁建议直接拿crAPI练一遍手跑顺了再考虑接入自己的测试流程。
返回列表