一、概述
1.1 背景
Completely Ridiculous API (crAPI)是 OWASP 社区支持的开源 API 安全测试靶场,旨在模拟真实业务场景中的 API 漏洞,帮助安全从业者实践 OWASP API Top 10 等核心风险的挖掘与利用。项目通过故意引入设计缺陷,还原 API 全生命周期的安全问题,是 API 安全学习、渗透测试训练的核心工具。
1.2 技术栈
crAPI 采用 微服务架构 模拟复杂业务系统,技术栈覆盖多语言、多数据库,最大化漏洞场景的多样性:
分层设计
前端层:crAPI Web Services(JS)
- 角色:用户交互入口(网页界面),负责接收用户操作(登录、下单、发帖),转发请求至后端微服务。
- 技术意义:模拟真实 Web 应用的前端层,暴露请求篡改、前端逻辑绕过等漏洞场景。
中间服务层(微服务集群,多语言实现):
- Identity Service (Java):
- 职责:用户身份认证(JWT/OTP 生成与验证)、车辆信息管理。
- 技术关联:Java 生态常见漏洞(如 JWT 算法混淆、弱认证逻辑)。
- Community Service (Go):
- 职责:社区功能(博客发布、评论互动)。
- 技术关联:Go 服务的输入验证缺陷(如 BOLA 越权访问他人博客)。
- Workshop Service (Python):
- 职责:维修厂管理、配件订单处理。
- 技术关联:Python 服务的业务逻辑漏洞(如批量赋值篡改订单金额)。
- Mailhog:
- 角色:邮件测试工具,模拟身份服务的邮件发送(如注册验证邮件)。
- 技术意义:暴露邮件伪造、OTP 劫持(若逻辑缺陷)的测试场景。
数据层:PostgreSQL or MongoDB
- 设计意图:支持 SQL(PostgreSQL)和 NoSQL(MongoDB)双数据库,覆盖 SQL 注入 与 NoSQL 注入 测试场景。
整体数据流视角
crAPI 通过 “多语言微服务 + 双数据库 + 分层交互” 的架构,完美支撑 OWASP API Top 10 漏洞的测试场景
1.3 业务场景
crAPI 模拟 B2C 汽车维修服务平台,核心业务流程包括:
- 用户生命周期:注册(Mailhog 收验证邮件)→ 登录(JWT 认证)→ 管理车辆信息。
- 服务请求:提交汽车维修申请(选择技师、描述问题)。
- 电商功能:购买汽车配件(下单、支付)。
- 社区互动:发布博客、评论互动。
工作原理:前端通过 HTTP API 调用后端微服务,服务间通过内部接口交互,最终操作 SQL/NoSQL 数据库。系统 故意省略安全校验逻辑(如权限验证、输入过滤、认证强化),使测试者能复现真实漏洞。
1.4 挑战
根据项目中文档的challenge描述,crAPI 聚焦 API 全链路安全测试,覆盖 OWASP API Top 10 核心风险,具体挑战如下:
编号 | 类别 | 描述 |
---|---|---|
1 | BOLA Vulnerabilities | 泄露其他用户的车辆敏感信息。需要找到其他用户的车辆 ID(非连续 GUID),并找到接收车辆 ID 并返回其信息的 API 端点。 |
2 | BOLA Vulnerabilities | 访问其他用户提交的机械师报告。需分析报告提交过程,找到暴露机械师报告详情的隐藏 API 端点,并通过修改报告 ID 访问其他报告。 |
3 | Broken User Authentication | 重置其他用户的密码。需找到其他用户的邮箱,可能需要暴力破解,并利用 REST API 的可预测性寻找相关端点。 |
4 | Excessive Data Exposure | 找到泄露其他用户敏感信息的 API 端点。 |
5 | Excessive Data Exposure | 找到泄露视频内部属性的 API 端点,该属性及其值有助于利用其他漏洞。 |
6 | Rate Limiting | 利用 “联系机械师” 功能执行七层 DoS 攻击。 |
7 | BFLA | 删除其他用户的视频。需利用 REST API 的可预测性找到管理员删除视频的端点。 |
8 | Mass Assignment | 免费获取商品。找到影子 API 端点以编辑特定订单的属性,从而为未实际退货的商品获取退款。 |
9 | Mass Assignment | 将余额增加 1000 美元或更多。在解决 “免费获取商品” 挑战的基础上,通过更大金额的退款实现。 |
10 | Mass Assignment | 更新视频的内部属性。找到可修改视频内部属性的端点,修改其值以利用其他漏洞。 |
11 | SSRF | 让 crAPI 向 “www.google.com” 发送 HTTP 请求并返回该 HTTP 响应。 |
12 | NoSQL Injection | 无需知道优惠码即可获取免费优惠券。 |
13 | SQL Injection | 通过修改数据库,重新使用已领取的优惠券。 |
14 | Unauthenticated Access | 找到不对用户进行身份验证检查的端点。 |
15 | JWT Vulnerabilities | 找到伪造有效 JWT 令牌的方法,以获取平台的完全访问权限。 |
16 | LLM Vulnerabilities | 利用聊天机器人进行成功的提示注入,实现客户端渲染注入。 |
17 | LLM Vulnerabilities | 利用聊天机器人提取其他用户的凭据并查看其订单。 |
18 | LLM Vulnerabilities | 让聊天机器人代表其他用户执行操作(如下单)。 |
- | 秘密挑战 | 有 3 个复杂的秘密挑战,未提供详细信息。 |
二、安装
GitHub 项目地址:https://github.com/OWASP/crAPI
docker安装命令:
curl -o /tmp/crapi.zip https://github.com/OWASP/crAPI/archive/refs/heads/main.zip
unzip /tmp/crapi.zip
cd crAPI-main/deploy/docker
docker compose pull
docker compose -f docker-compose.yml --compatibility up -d
pull之后,拉下的image
启动,安装成功之后访问http://localhost:8888
启动之后,你会发现他只允许127回环地址访问
此时,先将容器停止
sudo docker compose -f docker-compose.yml --compatibility stop
再执行
sudo LISTEN_IP="0.0.0.0" docker compose -f docker-compose.yml --compatibility up -d
再次访问
所有电子邮件默认发送到 mailhog 服务,可以检查 http://localhost:8025 如果需要,您可以更改 smtp 配置,但所有带有 domain example.com 的电子邮件仍会转到 mailhog。
停止命令
sudo docker compose -f docker-compose.yml --compatibility stop
三、挑战
工具:burp suite 社区版本
靶场共两个网站,8888端口为汽修维修服务平台,8025为邮箱服务平台。
3.1 账户注册
mathias
security101@qq.com
19111111111
Aa@123457
使用账户登录汽修维修平台,登录平台后会要求你输入车辆的VIN和PIN码,该信息在邮箱服务平台。
验证成功之后,会获取你的车辆信息。
3.2 泄露其他用户的车辆信息API端点
1、在社区板块,有其他用户的留言信息,访问留言板时,通过butp进行抓包,丢掉第一个包,在第二个包中看到有api路径,故将该数据包放在burp中的repeater模块。
2、在返回包中除了看到留言板中的留言者姓名和时间外还有车辆信息id,邮箱等敏感信息。
"id":"HoRBqzPgsMZSge9qq5SaWE","nickname":"maolin","email":"1666197054@gmail.com","vehicleid":"8ecb5f23-e729-469f-9980-9526dedbc9b3"
"id":"bGqqQzEN8YGNFiGSDNuq4a","nickname":"Robot","email":"robot001@example.com","vehicleid":"4bae9968-ec7f-4de3-a3a0-ba1b2ab5e5e5"
"id":"TWqjwxnLizUYNjujbBSKxZ","nickname":"Pogba","email":"pogba006@example.com","vehicleid":"cd515c12-0fc1-48ae-8b61-9230b70a845b"
"id":"5zH3bUtG7ehope6cgDfhvK","nickname":"Adam","email":"adam007@example.com","vehicleid":"f89b5f21-7829-45cb-a650-299a61090378"
3、点击留言板中任意一个留言,然后抓包,发现除了当前留言者的姓名和时间,返回包中还有其他敏感信息并且观察GET 的URL路径。
4、是否可以通过修改id值,直接看到id值对应的用户敏感信息呢?
3.3 访问其他用户提交给技工的报告。
1、点击【Contact Mechanic】,联系技工。
2、选择技工,并且描述问题。
3、点击发送时,抓包并且发送到repeater模块中。
4、分析请求包和响应包中的字段含义。
请求包:
mechanic_code: "TRAC_JME" - 所选择的维修人员
problem_details: "car error" - 描述的问题
vin: "6JDYB47AZQO659262" - 车辆vin码
mechanic_api: "http://192.168.0.102:8888/workshop/api/mechanic/receive_report" - 可能是接收该报告的 API 接口地址
repeat_request_if_failed: false - 请求失败时是否重复发送
number_of_repeats: 1 - 重复发送的次数
返回包
esponse_from_mechanic_api - 维修接口的具体响应数据
id: 13 - 可能是报告唯一id号
sent: true - 报告发送成功
"report_link":"http://192.168.0.102:8888/workshop/api/mechanic/mechanic_report?report_id=13" - 报告链接
"status":200 - 状态码
根据分析,可直接访问请求包和响应包中的两个api链接。
5、当直接使用浏览器访问时,要么显示没有相应参数,要么没有 jwt值。
6、在burp中访问,并且携带当前用户的jwt值,修改请求方法POST为GET
鼠标右键,选择【Change request method】
id为13直接显示出报告,12呢?10呢?是否可以爆破id号?
3.4 重置其他用户的密码
1、寻找功能点,在登录处,有忘记密码。
2、先以自己的邮箱为例,当输入邮箱之后,会有一个OTP校验码发送到你的邮箱。
之后就会进入修改密码处。
3、使用之前所获取的邮箱pogba006@example.com
,当输入邮箱之后,也会有一个otp的验证码发送到了邮箱。
之后进入了修改密码界面。
随便填写之后进行抓包。
4、4位数的验证码是可以爆破的,现在只要看是否可以重复发包。
当连续发送5次后,显示500 error。
5、观察URL,是否出现了v3,v3可能是v3版本,那么v2版本呢?
经测试,v2版本是可以一直重发包,来验证OTP校验码是否正确。
6、理论是可以通过爆破验证码来修改pogba006@example.com
邮箱密码,由于使用的是社区版本,爆破速度太慢,就不展示了。
3.5 找到泄露其他用户敏感信息的 API 端点
1、根据之前的所测试的,在社区板块中,返回包直接返回所有留言者的敏感信息。
2、api端点为/community/api/v2/community/posts/recent
3.6 找到泄露视频内部属性的 API 端点
1、在个人信息处可以上传视频,创建一个101.txt的文本文件,然后修改后缀名为mp4,上传时,抓取数据包放到repeater模块中观察响应包。
在响应包中可以看到,有id号,视频名称、视频编码格式以及类型。
2、上传成功的视频可以进行一下操作。
3、修改视频名称时,抓包,观察响应包。
4、将请求方式修改为GET型,参数52改为50。
泄露视频内部属性的 API 端点为/identity/api/v2/user/videos/50
3.7 【contact mechanic】功能完成第7层DoS
1、在之前分析过【contact mechanic】功能提交后的请求包和响应包,关键点在:
repeat_request_if_failed: false - 请求失败时是否重复发送
number_of_repeats: 1 - 重复发送的次数
2、修改参数,即可进行第七层DOS。
3.8 删除其他用户的视频
1、观察修改视频名称的请求包,PUT请求方法为更新,那么删除就是【DELETE】。
2、是否可以使用【DELETE】请求方法呢,可以使用 【OPTIONS】 请求方法,通过响应的 Allow 头部可查看支持的请求方法。
3、将【OPTIONS】 请求方法修改为【DELETE】请求方法。
显示权限不足。
4、观察URL,是否可以将【user】修改为【admin】呢?
5、修改ID号
3.9 白嫖商品
1、当前有80美金。
2、点击Buy的时候抓取数据包分析。
请求包中:
product_id - 可能为商品编号
quantity - 可能为购买的数量
响应包中:
id - 可能为订单编号
message - 提示信息
credit - 当前账户余额
3、点击【Past Orders】,查看订单信息,随便点击一个订单查看详细信息,然后抓包。
响应包中有一个字段为【“status”:“delivered”】,表示当前订单已经完成,如果【status】可以修改,是否可以先退款,再完成订单呢?
4、将【GET】请求方法改为【PUT】,ststus属性不知道有哪些,可以先尝试,随便写。
根据响应包可知,ststus状态有这些:‘delivered’,‘return pending’ or ‘returned’。
5、修改状态码为【returned】。
6、再修改为【delivered】。
7、返回购物界面,查看余额。
再查看订单信息。
3.9 将余额增加 1000 美元或更多
1、根据前面的经验,quantity 参数为购买数量,1个商品为10美金,那么退我100份商品不就是1000美金吗?
只需要增加一个参数:
2、返回网站查看余额:
3.10 更新视频的内部属性
1、根据之前分析,抓取修改名称时的数据包。
2、可以直接修改名称,那么其他属性是不是也可以直接修改呢?
3.11 SSRF
1、根据之前的分析,再给技工提交问题时,发现数据包中数据值是有URL链接的。
2、【mechanic_api】属性值是否可以做修改?
利用dnslog进行检验,http://www.dnslog.cn/
成功。
3.12 无需知道优惠码即可获取免费优惠券。
1、优惠券 可能会和数据库打交道。
2、在兑换优惠卷时,抓包。
3、尝试对【coupon_code】属性值进行注入。
4、此处是一个nosql注入,可以直接使用:
{"coupon_code":{
"$ne":"xxxxxxxxxxxx"
}}
5、兑换码为【TRAC075】。
3.13 找到不对用户进行身份验证检查的端点
1、访问自己的购物详情订单时,抓取数据包。
2、将id:14修改为其他值呢?
3.14 支付漏洞
1、当前的余额:
2、购买商品时抓取数据包。
3、根据之前的分析【quantity】参数为数量,如果数量为负数呢?
3.15 增加商品
1、在访问shop时,抓取第二个数据包,放在repeater模块中
2、同样可以先尝试使用 【OPTIONS】 请求方法,通过响应的 Allow 头部可查看支持的请求方法。
3、增加商品,构造参数。
{"id":3,"name":"security","price":"101.00","image_url":"https://i1.hdslb.com/bfs/face/40d1e8383ee5aae2cb45387ade5705ab95ad6bef.jpg@128w_128h_1c_1s.webp"}
4、返回网站的shop栏。
3.16 待续
JWT 与 注入 后续补充。