本文记录完成crAPI挑战的过程以及收获。
crAPI GitHub:OWASP/crAPI: completely ridiculous API (crAPI) (github.com)
个人理解接口安全是确保应用程序中的 API 在设计、实现和使用过程中,能够防止恶意攻击并保护敏感数据不被未经授权的访问。接口安全涵盖多个方面,主要目标是保护 API的机密性、完整性和可用性,同时防止应用程序受到各种安全漏洞和攻击。接口安全需要考虑以下几个方面:
在 crAPI 靶场中,有许多接口在存在安全漏洞,缺少验证、缺少敏感信息保护等等。我们通过 crAPI 靶场可以更加直观地了解到不安全的接口可以造成的恶劣后果。
靶场的搭建过程略,本人使用docker进行搭建,期间需要使用VPN。
靶场的所有挑战:crAPI/docs/challenges.md at develop · OWASP/crAPI (github.com)
打开浏览器的开发者窗口的网页栏,获取浏览器和服务器通讯的数据包,发现在点击靶场的community后,服务器的接口/community/api/v2/community/posts/recent会返回给我们用户的敏感信息:email、vehicleid等。
通过分析dashboard页面中的location功能,发现可以通过此接口:/identity/api/v2/vehicle/{vehicleid} /location,可以在没有车辆所有者的允许下查看车辆的位置信息。
通过对Contact Mechanic功能进行抓包分析得到一个接口:workshop/api/merchant/contact_mechanic,通过传入report_id即可访问其他用户的报告。
先进入forget password页面,再向邮箱发送了验证码后,点击Set Password按钮前开始抓包,获得发送重置密码请求的数据包,其中有三个输入元素:验证码、邮箱、新密码。
需要正确的验证码才能成功重置密码,由于验证码只有4位,最多仅有10000种可能,可以通过爆破的方法得到正确的验证码。
但仍然需要考虑网站的安全机制,多次使用验证码验证失败后可能会导致该账号被禁止登录或者更改密码操作。通过几次尝试后该项目更改密码存在两个接口。/community/api/v3/community/posts/recent;这个接口是网站重置密码默认使用的接口,对此接口在检测到多次失败后就会提示ERROR,无法对其进行爆破。
但是还有一个接口:/community/api/v2/community/posts/recent(将v3改为v2),此接口安全性较低,没有对错误进行反馈,可以对其爆破。
可以使用burpsuite工具的intruder模块和密码本开始爆破,我们以挑战一获得的用户email为例:
效果如上,验证码为0135时,修改密码成功。
这个问题出现的原因,一是验证码的长度太短,容易被爆破,另外就是仍然存在可用的不安全接口,在检查代码的时候应该将其禁用。
在挑战1中,我们已经找到返回用户车辆信息和车辆定位信息的接口,这些接口返回了过多的数据,不应该返回给用户过多的敏感数据,容易导致数据泄露。
对个人主页的视频改名功能抓包分析,可以而得到此接口:/identity/api/v2/user/videos/{video_id}
发现返回了视频的id,name,conversion_params,profileVideo等内容。
通过抓取发送维修信息的数据包可以发现其中有一个值为number_of_repeats,
假设此值为极大值,那么就会重复发起很多次请求,占用服务器资源,实现拒绝服务(DoS)攻击。
通过将repeat_request_if_failed改为ture并将number_of_repeats改为极大,这样既可实现crAPI靶场的DoS攻击。
在挑战5中,发现使用GET方法对接口:/identity/api/v2/user/videos/{video_id}请求可以获得视频的详细信息。
我们可以使用OPTINOS方法对此接口请求,了解此接口开放了哪些方法。
可以发现,Allow中有DELETE方法,我们可以将请求的方法改为DELETE,但是会失败,通过将user改为admin,访问/identity/api/v2/admin/videos/{video_id}即可以成功删除视频。
抓取下订单后的数据包进行分析可得,提交订单使用的是POST方法,发送request请求后发现服务器返回了当前订单的id信息。
我们尝试改用GET方法,并在接口后附上订单ID,发现服务器会返回订单的详细信息。
此时我们注意到订单信息中有一个status,我们可以通过PUT方法在data部分将status改为returned,即将订单改为已退还状态,此时金额会被退回,即完成了免费获得一件物品的效果(用户手动通过API将订单状态改为returned,但实际并没有return,这样可以将钱退回至用户账号,但是用户手上的商品并没有退还)。
在上一个挑战中,使用PUT方法修改订单状态的时候,我们注意到订单中还有一个属性为quantity,可以在修改订单状态的时候同时将quantity修改为极大,这样系统就会退还quantity*订单金额的钱。
效果如下:
对个人主页下的修改视频名字的功能进行抓包分析,得到接口/identity/api/v2/user/videos/{videoid},使用PUT方法对其发起请求即可修改视频属性。
对上传修理信息抓包分析后,发现对/workshop/api/merchant/contact_mechanic接口的request中包含mechanic_api,通过将其改为baidu.com即可完成此挑战。
通过兑换优惠券的功能进行抓包分析可以得到crAPI的一个接口:/community/api/v2/coupon/validate-coupon,发现可以利用类似sql注入的方式修改请求中的coupon_code。
挑战13的题目不是很懂…
申请优惠券的API为/workshop/api/shop/apply_coupon(crAPI的所有API可以在github文档中找到)
或许是使用 1' or '1' = '1
注入?
在之前的挑战中发现有两个接口,不需要身份验证即可返回信息。
机械功报告查看接口:/workshop/api/mechanic/mechanic_1 report?report_id=7
订单信息查看接口:/workshop/api/shop/orders/1
JWT是JSON Web Token的缩写,是一种用于在网络应用间传输信息的开放标准(RFC 7519)。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。JWT通常用于身份验证和授权机制。
头部(Header):头部通常由两部分组成,标识令牌类型和所使用的签名算法。
载荷(Payload):载荷包含要传输的数据。它可以包含预定义的标准声明(例如,发行人(issuer)、主题(subject)、过期时间(expiration time)等),以及自定义的声明。
签名(Signature):签名用于验证令牌的真实性和完整性。它由使用头部中指定的签名算法和密钥对头部、载荷进行加密生成。签名防止了令牌被篡改。
JWT的工作流程如下:
通常,JWT令牌在HTTP请求的授权头部(Authorization Header)中发送。具体来说,令牌通常放置在授权头部的Bearer字段后面。
在本靶场中,可以通过伪造Authorization实现假冒其他用户身份的效果。
crAPI项目的dashboard页面,即/identity/api/v2/user/dashboard并没有对JWT的第三部分进行验证,故我们可以直接改变Payload中的 sub,改为其他用户的邮箱再重新提交请求即可得到其他用户的dashboard信息。
还可以使用混淆攻击。分析原本的JWT可以得到用于加密header和payload的算法是RSA,非对称算法。服务器使用私钥对header和payload加密,作为sign负载后部,客户端可以使用服务器的公钥来验证真实性。
混淆攻击,即将header中的alg从RS256改为HS256,将非对称密码算法改为对称密码算法,此时再获取服务器的公钥,用公钥和HS256对header和payload签名,将此JWT发送至服务器。
服务器发现header部分的alg为HS256,则会将RS256的公钥视为HS256的密钥,签名就会验证成功。这样攻击者就可以自己伪造JWT,模拟任意用户的身份登录。
除了算法混淆漏洞外,还有jku滥用漏洞。”jku”是JWT header中的一个可选字段,用于指定用于验证签名的JWK Set的URL。JWK Set是包含公钥或公钥集合的JSON对象,用于验证JWT的签名。通过在JWT标头中包含”jku”字段,可以指定用于获取JWK Set的URL。验证方可以使用该URL来获取公钥并验证JWT的签名。
crAPI 将使用 JWT 标头指向的任何公钥验证 JWTjku令牌,我们使用自己创建的公钥/私钥对并使用 RS256 算法签署 JWT,以 JWK 格式将公钥托管在某处,使用适当的标头在jku标头中传递公钥 URL,该 JWT 将被 crAPI 接受为有效的 JWT 令牌。本质是让服务器使用我们创建的另外一对密钥进行验证签名,而这一对密钥是我们自己创建的,所以我们也可以任意伪造签名,模拟任意用户的身份登录。
windows上的burpsuite的jwt板块有bug,建议使用另一个网站辅助:https://jwt.io/
但是我后面伪造签名的实验试了很多次都失败了,目前还不知道原因。后面会针对JWT进行进一步的练习。
通过对shop页面抓包分析,我们可以得到此接口/workshop/api/shop/products,使用GET方法请求可以得到商品信息。
发现可以构造一个商品,并通过POST方法成功上传。
商品的金额和订单的数量应该都为正数,但是在crAPI靶场中,我们可以通过PUT方法将其改为负数,并且还可以正常运行。导致出现了购买商品还增加余额的现象。