STATEMENT
声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
前言
近日看到国外一篇挺不错的关于API的攻击文章,故消化吸收了一下,站在小白的角度结合一下案例来尝试下关于apis的攻击思路。算是拓展一下攻击面,顺便补缺补漏下吧。本文主要从API的十个风险点来展开叙说,当然不是只有这10处,像常见的注入就不在这叙说,展开能说好多。
10年前,网络应用倾向于遵循一种模式,即大部分的应用在呈现给用户之前都是在服务器端生成的。任何需要的数据都是由生成用户界面的同一服务器直接从数据库中收集的。它可能看起来像这样。
许多现代网络应用倾向于遵循一种不同的模式,通常被称为SPA(单页应用)。在这种模式下,通常有一个API后端,一个JavaScript用户界面和数据库。API只是作为网络应用程序和数据库之间的一个接口。所有对API的请求都是直接从网络浏览器发出的。
为API测试进行设置
Postman是一个方便的应用程序,使API安全测试变得轻而易举。你可以从其官方网站下载Postman。从本质上讲,Postman只是另一个HTTP客户端,可以用来轻松修改和发送对API的请求。如果你有一个文件中的API请求集合,你可以通过点击应用程序左上角的导入按钮,开始将它们导入Postman。
导入集合后,你会看到在Postman中加载的API调用,像这样。
通过点击单个的API调用,完整的API请求将在右边被看到。此外,请求的不同部分将被分成若干部分,如参数、授权、头信息、请求正文等。这样方便于我们研究每个部分。
可以与BurpSuite相同的方式修改请求头和正文。来分析测试案例的响应
Postman中的响应视图是这样的,响应也被分成不同的部分,如Body、Cookies、Headers等,所以你可以仔细分析每个部分。
API漏洞类型
API有很多类型和大小,攻击API的方法也因这些类型和大小而大不相同。所以这里就介绍其中的一些类型。
1、API暴露面
内部使用的API可能会意外地暴露在互联网上,这可能是由于错误的配置,或者只是因为假设没有人能够找到它。API的位置可以通过很多方式发现,包括分析JavaScript文件、分析暴露的源代码、观察主机名(如api.internal.example.com)和Google dorking。
这里包括之前我分享的一些案例,例如之前的JS泄露OSS的accessKeyId、accessKeySecret
以及常见的JS接口未授权访问等、除此以外,在外部主机上发现像SSRF这样的漏洞,可能会让你获取到内部的API。
2、配置缓存风险
对于需要认证的API来说,返回的数据往往是动态的,并且是针对每个API密钥的范围。例如,以A的身份访问/api/v1/userdetails 应该返回A的详细信息,而以B的身份访问同一终点应该返回B的详细信息。一个常见的错误配置发生在API不使用标准的Authorization 头,而是使用一个自定义的头,如X-API-Key 。缓存服务器可能无法识别这是一个经过验证的请求,并可能将其缓存。
如果是这种情况,并且没有Cache-Control 或Pragma 头信息,那么简单地访问/api/v1/userdetails 可能会暴露另一个用户的信息。
3、暴露的Token
通过任何方式发现一个API密钥,都可能为你提供对API的访问。更糟糕的是,供内部使用的API往往没有必要实施复杂的认证流程,因此可能会实施静态令牌作为其认证。秘密令牌可能在代码库、客户端JavaScript、拦截流量等方面被发现。
例如一次在红队演练中内网横向时获取到的一个GF配置接口信息。里面暴露了接口的认证key与对应的接口信息,包括可以查看婚姻及伴侣等信息。
4、授权风险/IDOR
授权是检查一个经过认证的用户是否可以访问一个特定的用户的过程。一个常见的与授权有关的漏洞被称为不安全的直接对象引用(IDOR)。例如,在一个开票应用程序的API中,我们可能有一个端点,用来获取发票的详细信息参数是应该返回的发票的标识符。如果这个端点是安全的,我应该只能得到属于我的发票的细节。例如,如果我创建了一张ID为1234的发票,那么它应该返回详细信息。如果我试图通过浏览/api/v1/invoices/?id=1233 来访问一张我没有创建的发票,它应该返回一个错误。如果我能够改变标识符来查看其他用户的发票细节,这就是一个被称为IDOR的漏洞。也就是所谓的越权。为了应对IDOR问题,今天许多API都利用UUID作为对象的标识符。一个UUID看起来像这样。f1af4910-e82f-11eb-beb2-0242ac130002,这也是大多数金融行业的修复处理方式。值得注意的是,利用UUID作为标识符并不是缓解IDOR问题的有效方法。事实上,UUID RFC特别指出了这一点。虽然利用UUIDs而不是整数作为对象的ID是很好的做法,但它们绝不应该被用作防止IDOR攻击的唯一保护措施。特别是可预测的随机数反而可能会导致情况更加严峻。就例如结合前端的敏感信息泄露,有的单位会将其生成算法暴露在前端,并且后端并未有效的进行前后端认证,导致可自行枚举进行攻击。
5、未记录的端点
经常会遇到这样的情况:尝试渗透攻击的API没有文档(或者至少没有你可以访问的文档)。同样常见的是,一个有文档的API会有超出文档内容的端点。有时,这些端点的存在可能是一个安全问题--例如,端点可能是为管理目的而设计的,并允许你作为一个低权限用户执行管理任务。其他时候,这些端点可能会出现漏洞,只是因为它们没有像那些容易发现的端点那样被测试。
这里我们可以通过用Burp来检测,例如通过查看目标选项卡检查所使用的端点。许多API会给出足够详细的错误,以列举未记录的端点和参数。例如,向/api/v1/randomstring 发送一个空白的POST请求,可能会导致一个错误,大意是无效路由,有效路由是[/users,/invoices,/customers] 。
如果你知道一个与API互动的应用程序,你可以分析该应用程序的JavaScript,以收集可能被访问的API端点的列表。这里建议使用API字典来进行模糊测试。通过遍历的方式来发现表面不易发现的接口。虽然这块在下面的解决方法中建议采用类似于swagger这种比较成熟的API功能,但是配置不当也有可能导致对应的接口披露。例如说:
这种就是直接披露了应用环境的接口信息。
6、版本差异风险
当一个组织发布一个API时,它可能与许多不同的应用程序对接。如果API在任何时候被更新,它可能会对这些应用程序中的一个或多个引入破坏性的变化。出于这个原因,多个API版本经常被实施,作为支持旧的API模式的一种手段,同时也为新的用户逐步升级API。
测试所有版本的API是值得的。旧版本可能仍有安全问题,这些问题后来在新版本中得到了修复,而较新的/边界/测试版可能引入了新的安全问题。
api版本管理的一个常见模式是:
/api/v1/
/api/v2/
/api/beta/
以及未投产时的生产环境入口:
qa
devenv
devenv1
devenv2
preprod
pre-prod
test
testing
staging
stage
dev
development
deploy
slave
master
review
prod
uat
prep
Version2
......
7、无速率限制导致批量请求攻击
大多数时候,API对用户的请求次数没有任何保护。这被称为 "缺乏速率限制",当攻击者可以调用API数千次以导致一些非预期的行为时,就会发生这种情况。服务器将试图满足这些请求中的每一个,这有可能通过对服务器进行超负荷的请求,使其处于DOS状态 允许攻击者快速渗出敏感的用户信息,如:用户ID、用户名、电子邮件等。即枚举。通过强制执行一个向受害者发送电子邮件/短信的功能,淹没受害者的收件箱。即短信dos攻击、邮箱dos攻击。
例如说看一个攻击场景,在一个检查证书的API端点上没有速率限制。GET /api/v1/user/1234/login/?password=password
通常情况下,你不会看到在这样的GET请求中发送密码,但为了本演示的目的,假设你看到了。为了对上述端点中的密码进行暴力攻击,攻击者可以使用BurpSuite’s Intruder )工具。这个工具允许我们定制不同种类的暴力攻击,但在这个例子中,我们将给它提供一个简单的密码列表。
在几秒钟的时间里,入侵者将发出数百个API请求,在每个请求中尝试使用不同的密码。
GET /api/v1/user/1234/login/?password=falsepassword1
GET /api/v1/user/1234/login/?password=falsepassword2
GET /api/v1/user/1234/login/?password=falsepassword3
. . .
GET /api/v1/user/1234/login/?password=correctpassword!
为了防止速率限制的错误,应用程序应该对用户在一定时间范围内请求API的频率进行限制。设置的确切限制将取决于该API或端点的使用情况。
8、接口竞争条件攻击
竞争条件是指两个或更多的请求在同一毫秒内被发送到一个API。当一个API没有处理这种情况的机制时,会导致API以非预期的方式处理这些请求。
一个潜在的竞赛条件的攻击场景可能是在一个有漏洞的电子商务应用程序上兑换折扣或促销代码时出现。
POST /api/v1/discount
Target: www.angus.com
Connection: close
{
"code","200",
"amount":"10"
BurpSuite有一个名为Turbo Intruder的扩展,允许用户使用内置的race.py 脚本来测试竞争条件。//该工具非常实用测并发,其并发包速率最快可达到每秒2W个。
在Turbo Intruder中配置好攻击后,攻击者可以向API发送多个并发请求,以换取这个优惠代码。
POST /api/v1/discount 200 OK
POST /api/v1/discount 200 OK
POST /api/v1/discount 200 OK
POST /api/v1/discount 404 Not Found
POST /api/v1/discount 404 Not Found
如果API在收到第一个并发请求后没有立即使促销代码失效,那么折扣金额可能会增加一倍、两倍。
包括像有的短信炸弹无法正常批量获取的时候也可利用竞争条件绕过批量获取。尽管有图形验证码限制,但依旧可绕过。
竞争条件攻击是攻击者发送修改资源的请求的速度与应用程序更新该特定资源的速度之间的竞赛。
9、XML注入
XXE代表XML外部实体,这种注入漏洞可以在任何使用API处理XML数据的地方测试。SOAP APIs也可能受到XXE注入的攻击,因为它们是基于XML的。
一个使用XML的API端点看起来是这样的。
XXE注入是指当攻击者注入指定DTD之外的自定义外部实体。一旦这些外部实体被API解析,它可以让攻击者访问应用程序的内部文件,升级到SSRF,将敏感数据泄露给攻击者控制的域或DOS服务器。
这是一个请求的例子,攻击者注入了一个名为xxe的外部自定义实体,这个实体的目的是为了检索一个内部文件。
POST /soap/v2/user HTTP/1.1
Host: angus.com
Content-Type: text/xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE ah [<!ENTITY xxe
SYSTEM "file:///etc/passwd">]>
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<getUser>
<id>&xxe injection;</id>
</getUser>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
如果API允许使用标准的XML解析器来处理数据,那么这个注入的外部实体将被应用程序处理并将/etc/passwd的内容返回给攻击者。例如说XML的用户名枚举。
10、Content类型转换
即使API可能使用JSON作为数据格式进行通信,底层服务器/框架仍然可能接受其他数据格式,如XML。因此,当看到一个API的content-Type 为application/json 时,仍然可以通过将其值切换为Content-Type: text/xml 来尝试测试XXE。
例如,如果一个API使用JSON
POST /api/v1/user HTTP/1.1
Host: angus.com
Content-Type: application/json
它可以被修改为以这种方式发送XML数据。
POST /soap/v2/user HTTP/1.1
Host: angus.com
Content-Type: text/xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE ah [<!ENTITY xxe
SYSTEM "file:///etc/passwd">]>
还有的就是我们常见的各类注入攻击,包括sql注入、命令注入等,就不在叙述了。
小结
1、(API 暴露面):实施严格的部署实践,通过IAM和网络分段强制执行最小权限原则。
2、(配置缓存风险):解决认证引发的API问题的方法是实现Cache-Control 或Pragma 头并利用标准的Authorization头。
3、(暴露的Token):通常可以在API密钥被部署到不应该部署的地方之前抓到它们。一些代码库供应商(包括GitHub)也有能力在推送前检测API密钥。其实也就是所谓的自查自检,这块个人觉得HAE就是很不错的工具推荐
4、(授权):授权问题通常很难以自动化的方式检测。代码库的结构应该被设置成很难在特定的端点上出现授权错误。为了实现这一点,授权措施应该尽可能地在堆栈中实施。有可能是在类的层面,或者使用中间件。
5、(未记录的端点):拥有一个强大的、结构化的方法和流程来记录API的功能,可以在以后的道路上节省很多麻烦。Swagger正是这方面的一个优秀标准。此外,最好是在编码之前用文档来规划API的功能,而不是反过来。
6、(版本差异风险):可以用定义的生命周期来支持API版本。例如,当你发布版本2的API时,你可以通知你的用户,版本1将达到生命终结(EoL),并在未来的一个特定日期被废弃。预生产/测试版本只有在经过彻底的安全问题测试后才可以公开访问。
7、(无速率限制导致批量请求攻击):速率限制可以通过许多不同的方式实现。每个账户、每个IP地址、每个端点、整个API等等。一些反向代理也可以用来实现整个应用程序的节流,而无需额外的开发。你使用的具体实现方式将取决于你的具体应用的要求。
8、(接口竞争条件攻击):缓解竞赛条件问题往往意味着牺牲性能。缓解竞赛条件的方法包括利用锁和其他线程安全功能。大多数编程语言都有内置的线程安全功能,但通常需要手动设置。
9、(XML注入):确保正在利用的XML解析器被设置为不解析XML实体。
10、(Content类型转换):这个错误实际上只存在于那些被设计为接受多种格式的框架上,其中每种格式对应一种类型的对象。在这些情况下,框架通常会有一个选项,将可用格式列入白名单
对于API的渗透,我们不单单像常规漏洞研究那样,包括目标采用的API服务、版本、泄露、披露等,包括其传输的方法、类型,总之在HTTP中的关联参数都是我们需要涉及的内容,包括其引用的第三方资源,例如说js等。
*特别说明:本文部分截图源于互联网案例
安恒信息
✦
杭州亚运会网络安全服务官方合作伙伴
成都大运会网络信息安全类官方赞助商
武汉军运会、北京一带一路峰会
青岛上合峰会、上海进博会
厦门金砖峰会、G20杭州峰会
支撑单位北京奥运会等近百场国家级
重大活动网络安保支撑单位
END
长按识别二维码关注我们