OWASP API 安全Top 10 目录:
- API1:2019-失效的对象级别授权(本篇)
- API2:2019-失效的用户身份验证
- API3:2019-过度的数据暴露
- API4:2019-资源缺乏和速率限制
- API5:2019-失效的功能级授权
- API6:2019-批量分配
- API7:2019-安全配置错误
- API8:2019-注入
- API9:2019-资产管理不当
- API10:2019-日志和监视不足
API1:2019-失效的对象级别授权
漏洞原理
这个漏洞和IDOR是类似的,就是权限有问题,用户访问了不该访问的资源,其实就是我们常说的越权。
比如修改请求中的对象ID,达到对没有授权的对象ID的访问。导致敏感数据的未授权访问,数据丢失,数据被篡改,账号被接管等问题。
这个漏洞非常的普遍,在前几年,几乎随便都能测到这种漏洞。服务器因为不会完整的跟踪用户的状态,只会通过解析对象ID来返回结果,如果不做授权就会直接返回数据。
对象级的授权主要是在代码层面上进行访问控制的一种机制,检验用户是否可以访问对象,出现这种漏洞主要是因为很多厂商都没做这一块。
例子:
当用户向API发出请求的时候,主要是为了访问对象。用户只能访问已经被授权的对象,这是正常的流程。当授权不当的时候,用户就可以访问不应该被允许的数据。
比如我们访问下面这个API,就可以访问到12345用户的消息记录
https://pxiaoer.blog/messages/12345
如果我们把12345改成12346,则变成另外一个用户。如果这样访问就可以得到消息,那就存在越权的漏洞。
还比如,在POST的请求中,有如下的JSON
{
"userId": "12345678",
"oldPassword": "My_0ld_Pa$$",
"newPassword": "$uperS3CurE"
}
我们更改userId如果没有权限验证的话,就会把用户的密码修改成功。
攻击场景
场景1:
一个电商网站的商铺接口
/shops/{shopName}/revenue_data.json
可以通过替换 shopName 来访问其他商铺的数据。
场景2:
在一个可穿戴设备流量中的HTTP头部,存在一个自定义的请求头User-Id:54796
可以通过更改User-Id后面的值来修改其他用户的账号数据
攻击手段
主要是有两种类型的对象
- 基于user ID
- 基于对象ID
基于user ID
比如像 https://google.com/get_users_search_history?userID=1234
如果能够遍历userID就可以得到其他人的数据
我们可以通过验证userid来防止遍历:
if($_GET['userID'] === object.ownerID){
ShowData()
}else{
echo "You are not allowed to view this data"
wait(5s)
Redirect(Homepage)
}
但是不要错误的以这种逻辑来验证:
if(!$_GET['userID'] === object.ownerID){
echo "You are not allowed to view this data"
wait(5s)
Redirect(Homepage)
}
ShowData()
上面的代码主要是因为可以使用回退按钮,就可以让数据显示。
基于对象ID
对象ID也是一样的,主要是需要记住对对象ID 进行权限限制
比如:
GET product.php?id=12
POST product.php?id=12
DELETE product.php?id=12
OPTIONS
上面三个接口: 得到商品信息,更新商品详情和删除商品
在后面的开发中,又想添加一个功能,把商品信息通过CSV导入,那就需要一个接口
POST /import.php? {1,"test",12}
这个时候,攻击者就可以通过修改CSV导入的内容来重写商品信息
POST updateProduct.php?productID?id=1
if($_GET['productID'].owner === object.ownerID){
UpdateData()
}else{
echo "You are not allowed to view this data"
wait(5s)
Redirect(Homepage)
}
POST /import.php?
StartUpdateData()
还有一种场景就是有跨团队调用的这种函数很容易忘记实现权限验证
比如,上面的例子中添加一个函数,每10分钟更新一次价格,这里的更新价格的函数就可以替换对象ID
TimerForProducts(){
wait(24H)
UpdatePrices($_GET[UsersProducts[])
}
UpdatePrices(products[]){
for each product in products{
getPrice()
}
}
GET /updatePrices?UsersProducts=1,2,3,4
上面的程序中,攻击者很容易就可以通过后台调用来更新价格
GET /updatePrices?UsersProducts=1,2,3,4,5,6,7,8,9,...
防御手段
- 主要是用户授权机制上,用户策略和继承关系来实现一定的授权机制。
- 在接收用户输入和访问数据库等函数中,通过授权机制来检查登录用户是否有权在该记录上执行所请求的操作。
- 多测试授权机制
- 使用auth token来代替userID来作为参数,比如JWT等
- 使用GUIDS来作为ID,GUIDS是一串很长的随机数,这样可以避免猜出其他用户的认证信息
- 使用一个认证的解决方案
- API安全网关
真实案例
1.[Razer Pay] Broken Access Control at /v1/verifyPhone/ allows enumeration of usernames and ID information
链接:https://hackerone.com/reports/752443
雷蛇的账户,允许用户枚举账户查看其他账户的用户名和手机号。
2.Private list members disclosure via GraphQL
链接:https://hackerone.com/reports/885539
3.User sensitive information disclosure
链接:https://hackerone.com/reports/975047
4.Disclose Any Store products, Files, Purchase Orders Via Email through Shopify Stocky APP
链接:https://hackerone.com/reports/763994
5.IDOR on stocky application-Low Stock-Varient-Settings-Columns
链接:https://hackerone.com/reports/853130
6.IDOR on Apple via “X-Dsid” header allows attacker to retrieve name, credit card information, addresses, and various PII of any Apple users via DSID
链接:https://twitter.com/samwcyo/status/1350025970615529473
挖掘建议
自动挖掘
自动化工具确实不太好检测这一类的漏洞,不过还是有一些人在尝试。
I. 黑盒+自动化
主要分给两个关键部分
- 流量采集
- 服务器出口日志采集
- 请求重放
- 多个账号重放请求
- 结果对比
- 排除误报
优点:在理想情况下,可以通过很少的人力去覆盖大量应用
缺点:大量的误报,安全产品死于误报;线上真实流量重放效果最好,却容易造成故障
II. 黑盒+半自动化
像ZTO的authcheck、BurpSuit插件AuthMatrix等差不多,就是手工对比。
- 流量采集
- 浏览器被动代理或爬虫方式采集
- 请求重放
- 多个账号重放请求
- 对response进行简化
- 人工确认
- 对简化后的response进行判断是否存在漏洞
优点:最后输出的漏洞结果准确度较高,适合针对单一系统进行安全测试
缺点:在面对大量应用及大量迭代新增API时,效率太低
III. 白盒+自动化
这种方式有两种思路,一种是发现存在越权风险的接口,一种是发现不存在越权风险的接口,原理是差不多的
- 白盒扫描
- 入参是否包含可越权(可遍历)的参数
- 是否有从cookie或session中或获取用户标识
- 风险确认
- 是否包含authcheck(xxid, userid)的判断逻辑
- 是否包含@authcheck的注解
优点:仿佛看到了可以批量发现越权风险的方法,对于一些简单的水平越权可以有效发现,而且一般一个系统的权限缺陷都是相似的,发现一个,发现一片
缺点:误报率太高,不能发现复杂的越权风险
IV. 白盒+半自动化
这种思路和上面提到的”黑盒+半自动化“的思路差不多
- 白盒扫描
- 扫描器应用的API list
- 标明入参及用户标识、判断逻辑
- 人工确认
- 通过白盒扫描出来的入参、用户标识、判断逻辑来判断是否存在越权风险
优点:对一部分水平越权、未授权访问的风险可以有效发现
缺点:API数量一多就不灵光了,很难发现复杂的越权
手工挖掘
手工比较好检测,主要是找到这些userID和对象ID,而且他们可能出现的位置是在URL,请求主体或者HTTP 头中。
主要是分析返回的响应结果来检查是否有漏洞存在。
手工挖掘工具
- Chrome 开发者工具
- Burp Suite
- Postman