基础概念
Web API是指用于Web服务器或Web浏览器的应用程序编程接口(API)。作为一个Web开发概念,它可以与Web应用程序的客户端(包括正在使用的任何Web框架)相关。服务器端Web API由一个或多个公开暴露的端点组成,该端点指向已定义的请求响应消息系统,通常通过基于HTTP的Web服务器以JSON或XML表示。
Web API可以粗略的分为客户端Web API和服务器端Web API两种,其中客户端API是用于扩展Web浏览器或其他HTTP客户端中的功能,而服务器端API是基于HTTP的Web服务器公开的指向已定义的请求-响应消息系统的接口,本文主要介绍的就是基于服务器端Web API漏洞挖掘手法。
什么是API漏洞
API漏洞是指API安全性中可能被恶意行为者利用的潜在弱点或漏洞。这些漏洞可能存在于API的任何部分,从设计阶段到部署阶段。它们可能会导致严重的后果,例如数据泄露、未授权访问,甚至系统崩溃。
根据OWASP统计,2023年十大API安全漏洞如下:
漏洞名称 |
---|
对象级授权被破坏(Broken Object Level Authorization) |
破损的用户身份验证(Broken User Authentication) |
破碎对象属性级授权(Broken Object Property Level Authorization) |
资源消耗不受限制(Unrestricted Resource Consumption) |
功能级别授权被破坏(Broken Function Level Authorization) |
不受限制地访问敏感业务流程(Unrestricted A***ess to Sensitive Business Flows) |
服务器端请求伪造(Server Side Request Forgery) |
安全配置错误(Security Misconfiguration) |
库存管理不当(Improper Inventory Management) |
API的不安全组合(Unsafe ***position of APIs) |
API漏洞介绍
对象级授权被破坏
对象级授权被破坏(BOLA),当API根据用户角色提供对数据的访问权限,但无法验证用户是否有权访问这些数据时,就会产生漏洞。通过此漏洞,攻击者可以绕过授权访问敏感数据甚至执行未经授权的操作。
示例
BOLA漏洞如何发现呢,一般情况下我们可以从网站的某些查询功能入手。例如在某个网站的个人中心中,用户想查看自己的个人资料,那么就会向服务器API发送一个查询资料的请求。
POST example.***/api/v2/customer/profile HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"id":"1041864"}
服务器API处理请求后发送数据给客户端。
HTTP/1.1 200
Server: openresty/1.17.8.2
Date: Mon, 22 Jan 2024 10:25:30 GMT
Content-Type: application/json
Connection: keep-alive
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
{
'id': 1041864,
'name': 'zhangsan',
'email': 'zhangsan@test.***',
'phone_number': 13800000000,
'card_on_file': false,
'credit_card': null,
'loyalty_points': 0,
}
接着攻击者复制该请求并将数据包中的id修改为1041800,发送给服务器并成功获取了其他人的个人信息。
HTTP/1.1 200
Server: openresty/1.17.8.2
Date: Mon, 22 Jan 2024 10:26:30 GMT
Content-Type: application/json
Connection: keep-alive
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
{
'id': 1041800,
'name': 'lisi',
'email': 'lisi@test.***',
'phone_number': 13800000123,
'card_on_file': false,
'credit_card': null,
'loyalty_points': 0,
}
通过这个漏洞,攻击者可以通过重复调用/api/v2/customer/profile这个API并在每个请求中包含不同的ID来查询用户的敏感信息。
破损的用户身份验证
破损的用户身份验证是指应用程序中存在缺陷或错误的用户身份验证机制,导致攻击者能够绕过身份验证,获得未经授权的访问权。
以下是一些可能导致该漏洞的问题:
-
密码复杂性较弱
-
密码历史记录短或丢失
-
账户锁定阈值过高或缺失
-
无法在基于证书的身份验证中为每个设备提供唯一的证书
-
密码和证书轮换的持续时间过长
-
身份验证材料在url和GET请求中公开
-
熵不足的身份验证令牌
-
使用API密钥作为唯一的身份验证材料
-
未能验证认证材料的真实性
-
JSON Web令牌(JWT)配置不安全,例如使用弱数字签名算法或丢失签名
-
在加密或散列算法中使用短密钥
-
使用不适合用例的算法,例如使用哈希算法而不是基于密码的密钥派生函数(PBKDF)
示例1:找回密码
破损的用户身份验证通常出现在各种需要身份认证的场景下,例如找回密码功能。用户正常操作向服务器发送找回密码请求。
POST api/v2/reset-password HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"userID":"123"}
服务器接收到请求后,触发密码重置功能,并向用户邮箱发送验证码以验证身份。由于API没有速率限制,攻击者可以尝试爆破所有4位数字,进行暴力破解。
POST api/v2/reset-password HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"userID":"123","msg":"0000","newPass":"test123"}
然后,攻击者可以猜测该验证码并为用户重置密码。
示例2:JWT接受"None"算法
JWT令牌指Json Web令牌,其中常常包括用户信息,其优点在于我们始终可以轻松解码这些令牌并查看信息,如果想要修改数据,就必须使用算法进行签名。
JWT应该始终使用正确的算法验证令牌,大多数JWT框架默认启用None算法,这将导致我们无需加密即可修改系统内的数据。
这是一个JWT的示例
{
"alg": "HS256",
"typ": "JWT"
}
{
"id": "567",
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
可以看到这个令牌使用HS256加密,如果我们想编辑这个令牌,就必须知道HS256密钥。但如果验证机制接受None算法,我们就可以随意JWT内容而不用验证签名。
{
"alg": "None",
"typ": "JWT"
}
{
"id": "567",
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
破损对象属性级别授权
破损对象属性级别授权是指并非每个用户都有权访问对象的所有属性,即使他们被授权访问该对象的某些属性也是如此。当授权未在足够细粒度的级别执行时,就会出现破损对象属性级别授权漏洞。攻击者可以利用漏洞恶意访问或更改属性。
示例
假设应用程序有一个用户,他拥有first_name、last_name、email_name、is_admin之类的属性。他有编辑前三个属性的权限。换句话说,他可以修改自己的姓名和邮箱信息,而最后一个属性须有权限更高的人去修改。正常用户在修改信息时,UI根本不会显示最后一个属性,所以无法自己更改它,但API实际上并不验证编辑is_admin属性的权限。
正常用户提交修改信息的表单如下:
POST api/v2/user/update-info HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"userID":"123","first_name":"zhang","last_name":"san","email_name":"123@test.***"}
攻击者向请求中添加is_admin属性并赋值为true,也就是调用API给用户123赋予管理员权限。
POST api/v2/user/update-info HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"userID":"123","first_name":"zhang","last_name":"san","email_name":"123@test.***","is_admin":True}
如果成功,攻击者就可以以管理员身份在应用程序中执行操作。
不受限制的资源消耗
不受限制的资源消耗可以分为两种情况:
-
由于缺少资源限制,攻击者可以构造大量或单个的API请求,从而使应用程序不堪重负,从而影响应用程序的性能和响应能力,或者导致其变得无响应,也就是DoS攻击。
-
由于缺乏速率限制,攻击者可以构造大量的API请求来淹没系统资源、暴力破解登录凭据、窃取大量数据。
示例1
假设网站存在关键字查询功能,用户在使用API时,系统规定了每页最大返回数量和最大返回数据量page_size和max_return。
POST api/v2/search HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"key_word":"test","max_return":"100","page_size":"10"}
攻击者通过修改max_return和page_size的值至20000。
POST api/v2/search HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"key_word":"test","max_return":"20000","page_size":"20000"}
这种修改将导致应用程序返回过多的数据来响应查询,进而导致应用程序速度减慢或对所有用户无响应。
示例2
假设某网站登录处存在忘记密码功能,用户使用此功能会向手机发送验证码,以便重置密码。
首先API调用会从用户浏览器发送到后端API
POST api/v2/user/forgetpwd HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Cookie:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlZEBleGFtcGxlLmNvbSIsImlhdCI6MTY1ODQ2MDMzMCwiZXhwIjoxNjU4NTQ2NzMwfQ.m0ha0L89xuLpLlLlybcaD2SfKp23BZfe_Hjjs- Ppr***2sDvxpmWAcemN5yOq-nhx78Iu8EzLIJbqqc1d-q10UA
Connection: keep-alive
{"username":"test","step":1}
后端API向第三方API发送短信业务请求
POST /sms/send_code HTTP/1.1
Host: smssender.***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
A***ept: */*
A***ept-Language: en-US,en;q=0.5
Content-Type: application/json
Connection: keep-alive
{"phone":"13800000000"}
第三方收到请求后,会向用户手机号码发送验证码短信。在这个流程中,攻击者可以复刻这个API请求并重复大量发送给后端,导致用户受到短信轰炸攻击。
功能级别授权被破坏
功能级别授权被破坏(BFLA)与对象级授权被破坏(BOLA)很相似,都是由于授权实施不当或配置错误造成的。而功能级别授权被破坏(BFLA)可以被视为对象级授权被破坏(BOLA)的更高级别版本,在利用BFLA漏洞时,攻击者关注的是通用API函数而不是单个API对象。BFLA的结果是客户端可以访问超出其预期访问级别的功能。
示例
假设在某网站存在查看用户的功能,普通用户只能查看用户信息,而管理员用户可以对用户信息进行增删改查。
正常用户上传时数据包如下:
POST api/v2/user/search HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
A***ept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
A***ept-Encoding: gzip, deflate
A***ept-Language: zh-***,zh;q=0.9
Cookie: JSESSIONID=2261EE46F2BABC4606D6B62DBB4B55
{"userID":"123","max_return":"250","page_size":"250"}
当攻击者以普通用户身份将POST方法改为DELETE方法时,普通用户即拥有了删除用户信息的权限
DELETE api/v2/user/search HTTP/1.1
Host: example.***
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
A***ept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
A***ept-Encoding: gzip, deflate
A***ept-Language: zh-***,zh;q=0.9
Cookie: JSESSIONID=2261EE46F2BABC4606D6B62DBB4B55
{"userID":"123","max_return":"250","page_size":"250"}