1638 字
8 分钟
API漏洞

1.查找 api 文档

  • 常见路径:/api,/docs,/swagger,/v1,/openapi,尝试常见拼接方式:/swagger-uo/,/api/docs/,/openapi.json

  • 分析请求中的 api 路径,测试端点,分析 js 文件中可能隐藏的 api 路径

  • 查看 robots.txt 文件

走一遍正常流程后在历史记录发现修改 email 的 api 请求

逐个探测端点,发现访问/api 可以查看 api 文档,利用文档中信息完成实验

2.识别 api 端点支持的 http 方法

走一遍流程后发现存在/api/products/1/price 接口

测试端点发现都不能查看 api 文档,测试不同请求方法,使用 OPTIONS 方法让服务器返回支持的请求方法发现支持 GET 和 PATCH

返回 Unauthorized,未认证,先登陆一下账号

报错返回了可利用信息

添加请求头后页面依旧报错,联系刚添加的Content-Type: application/json 猜想是不是要添加 json 信息

添加后依然报错,但页面回显了有用信息,可以猜测是不是可以通过 price 篡改商品价格

查看网页商品价格也变成了 0

3.寻找隐藏参数

api 接口可能藏有未公开的参数,而这些参数又很有可能是可利用的,高价值的点,找出这些参数,查看是否可控,可通过

批量赋值漏洞:当 api 允许对多个参数进行批量更新时没有对更新的参数进行校验就可能导致更改了隐藏参数的值,可能导致访问权限的失控,如提交多余字段 is_admin=true,未作校验直接提升普通用户为管理员权限

开始时抓包了一个 get 请求的 api 接口

测试端点看能不能查看 api 文档,文档中除了 get 方法外,还可以使用 post 请求方法,仔细查看 post 方法是如何使用的,其中提到了还有一个参数{“order” Order},开始没看清还以为要在 url 添加一个 order 参数,post 请求谁家好人在 url 出添加参数(虽然好像可以),同时可以注意到参数是个 json 格式的参数

按照他的格式添加一个 json 格式的数据,回显表示未定义键 chosen_products,同时表明了是一个数组格式的值

可以联想之前的 get 请求返回的一段 json 格式的数据,其中就包含了 chosen_discount 和 chosen_products 参数,而这个 post 请求却只要我们添加chosen_products,猜想chosen_discount 会不会是一个 post 请求中的隐藏参数,get 用来查询商品信息,post 用来生成商品信息,post 参数中少的一部分就是跟商品价格生成有关的,不想让人知道的隐藏参数

直接赋值 json 数据到 post 请求中,更改 price 发现商品价格没有变化,这个参数是不可控的,更改 discount,改变商品折扣发现参数可控,商品价格变为 0

后面发现在我们点击购买商品时可以抓到一个 post 请求的 api,查看发现数据中发送了一个包含 chosen_priducts 的参数,这样就更证实了chosen_discount 是一个隐藏参数

4.服务器端参数污染

当 用户输入被发送内部的 api 服务器而未严格校验时,通过操纵参数来达成:覆盖现有参数,修改应用程序行为,访问未授权数据

  • 添加#,截断后面的请求

  • 添加&,添加查询参数,可以探测隐藏参数,也可以通过第二个参数覆盖第一个参数

忘记邮箱可填入 username 参数

添加 url 编码的&符号,随便填个参数回显参数不被支持

添加正确的参数后依旧回显第一个参数的页面,

将第二个参数的值改为 administrator,第一个改为错误名称,发现页面依旧回显正确,说明服务端首先采用第二个参数,可用第二个参数覆盖第一个参数

在参数后面再添加一个截断符#,看是否存在服务器内部的参数,添加截断符后爆粗怕,显示没有 field,说明服务器后端还有一个&filed=,通过截断导致没有了 field 参数报错,

添加 field 参数后不报错说明猜想正确,的确存在 field 参数,

做着做着发现不对了,不管我 field 怎么写都不报错,也没有什么有效信息,查看题解,还是应该将&和#url 编码,开始没有编码也正确就以为不用了,还是需要编码,编码后我随便个 field 添加一个值会显示参数非法,既然这样试一下 username,username 应该是定义了的参数

当将 field 的值改为 username 后页面正确回显,显示 type:username,result:administrator,那这个 filed 应该是可以传入变量名然后拿到变量的值

做到这一步后依旧不会了,以为通过 field=email 拿到管理员的邮箱账号就可以登录了,实则不然,查看题解后发现漏了一个 js 文件,还得细心啊,js 文件中提到了一个 reset_token 的变量用来校验身份

将 field 的值改为 reset_token,成功拿到管理员的 token,直接重置管理员账号密码完成实验

5.rest url,与传统 url 不同,传统 url 使用查询语句查询资源,url 只是调用页面,如/index?id=1,而 rest url 直接用 url 表示资源,如/index/1

因为 rest url 会将用户输入输入放到 url 路径中,所以可以尝试目录遍历的参数污染

正常输入

添加./后依然显示正确信息,说明服务端可能未作过滤

使用../页面报错,说明服务端未作过滤和校验导致目录遍历

多试几次,超出 api 根目录以外目录

尝试常见的 api 文档,同时注意用#分隔可能的服务器端后面的参数,发现回显文档,显示路径:“paths”: {\n “/api/internal/v1/users/{username}/field/{field}“,说明我们的输入被放到{username},后面还跟了一个服务器端自定义的{field},这也说明之前使用#分隔符的正确性

尝试控制 field 参数成功,接下来和上面一样利用 field 参数回显 token 然后重置管理员密码

尝试输出 token 显示版本不对,观察路径尝试回退到 v1 所在路径

API漏洞
https://lab404.cn/posts/api-vulnerabilities/
作者
见山
发布于
2025-12-07
许可协议
CC BY-NC-SA 4.0