API
侦察
首先,您应该确定 API 端点。这些是 API 接收有关其服务器上特定资源的请求的位置。例如,考虑以下GET
请求:
GET /api/books HTTP/1.1
Host: example.com
此请求的 API
端点是/api/books
。这将导致与 API
的交互以从图书馆检索书籍列表。另一个 API
端点可能是,例如, /api/books/mystery
它将检索神秘书籍列表。
确定端点后,您需要确定如何与它们交互。这使您能够构建有效的 HTTP
请求来测试 API
。例如,您应该找出有关以下内容的信息:
-
API
处理的==输入数据==,包括强制参数和可选参数。 -
API
接受的==请求类型==,包括支持的 HTTP 方法和媒体格式。 -
==速率限制和身份验证机制==。
API
文档
API
通常会有文档记录,以便开发人员知道如何使用和集成它们。
文档既可以采用人可读的形式,也可以采用机器可读的形式。人可读文档旨在帮助开发人员了解如何使用 API
。它可能包括详细的说明、示例和使用场景。机器可读文档旨在由软件处理,以自动执行 API
集成和验证等任务。它以 JSON
或 XML
等结构化格式编写。
API
文档通常是公开的,特别是当 API
旨在供外部开发人员使用时。如果是这种情况,请始终通过查看文档来开始侦察。
发现 API
文档
即使 API
文档未公开,您仍然可以通过浏览使用该 API
的应用程序来访问它。
为此,您可以使用 Burp Scanner
来抓取 API
。您也可以使用 Burp
的浏览器手动浏览应用程序。查找可能引用 API
文档的端点,例如:
-
/api
-
/swagger/index.html
-
/openapi.json
如果您确定了资源的端点,请务必调查基本路径。例如,如果您确定了资源端点 /api/swagger/v1/users/123
,则应调查以下路径:
-
/api/swagger/v1
-
/api/swagger
-
/api
您还可以使用常用路径列表来使用 Intruder
查找文档。
1、实验室:使用文档利用 API
端点
要解决该实验,请找到公开的 API
文档并删除carlos
。您可以使用以下凭据登录到您自己的帐户:wiener:peter
。
没什么明显的提示,测试路径/api
-> 发现有三个接口 -> 直接通过Delete /user[username: String]
接口即可
使用机器可读的文档
您可以使用一系列自动化工具来分析您找到的任何机器可读的 API
文档。
您可以使用 Burp Scanner
抓取和审核 OpenAPI
文档或任何其他 JSON
或 YAML
格式的文档。您还可以使用 OpenAPI Parser BApp
解析 OpenAPI
文档。
您还可以使用专门的工具来测试记录的端点,例如 Postman
或 SoapUI
。
识别API
端点
您还可以通过浏览使用 API
的应用程序来收集大量信息。即使您可以访问 API
文档,这也常常是值得的,因为有时文档可能不准确或过时。 ---- 即使有API
文档,也可以手动测试一下API
的各个功能点
您可以使用 Burp Scanner
来抓取应用程序,然后使用 Burp
的浏览器手动调查有趣的攻击面。
浏览应用程序时,请查找 URL
结构中暗示 API
端点的模式,例如/api/
。还要注意 JavaScript
文件。这些文件可能包含对您未通过 Web
浏览器直接触发的 API
端点的引用。Burp Scanner
会在抓取过程中自动提取一些端点,但对于更重的提取,请使用 JS Link Finder BApp
。您还可以在 Burp
中手动查看 JavaScript
文件。
与 API
端点交互
确定 API
端点后,使用 Burp Repeater
和 Burp Intruder
与它们交互。这使您能够观察 API
的行为并发现其他攻击面。例如,您可以调查 API
如何响应更改 HTTP 方法和媒体类型。
与 API
端点交互时,请仔细检查错误消息和其他响应。有时,这些响应中包含可用于构建有效 HTTP
请求的信息。
识别支持的 HTTP
方法
HTTP
方法指定要对资源执行的操作。例如:
-
GET
- 从资源中检索数据。 -
PATCH
- 对资源应用部分更改。 -
OPTIONS
- 检索可在资源上使用的请求方法类型的信息。
API
端点可能支持不同的 HTTP
方法。因此,在调查 API
端点时,测试所有潜在方法非常重要。这可能使您能够识别其他端点功能,从而打开更多的攻击面。
例如,端点/api/tasks
可能支持以下方法:
-
GET /api/tasks
- 检索任务列表。 -
POST /api/tasks
- 创建新任务。 -
DELETE /api/tasks/1
- 删除任务。
您可以使用 Burp Intruder
中内置的HTTP 动词列表自动循环执行一系列方法。
识别支持的内容类型
API
端点通常需要==特定格式的数据==。因此,它们的行为可能会根据请求中提供的数据的内容类型而有所不同。==更改内容类型可能使您能够==:
-
触发错误以泄露有用信息。 -
绕过有缺陷的防御。 -
利用处理逻辑的差异。例如, API
在处理JSON
数据时可能是安全的,但在处理XML
时容易受到注入攻击。
要更改内容类型,请修改Content-Type
标头,然后相应地重新格式化请求正文。您可以使用内容类型转换器 BApp
自动在 XML
和 JSON
之间转换请求中提交的数据。
2、实验室:查找并利用未使用的 API
端点
为了解决实验室问题,利用隐藏的 API
端点购买轻质 l33t
皮夹克。您可以使用以下凭据登录自己的帐户: wiener:peter
。
点击商品的时候进行抓包,会有一个api
请求来获取该商品的价格api/product/1/price
,通过OPTIONS
的方法,查看该接口允许什么HTTP
方法 -> GET PATCH
,PATCH
对局部数据进行更新
修改以下三处地方即可
PATCH
Content-Type: application/json
{"price":0}
使用入侵者查找隐藏端点
一旦确定了一些初始 API
端点,您就可以使用 Intruder
来发现隐藏的端点。例如,考虑这样一个场景:您已经确定了以下用于更新用户信息的 API
端点:
PUT /api/user/update
为了识别隐藏的端点,您可以使用 Burp Intruder
查找具有相同结构的其他资源。例如,您可以将有效负载添加到/update
路径的位置,其中包含其他常用函数列表,例如 delete
和add
。
查找隐藏端点时,请使用基于常见 API
命名约定和行业术语的词汇表。根据初步侦察,请确保还包括与应用程序相关的术语。
寻找隐藏的参数
在进行 API
侦察时,您可能会发现 API
支持的未记录参数。您可以尝试使用这些参数来更改应用程序的行为。Burp
包含许多可以帮助您识别隐藏参数的工具:
-
Burp Intruder
可让您自动发现隐藏参数,使用常用参数名称的单词表来替换现有参数或添加新参数。确保您还根据初步侦察结果包含与应用程序相关的名称。 -
Param miner BApp
可让您针对每个请求自动猜测最多 65,536 个参数名称。Param miner
会根据从范围中获取的信息自动猜测与应用程序相关的名称。 -
内容发现工具使您能够发现未链接到可浏览的可见内容的内容,包括参数。
批量分配漏洞
批量分配(也称为自动绑定)可能会==无意中创建隐藏参数==。当软件框架==自动将请求参数绑定到内部对象的字段==时,就会发生这种情况。因此,批量分配可能会导致应用程序支持开发人员从未打算处理的参数。
识别隐藏参数
由于批量分配从对象字段创建参数,因此您通常可以通过手动检查 API
返回的对象来识别这些隐藏参数。
例如,考虑一个PATCH /api/users/
请求,它使用户能够更新他们的用户名和电子邮件,并包括以下 JSON
:
{
"username": "wiener",
"email": "[email protected]",
}
并发GET /api/users/123
请求返回以下 JSON
:
{
"id": 123,
"name": "John Doe",
"email": "[email protected]",
"isAdmin": "false"
}
这可能表明隐藏id
和isAdmin
参数与更新的用户名和电子邮件参数一起绑定到内部用户对象。
测试批量分配漏洞
为了测试是否可以修改枚举isAdmin
参数值,请将其添加到PATCH
请求中:
{
"username": "wiener",
"email": "[email protected]",
"isAdmin": false,
}
另外,PATCH
发送一个isAdmin
参数值无效的请求:
{
"username": "wiener",
"email": "[email protected]",
"isAdmin": "foo",
}
如果应用程序的行为不同,这可能表明无效值会影响查询逻辑,但有效值不会。这可能表明用户可以成功更新该参数。
然后,您可以PATCH
发送一个将isAdmin
参数值设置为true
的请求,以尝试利用该漏洞:
{
"username": "wiener",
"email": "[email protected]",
"isAdmin": true,
}
如果isAdmin
请求中的值在未经过充分验证和清理的情况下绑定到用户对象,则用户wiener
可能会被错误地授予管理员权限。要确定是否是这种情况,请浏览应用程序以wiener
查看您是否可以访问管理员功能。
3、实验室:利用批量分配漏洞
api/checkout
-> api
接口 -> options
支持 Get
和 Post
方法,将get
方法输出的响应结果,放在POST
请求体中
{
"chosen_discount":{
"percentage":100
},
"chosen_products":[{
"product_id":"1",
"name":"Lightweight "l33t" Leather Jacket",
"quantity":1,
"item_price":133700
}]}
即可
预防 API
漏洞
在设计 API
时,请确保从一开始就考虑安全性。特别是,请确保您:
-
如果您==不希望 API
公开访问,请保护好您的文档==。 -
确保您的==文档保持最新==,以便合法测试人员能够完全了解 API
的攻击面。 -
==应用允许的 HTTP
方法的允许列表==。 -
验证每个请求或响应==是否符合预期的内容类型==。 -
==使用通用错误消息==以避免泄露可能对攻击者有用的信息。 -
对 API
的==所有版本都采取保护措施==,而不仅仅是当前生产版本。
为了防止批量分配漏洞,请将用户==可以更新的属性列入允许名单,并将用户不应更新的敏感属性列入黑名单==。
服务端参数污染
某些系统包含==无法通过互联网直接访问的内部 API
==。当网站将用户输入嵌入到对内部 API
的服务器端请求中而未进行充分编码时,就会发生服务器端参数污染。这意味着攻击者可能能够操纵或注入参数,从而使他们能够实现以下目的:
-
覆盖现有参数。 -
修改应用程序行为。 -
访问未经授权的数据。
您可以测试任何用户输入是否存在任何类型的参数污染。例如,查询参数、表单字段、标头和 URL 路径参数都可能存在漏洞。
笔记
此漏洞有时被称为
HTTP
参数污染。然而,该术语也用于指代Web
应用程序防火墙 (WAF
) 绕过技术。为了避免混淆,在本主题中我们仅提及服务器端参数污染。此外,尽管名称相似,但该漏洞类别与服务器端原型污染几乎没有共同之处。
测试查询字符串中的服务器端参数污染
要测试查询字符串中的服务器端参数污染,请在输入中 放置查询语法字符(如#
、=
、 &
) ,然后观察应用程序如何响应。
假设有一个存在漏洞的应用程序,它允许你根据用户名搜索其他用户。当你搜索用户时,你的浏览器会发出以下请求:
GET /userSearch?name=peter&back=/home
为了检索用户信息,服务器使用以下请求查询内部 API
:
GET /users/search?name=peter&publicProfile=true
截断查询字符串
您可以使用 URL 编码#
字符来尝试截断服务器端请求。为了帮助您解释响应,您还可以在#
字符后添加一个字符串。
例如,您可以将查询字符串修改为以下内容:
GET /userSearch?name=peter%23foo&back=/home
前端会尝试访问以下URL:
GET /users/search?name=peter#foo&publicProfile=true
笔记
必须对
#
字符进行 URL 编码。否则,前端应用程序会将其解释为片段标识符,并且不会将其传递给内部API
。
查看响应以查找有关查询是否被截断的线索。例如,如果响应返回 user
peter
,则服务器端查询可能已被截断。如果Invalid name
返回错误消息,则应用程序可能已将其视为 foo
用户名的一部分。这表明服务器端请求可能未被截断。
如果您能够截断服务器端请求,则无需将该字段publicProfile
设置为 true
。您可以利用这一点返回非公开的用户个人资料。
注入无效参数
您可以使用 URL 编码&
字符尝试向服务器端请求添加第二个参数。
例如,您可以将查询字符串修改为以下内容:
GET /userSearch?name=peter%26foo=xyz&back=/home
这会导致服务器端向内部 API
发出以下请求:
GET /users/search?name=peter&foo=xyz&publicProfile=true
查看响应以获取有关如何解析附加参数的线索。例如,如果响应没有变化,这可能表明该参数已成功注入但被应用程序忽略。
为了建立更完整的图像,您需要进行进一步的测试。
注入有效参数
如果您能够修改查询字符串,则可以尝试向服务器端请求添加第二个有效参数。
相关页面
有关如何识别可注入查询字符串的参数的信息,请参阅查找隐藏参数部分。
例如,如果您已经确定了email
参数,则可以将其添加到查询字符串中,如下所示:
GET /userSearch?name=peter%26email=foo&back=/home
这会导致服务器端向内部 API
发出以下请求:
GET /users/search?name=peter&email=foo&publicProfile=true
查看响应以获取有关如何解析附加参数的线索。
覆盖现有参数
要确认应用程序是否容易受到服务器端参数污染,您可以尝试覆盖原始参数。通过注入具有相同名称的第二个参数来执行此操作。
例如,您可以将查询字符串修改为以下内容:
GET /userSearch?name=peter%26name=carlos&back=/home
这会导致服务器端向内部 API
发出以下请求:
GET /users/search?name=peter&name=carlos&publicProfile=true
内部 API
解释两个name
参数。其影响取决于应用程序如何处理第二个参数。这在不同的网络技术中有所不同。例如:
-
PHP
仅解析最后一个参数。这将导致用户搜索carlos
。 -
ASP.NET
结合了这两个参数。这将导致用户搜索peter,carlos
,从而可能导致Invalid username
错误消息。 -
Node.js
/express
仅解析第一个参数。这会导致用户搜索peter
,结果不变。
如果您能够覆盖原始参数,则可能能够进行漏洞利用。例如,您可以添加 name=administrator
到请求中。这可能使您能够以管理员用户身份登录。
4、实验室:利用查询字符串中的服务器端参数污染
服务端参数污染 ---
& #
爆破字段值 --->
/static/js/forgotPassword.js
文件
const resetToken = urlParams.get('reset-token');
if (resetToken)
{
window.location.href = `/forgot-password?reset_token=${resetToken}`;
}
// 如果存在 reset_token值 -> 跳转到 /forgot-password?reset_token=${resetToken}` 处
得到
reset_token
访问
/forgot-password?reset_token={reset_token}
重置密码
然后以重置的密码进行登录即可
测试 REST
路径中的服务器端参数污染
RESTful API
可能会将参数名称和值放在 URL
路径中,而不是查询字符串中。例如,考虑以下路径:
/api/users/123
URL
路径可能分解如下:
-
/api
是根API
端点。 -
/users
代表一种资源,在本例中是users
。 -
/123
表示一个参数,这里是特定用户的标识符。
假设有一个应用程序,它允许您根据用户名编辑用户个人资料。请求将发送到以下端点:
GET /edit_profile.php?name=peter
这会导致以下服务器端请求:
GET /api/private/users/peter
攻击者可能能够操纵服务器端 URL
路径参数来利用该 API
。要测试此漏洞,请添加路径遍历序列来修改参数并观察应用程序的响应情况。
您可以提交 URL
编码peter/../admin
作为参数的值name
:
GET /edit_profile.php?name=peter%2f..%2fadmin
这可能会导致以下服务器端请求:
GET /api/private/users/peter/../admin
如果服务器端客户端或后端 API
规范化该路径,则可能会解析为/api/private/users/admin
。
测试结构化数据格式中的服务器端参数污染
攻击者可能能够操纵参数来利用服务器处理其他结构化数据格式(例如 JSON
或 XML
)时的漏洞。要测试这一点,请将意外的结构化数据注入用户输入,然后查看服务器如何响应。
假设有一款应用,它允许用户编辑个人资料,然后通过向服务器端 API
发出请求来应用更改。当您编辑姓名时,浏览器会发出以下请求:
POST /myaccount
name=peter
这会导致以下服务器端请求:
PATCH /users/7312/update
{"name":"peter"}
您可以尝试按如下方式将参数添加access_level
到请求中:
POST /myaccount
name=peter","access_level":"administrator
如果用户输入在没有经过充分验证或清理的情况下被添加到服务器端 JSON
数据中,则会导致以下服务器端请求:
PATCH /users/7312/update
{name="peter","access_level":"administrator"}
这可能会导致用户peter
被授予管理员访问权限。
相关页面
有关如何识别可注入查询字符串的参数的信息,请参阅查找隐藏参数部分。
考虑一个类似的例子,但客户端用户输入的是 JSON
数据。当你编辑姓名时,浏览器会发出以下请求:
POST /myaccount
{"name": "peter"}
这会导致以下服务器端请求:
PATCH /users/7312/update
{"name":"peter"}
您可以尝试按如下方式将参数添加access_level
到请求中:
POST /myaccount
{"name": "peter","access_level":"administrator"}
如果对用户输入进行解码,然后在没有进行充分编码的情况下将其添加到服务器端 JSON
数据中,则会导致以下服务器端请求:
PATCH /users/7312/update
{"name":"peter","access_level":"administrator"}
同样,这可能会导致用户peter
被授予管理员访问权限。
结构化格式注入也可能发生在响应中。例如,如果用户输入安全地存储在数据库中,然后嵌入到来自后端 API
的 JSON
响应中而没有进行充分编码,则可能会发生这种情况。您通常可以像在请求中一样在响应中检测和利用结构化格式注入。
笔记
下面的示例采用
JSON
格式,但服务器端参数污染可能发生在任何结构化数据格式中。有关 XML 格式的示例,请参阅 XML 外部实体 (XXE
) 注入主题中的XInclude
攻击部分。
使用自动化工具进行测试
Burp
包含自动化工具,可以==帮助您检测服务器端参数污染漏洞==。
Burp Scanner
在执行审计时会自动检测可疑的输入转换。当应用程序接收用户输入、以某种方式转换输入,然后对结果进行进一步处理时,就会发生这种情况。此行为不一定构成漏洞,因此您需要使用上面概述的手动技术进行进一步测试。有关更多信息,请参阅可疑输入转换问题定义。
您还可以使用 Backslash Powered Scanner BApp
来识别服务器端注入漏洞。==扫描仪将输入分类为无聊、有趣或易受攻击==。您需要使用上面概述的手动技术调查有趣的输入。有关更多信息,请参阅 Backslash Powered Scanning:
寻找未知漏洞类别白皮书。
防止服务器端参数污染
为防止服务器端参数污染,请使用允许列表定义不需要编码的字符,并确保所有其他用户输入在包含在服务器端请求中之前都经过编码。您还应确保所有输入都符合预期的格式和结构。
原文始发于微信公众号(夜风Sec):Bp靶场portswigger-Api
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论