2021 API安全渗透

原文链接:https://labs.detectify.com/2021/08/10/how-to-hack-apis-in-2021/
中文翻译:https://mp.weixin.qq.com/s/gwW0ZDJoTx6WgAtwKaCv1w

Detectify Crowdsource is not your average bug bounty platform. It’s an invite-only community of the best ethical hackers who are passionate about securing modern technologies and end users. Crowdsource hackers Hakluke and Farah Hawa have joined forces on this guest blog on how hackers and defenders can (safely) hack APIs to help make the Internet safer.

不是一个普通的 bug 赏金平台。这是一个只有受邀才能参加的社区,里面有最有道德的黑客,他们热衷于保护现代技术和最终用户。Crowdsource 黑客 Hakluke 和 Farah Hawa 已经在这个客座博客上联合起来,讨论黑客和防御者如何(安全地)破解 api 来帮助互联网更安全。

Baaackkk iiin myyy dayyyyy APIs were not nearly as common as they are now. This is due to the explosion in the popularity of Single Page Applications (SPAs). 10 years ago, web applications tended to follow a pattern where most of the application was generated on the server-side before being presented to the user. Any data that was needed would be gathered directly from a database by the same server that generates the UI. It might look something like this:

当时的蜜蜂并不像现在这么普遍。这是由于单页应用程序(Single Page Applications,简称 SPAs)的爆炸式增长。10年前,web 应用程序趋向于遵循一种模式,即大部分应用程序在呈现给用户之前都是在服务器端生成的。生成 UI 的同一台服务器将直接从数据库收集所需的任何数据。它可能看起来像这样:

most of the application was generated on the server-side before being presented to the user

Chart: Web application model 10 years ago

图表: 10年前的 Web 应用程序模型

Many modern web applications tend to follow a different model often referred to as an SPA (Single Page Application). In this model there is typically an API backend, a JavaScript UI, and database. The API simply serves as an interface between the webapp and the database. All requests to the API are made directly from the web browser.

许多现代 web 应用程序趋向于遵循一种不同的模式,通常被称为 SPA (单页应用程序)。在这个模型中,通常有一个 API 后端、一个 JavaScript UI 和一个数据库。这个 API 只是作为 webapp 和数据库之间的一个接口。所有对 API 的请求都是直接从 web 浏览器发出的。

Detectify product update: the fuzzing engine will cover public-facing APIs

产品更新: 模糊引擎将覆盖面向公众的 api

All requests to the API are made directly from the web browser.

Chart: Modern web applications tend to follow a different model often referred to as an SPA

图表: 现代网络应用程序趋向于遵循一种通常被称为 SPA 的不同模式

This is often a better solution because it is easier to scale and allows more specialised developers to work on the project, i.e. frontend developers can work on the frontend while backend developers work on the API. These apps also tend to feel snappier because page loads are not required for every request.

这通常是一个更好的解决方案,因为它更容易扩展,并允许更专业的开发人员在项目上工作,也就是说,前端开发人员可以在前端工作,而后端开发人员在 API 上工作。这些应用程序也往往感觉更加流畅,因为并不是每个请求都需要页面加载。

Instead, different components of the same page will update magically, giving it a similar feel to a native application. This model has also become more popular because ten billion ⁽ᶜᶦᵗᵃᵗᶦᵒⁿ ⁿᵉᵉᵈᵉᵈ⁾ different frontend JavaScript frameworks (React, Vue and Angular, etc.) have come into existence. Suspicious minded folk might conclude that the ridiculous amount of JavaScript frameworks available today is a co-ordinated attempt to slow the progress of webapp development, instigated by the Illuminati. That’s probably not true though .

相反,同一页面的不同组件会神奇地更新,给人一种与本地应用程序相似的感觉。这个模型也变得更加流行,因为已经出现了100亿个不同的前端 JavaScript 框架(React、 Vue 和 Angular 等)。持怀疑态度的人们可能会得出结论,今天可用的大量 JavaScript 框架是一个协调一致的尝试,目的是放慢网络应用开发的进度,这是由光明会发起的。不过这可能不是真的。

All this to say – there are APIs everywhere now, so we should know how to hack and secure them. If you’re still reading – your fingers are probably hovering over ctrl+w. Your brain is thinking “this article title promised to teach me to hack, not what a SPA is. I am an intellectual individual and the author’s attempts at humour are futile, life is short and I am wasting my time reading this stupi….” HOLD IT! We’re getting there. I promise. Cool your jets. Goooooosfraba.

所有这些都是为了说明,现在到处都有 api,所以我们应该知道如何破解和保护它们。如果你还在读书,你的手指可能正在 ctrl + w 键上徘徊,你的大脑正在思考“这篇文章的标题承诺教我如何破解,而不是 SPA 是什么。我是一个知识分子,作者的幽默尝试是徒劳的,生命是短暂的,我正在浪费我的时间阅读这个愚蠢的… …”等等!我们快到了。我保证。冷静一下。Goooooosfraba.

Setting up for testing APIs

设置 api 测试

Postman is a handy application that makes API security testing a breeze. You can download Postman from its official website. In essence, Postman is just another HTTP client which can be used to easily modify and send requests to APIs.

Postman 是一个方便的应用程序,使 API 安全性测试轻而易举。你可以从邮差的官方网站下载。实际上,Postman 只是另一个 HTTP 客户端,可以用它轻松地修改和向 api 发送请求。

If you’ve got a collection of API requests in a file, you can start by importing them into Postman by clicking on the Import button on the top-left corner of the app:

如果你在一个文件中收集了一些 API 请求,你可以通过点击应用程序左上角的导入按钮将它们导入到 Postman 中:

postman API calls

After importing the collection, you will see the API calls loaded in Postman like so:

导入集合后,您将看到在 Postman 中加载 API 调用,如下所示:

API calls in Postman

By clicking on an individual API call, the full API request will be seen on the right. Moreover, different parts of the request will be broken down into sections like Params, Authorization, Headers, Request Body, etc. This will allow you to easily play around with each part.

通过单击一个单独的 API 调用,完整的 API 请求将显示在右侧。此外,请求的不同部分将被分解为像 Params、 Authorization、 header、 Request Body 等部分。这样你就可以很容易地处理每个部分。

parameters of API call requests in postman

You can modify the request headers and body in the same manner as you would in BurpSuite. To analyze the responses to your test cases, you can simply hit the Send button on the top right.

您可以像在 BurpSuite 中一样修改请求标头和正文。要分析测试用例的响应,只需点击右上角的 Send 按钮即可。

how to modify in postman

The response view in Postman looks like this and the response is also bifurcated into different sections like Body, Cookies, Headers, etc. so you can analyze each part carefully.

Postman 中的响应视图看起来像这样,响应也被分成不同的部分,比如 Body、 Cookies、 Headers 等,因此您可以仔细分析每个部分。

response view in postman

Since Postman is meant for APIs specifically, you have a lot of in-built options to test for functions that are mostly present in APIs. For example, by clicking on this drop-down arrow next to the request method, you can see tons of different request verbs to test with:

由于 Postman 是专门用于 api 的,因此您有许多内置的选项可以测试 api 中大多数出现的函数。例如,单击 request 方法旁边的下拉箭头,您可以看到大量不同的请求动词来进行测试:

GET in postman

For GET requests, you can add/remove as well as edit parameters via the Params tab. When you check/uncheck parameters, you can see them appear accordingly in the URI field.

对于 GET 请求,您可以通过 Params 选项卡添加/删除以及编辑参数。在检查/取消检查参数时,可以看到它们相应地出现在 URI 字段中。

get postman 2

When it comes to adding Authorization values, Postman gives you a number of options to choose from and you can choose one depending on how the target API handles authorization.

在添加授权值时,Postman 提供了许多选项供您选择,您可以根据目标 API 处理授权的方式选择一个。

authorization of values in postman

You can also add Authorization values to the entire collection or sub-collection by following these steps:

还可以通过以下步骤向整个集合或子集合添加 Authorization 值:

  1. Click the three dots on the side of the collection/sub-collection name and choose the 单击集合/子集合名称侧面的三个点,然后选择Edit 编辑 option 选择
    authorization step 1
  2. Go to the 你可以去Authorization 授权 tab, select the type of auth and add its value. 选项卡中,选择 auth 类型并添加其值
    authorization step 2
  3. Lastly, go to an individual API request and select the 最后,转到一个单独的 API 请求并选择Inherit auth from parent 从父节点继承授权option 选择
    authorization step 3

This will save you the trouble of setting Authorization values for every single request.

这将为您省去为每个请求设置 Authorization 值的麻烦。

Another handy feature of Postman is that it allows users to proxy API requests with BurpSuite. In order to set that up, you need to follow these steps:

Postman 的另一个方便的特性是,它允许用户使用 BurpSuite 代理 API 请求。为了达到这个目的,你需要遵循以下步骤:

  1. Click on the Settings option from the drop-down menu on the top-right corner 点击右上角下拉菜单中的设置选项
    settings
  2. Go to the 你可以去Proxy 代理人 tab and do this: 然后这样做:
    • Switch Off 关掉Use the system proxy 使用系统代理
    • Switch On 打开开关Add a custom proxy configuration 添加自定义代理配置
    • Set 预备the 的 Proxy Server IP address 代理服务器 IP 地址 & port 港口 to match your Burp Suite proxy settings. The default values are 127.0.0.1 and 8080. 默认值是127.0.0.1和8080
      Your final settings should look like this: 你的最终设置应该是这样的:
      Final settings
  3. To proxy HTTPS requests without any errors, you can switch off 对于没有任何错误的代理 HTTPS 请求,您可以关闭SSL certificate validation SSL 证书验证 under the 在… 之下General 将军 tab. 标签
    toggle ssl certs

Detectify product update: the fuzzing engine will cover public-facing APIs

产品更新: 模糊引擎将覆盖面向公众的 api

Types of API Vulnerabilities

API 漏洞的类型

APIs come in many shapes and sizes, the methods of attacking an API will vary greatly depending on these shapes, and sizes. It would be impossible to cover every attack type in a single blog, but we’re going to go through a bunch of them!

API 有许多形状和大小,攻击 API 的方法将根据这些形状和大小有很大的不同。在一个博客中覆盖所有的攻击类型是不可能的,但是我们将经历一系列的攻击!

API Exposure

空气污染指数

Much like web applications, APIs can have different levels of visibility. Some may be accessible to the internet while others are only available internally. One of the more rudimentary API hacks is simply gaining access to an API which should be inaccessible to you. This may be achieved through a variety of methods, including:

就像 web 应用程序一样,api 可以有不同程度的可见性。有些可以通过互联网访问,而有些则只能在内部访问。最基本的 API 技巧之一就是获得对 API 的访问权,而这些 API 对您来说应该是不可访问的。这可以通过多种方法实现,包括:

  • Forced browsing: 强制浏览: If you are lucky, an API that is intended for internal use may be accidentally exposed to the internet, either through a misconfiguration or just because it was assumed that nobody would be able to find it. API locations may be discovered through many means including analysing JavaScript files, analysing exposed source code, observing host names (e.g. 如果幸运的话,一个用于内部使用的 API 可能会意外地暴露在互联网上,要么是由于配置不当,要么仅仅是因为人们认为没有人能够找到它。通过分析 JavaScript 文件、分析公开的源代码、观察主机名(例如:api 美国石油学会.internal 内部的.example 例子.com) and Google dorking. )和 Google dorking
  • Pivoting: 转轴: Discovering an exploit like SSRF on an external host may allow you to pivot into an internal API. 在外部主机上发现类似 SSRF 的漏洞可能允许您转向内部 API

Mitigation

缓解措施

There are many best practices that can help mitigate against unintentionally exposing APIs including the implementation of strict deployment practices, enforced principle of least privilege through IAM and network segmentation.

有许多最佳实践可以帮助减少无意中暴露的 api,包括实现严格的部署实践、通过 IAM 强制执行最小特权原则以及网络分割。

Misconfigured Caching

错误配置的缓存

For APIs that require authentication, the data being returned is often dynamic and is scoped to each API key. For example, accessing /api/v1/userdetails as Bob should return Bob’s details, while accessing the same endpoint as Jane should return Jane’s details.

对于需要身份验证的 API,返回的数据通常是动态的,其作用域为每个 API 密钥。例如,作为 Bob 访问/api/v1/userdetails 时应该返回 Bob 的详细信息,而作为 Jane 访问相同的端点时应该返回 Jane 的详细信息。

A common misconfiguration occurs when an API does not use the standard Authorization header, instead using a custom header such as X-API-Key. Caching servers may not recognise this as an authenticated request, and may cache it.

当 API 没有使用标准的 Authorization 头,而是使用自定义头(如 x-API-key)时,常见的错误配置会发生。缓存服务器可能不认可这是一个经过身份验证的请求,并可能缓存它。

If this is the case, and there are no Cache-Control or Pragma headers, simply accessing /api/v1/userdetails may reveal the information of another user.

如果是这种情况,而且没有 Cache-Control 或 Pragma 头,那么只需访问/api/v1/userdetails 就可以显示其他用户的信息。

Mitigation

缓解措施

The fix for this is to implement Cache-Control or Pragma headers and utilise the standard Authorization header.

解决这个问题的方法是实现 Cache-Control 或杂注头,并使用标准的 Authorization 头。

Exposed tokens 暴露的代币

We shouldn’t discount the most rudimentary authentication hack. Discovering an API key through any means may provide you with access to the API. To make matters worse, APIs that are meant for internal use often have no need to implement complex authentication flows and thus may implement a static token as their authentication. Secret tokens may be discovered in code repositories, client-side JavaScript, intercepting traffic, etc.

我们不应该忽视最基本的身份验证黑客。通过任何方式发现一个 API 密钥可以为您提供对 API 的访问。更糟糕的是,用于内部使用的 api 通常不需要实现复杂的身份验证流,因此可以实现静态令牌作为其身份验证。可以在代码库、客户端 JavaScript、拦截流量等中发现秘密令牌。

Mitigation 缓解措施

Implementing code scanning into your devops pipeline will often catch API keys before they are deployed somewhere they shouldn’t be. Some code repository providers (including GitHub) also have the ability to detect API keys before they are pushed.

在 devops 管道中实现代码扫描通常会在 API 密钥被部署到不该部署的地方之前捕获它们。一些代码存储库提供程序(包括 GitHub)也能够在 API 键被推出之前检测到它们。

JWT Weaknesses JWT 的弱点

If your API token is three base64 blobs separated by two dots (.), it’s probably a JSON Web Token (JWT). Like many things, these tokens are secure in theory, but there are many ways to mess up the implementation in a way that introduces security issues. Before we delve into JWT attacks we’ll go through a very quick JWT primer.

如果您的 API 令牌是由两个点(.)分隔的三个 base64 blob它可能是一个 JSON Web 令牌(JWT)。像许多事情一样,这些令牌在理论上是安全的,但是有许多方法会以引入安全性问题的方式搞乱实现。在深入探讨 JWT 的攻击之前,我们先来了解一下 JWT 的基本知识。

Here’s an example JWT token, colorized for your aesthetic appreciation:

下面是一个示例 JWT 令牌,为了你的审美欣赏而着色:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Eyjhbgcioijiuzi1niisinr5cci6ikpxvcj9.eyjzdwiiiixmjm0nty3odkwiibmftzsi6ikvvag4grg9liiwiawf0ijoxnte2mjm5mdiyfq.sflkxwrjsmekkf2qt4fwpmejf36pok6yqadqsw5c

There are three base64 encoded strings separated by dots, the first section (colored in red) is the header. The second (colored in purple) is the payload, and the third (colored in blue) is the signature.

有三个用点分隔的 base64编码的字符串,第一部分(红色)是标题。第二个(紫色)是有效载荷,第三个(蓝色)是签名。

If we decode the first section, also known as the header, we will see the following:

如果我们对第一部分进行解码,我们会看到如下内容:

{
"alg": "HS256",
"typ": "JWT"
}

{“ alg”: “ HS256”,“ typ”: “ JWT”}

This outlines the algorithm that we’re using (HS256) and the type of token (JWT). If you’ve not worked with JWTs before you might be thinking “why do we need an algorithm?”. We will get there soon!

这概述了我们正在使用的算法(HS256)和令牌类型(JWT)。如果您以前没有使用过 JWTs,那么您可能会想: “为什么我们需要一个算法?”.我们很快就会到那儿的!

If we decode the second section, also known as the payload, we will see the following:

如果我们解码第二部分,也就是有效载荷,我们将看到如下内容:

{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}

{“ sub”: “1234567890”,“ name”: “ John Doe”,“ iat”: 1516239022}

This section could contain anything, but at minimum it needs to contain some kind of user identifier and a timeout (iat).

这个部分可以包含任何内容,但至少需要包含某种用户标识符和超时(iat)。

The third section (also known as the signature) signs the first two sections with a secret key. In this case it is signed with the HS256 algorithm, which can be determined by looking at the “alg” value in the header. The idea is that the secret key should only be known to the owner of the application. When the application receives a JWT token, it can verify that the token is legitimate by decrypting the signature and comparing it to the data in the header and payload. If the data matches up then the data is verified, otherwise it is invalid.

第三部分(也称为签名)用密钥对前两部分进行签名。在这种情况下,它使用 HS256算法进行签名,这可以通过查看头部的“ alg”值来确定。其思想是,只有应用程序的所有者才应该知道秘钥。当应用程序接收到 JWT 令牌时,它可以通过解密签名并将其与头部和有效负载中的数据进行比较来验证该令牌是否合法。如果数据匹配,则验证数据,否则数据无效。

So why would anyone use JWT? It is because it negates the need for server-side session management. Traditionally when a user logs in, an application would assign a secret token to the user and store that same token in a database. Whenever the user makes a request with their token, the application needs to check if the token is in the database. If it is, the user is allowed to continue, otherwise they are not. When we use JWTs, we introduce a method of trusting data that is sent from the client instead of solely trusting information that is stored in the database. If the application receives a JWT token that can be verified using the secret key, then the application has no reason to distrust it.

那么为什么会有人使用 JWT 呢?这是因为它否定了对服务器端会话管理的需求。传统上,当用户登录时,应用程序将向用户分配一个秘密令牌,并将该令牌存储在数据库中。每当用户使用他们的令牌发出请求时,应用程序需要检查该令牌是否在数据库中。如果是,则允许用户继续,否则不允许继续。当我们使用 JWTs 时,我们引入了一种从客户机发送的信任数据的方法,而不是仅仅信任存储在数据库中的信息。如果应用程序收到可以使用秘密密钥验证的 JWT 令牌,那么应用程序没有理由怀疑它。

As we touched on earlier, in theory JWT tokens are totally secure. The problem is that they are often implemented in a way that is insecure. Here are some examples:

正如我们在前面提到的,理论上 JWT 令牌是完全安全的。问题在于,它们的实现方式往往是不安全的。以下是一些例子:

  • The None algorithm: Some implementations of JWT will allow you to specify “None” as the algorithm. If the algorithm is “None”, the application will not check the validity with the signature, so you can simply update the payload to whatever you want. The most obvious exploitation of this would be to update the user id to another user to take control of their account. None 算法: JWT 的一些实现允许您指定“ None”作为算法。如果算法是“ None”,应用程序将不会用签名检查有效性,因此您可以简单地将有效负载更新为您想要的任何内容。最明显的利用方式是将用户 id 更新为另一个用户,以控制他们的帐户
  • Brute forcing: It is possible to brute force the secret key of JWT tokens. The feasibility of this attack will depend on the strength of the key. You can attempt to crack JWT tokens using 蛮力破解: 蛮力破解 JWT 令牌的密钥是可能的。这次攻击的可行性将取决于钥匙的强度。您可以使用以下命令尝试破解 JWT 令牌this tool 这个工具. A full write-up on the method can be found on 。有关此方法的详细资料,可浏览Auth0’s blog 0的博客.
  • Simply changing the payload: In some rare cases, the server may simply skip the token verification entirely and trust the data in the payload. While I have not seen this personally, I have read about it occuring in the wild! 只需更改有效负载: 在某些罕见的情况下,服务器可能完全跳过令牌验证,并信任有效负载中的数据。虽然我没有亲眼见过这种情况,但我读到过它发生在野外
  • Switching RS to HS: There’s a defect with some older JWT libraries where you can trick an application that is expecting tokens signed using asymmetric cryptography into accepting a symmetrically signed token. The symmetrically signed token that ends up being used is actually a public key which is often somehow obtainable, or reused from their HTTPS key. There is a great writeup of this method 将 RS 切换到 HS: 在一些较老的 JWT 库中存在一个缺陷,您可以使用非对称加密技术欺骗期望使用已签名令牌的应用程序接受对称签名令牌。最终被使用的对称签名令牌实际上是一个公钥,通常可以以某种方式获得,或者从它们的 HTTPS 密钥中重用。关于这个方法有一篇很棒的文章here 这里.
  • The 这个iat timeout is not honoured, so JWT tokens remain valid forever. 不支持超时,因此 JWT 标记将永远有效

Mitigation 缓解措施

The best mitigation for JWT weaknesses is to utilise a widely-used, reputable JWT library for all JWT operations.

对于 JWT 的弱点,最好的缓解方法是在所有 JWT 操作中使用广泛使用的、有信誉的 JWT 库。

Authorization Issues / IDOR 授权事项/IDOR

Authorization is the process of checking whether an authenticated user has access to a specific user. A common authorization-related vulnerability is known as an Insecure Direct Object Reference (IDOR). For example, in an API for an invoicing application, we may have an endpoint that is used to get the details of an invoice:

/api/v1/invoices/?id=1234

授权是检查经过身份验证的用户是否有权访问特定用户的过程。一个常见的与授权相关的漏洞称为不安全的直接对象引用(Insecure Direct Object Reference,IDOR)。例如,在一个发票应用程序的 API 中,我们可能有一个用于获取发票详细信息的端点:/API/v1/invoices/?1234

The id parameter is the identifier for the invoice that should be returned. If this endpoint is secured, I should only be able to get the details of invoices that belong to me. For example if I created an invoice with an ID of 1234 then it should return the details. If I try to access an invoice that I did not create by browsing to /api/v1/invoices/?id=1233, it should return an error.

Id 参数是应该返回的发票的标识符。如果这个端点是安全的,我应该只能得到属于我的发票的细节。例如,如果我创建了一个 ID 为1234的发票,那么它应该返回详细信息。如果我试图访问一个没有通过浏览/api/v1/invoices/来创建的发票,那么我会怎么做?1233,它应该返回一个错误。

If I am able to change the identifier to view the invoice details of other users, this is a vulnerability known as an IDOR.

如果我能够更改标识符以查看其他用户的发票详细信息,这是一个称为 IDOR 的漏洞。

To counter IDOR issues, many APIs today are utilising UUIDs as object identifiers. A UUID looks like this:

为了解决 IDOR 问题,现在很多 api 都使用 UUID 作为对象标识符:

f1af4910-e82f-11eb-beb2-0242ac130002

It’s important to note that utilising UUIDs as identifiers is not a valid method of mitigating IDOR issues. In fact, the UUID RFC specifically calls this out:

需要注意的是,使用 uuid 作为标识符并不是减轻 IDOR 问题的有效方法。事实上,UUID RFC 特别指出了这一点:

Do not assume that UUIDs are hard to guess; they should not be used as security capabilities (identifiers whose mere possession grants access), for example.  A predictable random number source will exacerbate the situation.

不要假定 uuid 很难猜测; 例如,它们不应该用作安全性能(仅仅拥有授予访问权的标识符)。一个可预测的随机数源会使情况恶化。

While it is good practice to utilise UUIDs as object IDs instead of integers, they should never be used as the sole protection against IDOR attacks.

虽然使用 uuid 而不是整数作为对象 id 是一种良好的实践,但是它们永远不应该作为防止 IDOR 攻击的唯一保护。

Mitigation 缓解措施

Authorization issues are typically difficult to detect in an automated fashion. The structure of the codebase should be set up in a way that it is difficult to make authorization errors on specific endpoints. To achieve this, authorization measures should be implemented as far up the stack as possible. Potentially at a class level, or using middleware.

授权问题通常难以自动检测。代码库的结构设置方式应该使得很难在特定端点上发生授权错误。为了实现这一点,授权措施应该尽可能地在堆栈上实现。可能在类级别,或者使用中间件。

Undocumented Endpoints 没有文档的端点

It is common to encounter situations where the API you are attacking has no documentation (or at least none that is accessible to you). It is also fairly common that an API with documentation will have endpoints beyond what is documented. Sometimes the very existence of these endpoints may be a security issue – for example, the endpoint may be designed for administrative purposes, and allow you to perform administrative tasks as an underprivileged user. Other times, these endpoints may present vulnerabilities simply because they have not been tested as thoroughly as the ones that are easy to discover.

遇到您要攻击的 API 没有文档(或者至少没有您可以访问的文档)的情况是很常见的。带有文档的 API 具有文档之外的端点也是相当常见的。有时,这些端点的存在本身可能是一个安全问题——例如,端点可能是为管理目的而设计的,并允许您作为弱势用户执行管理任务。在其他情况下,这些端点可能仅仅因为它们没有像容易发现的端点那样被彻底测试而显示漏洞。

Here are a few methods that we can utilise to uncover undocumented endpoints:

以下是我们可以利用的一些方法,来发现未登记的端点:

  • Use an application that interfaces with the API, and capture traffic. Perhaps the most commonly used tool for this today is Burp Suite.  使用与 API 接口的应用程序,并捕获流量。也许今天最常用的工具是 Burp Suite
    • Set up Burp Suite to proxy the application traffic 设置 Burp Suite 来代理应用程序流量
    • Use all the application features 使用所有的应用程序功能
    • Check the endpoints that were used by viewing the Target tab. 检查通过查看 Target 选项卡使用的端点
  • Observe errors. Many APIs will give errors that are verbose enough to enumerate undocumented endpoints and parameters. For example, sending a blank POST request to 观察错误。许多 api 提供的错误非常冗长,足以枚举无文档记录的端点和参数。例如,将空白 POST 请求发送到/api/v1/randomstring may result in an error that says something along the lines of 可能会导致一个错误,说一些类似于Invalid route, valid routes are [/users,/invoices,/customers].
  • Analyse client-side JavaScript. If you know of an application that interacts with the API, you can analyse the JavaScript within that application to gather a list of API endpoints that may be accessible. 分析客户端的 JavaScript。如果您知道有一个应用程序与 API 交互,那么您可以分析该应用程序中的 JavaScript,以收集可访问的 API 端点列表
  • Use 使用Kiterunner 科特伦纳, a tool by Assetnote that is designed for content discovery on APIs 是由 Assetnote 设计的一个工具,用于在 api 上发现内容
  • Brute force endpoints, there are some 暴力破解端点,有一些excellent 好极了 API wordlists on API 文字列表Assetnote’s website 的网站

Mitigation 缓解措施

Having a strong, structured method and process for documenting API functionality can save a lot of headaches down the road. Swagger is an excellent standard for exactly this. Additionally, it’s best to plan out the API functionality with documentation before coding it instead of the other way around.

拥有一个强大的、结构化的方法和过程来记录 API 功能可以避免很多麻烦。昂首阔步正是这一优秀的标准。此外,最好在编码 API 功能之前就用文档来规划 API 功能,而不是相反。

Different Versions 不同版本

When an organisation releases an API, it may interface with many different applications. If the API is updated at any point, it may introduce breaking changes for one or more of those applications. For that reason, multiple API versions are often implemented as a means of supporting older API schemas while also upgrading the API over time for new users.

当一个组织发布一个 API 时,它可能与许多不同的应用程序接口。如果 API 在任何时候被更新,它可能会引入一个或多个这些应用程序的突变更改。出于这个原因,多个 API 版本通常作为一种支持旧的 API 模式的方法来实现,同时随着时间的推移为新用户升级 API。

It is worth testing all versions of the API. Older versions may still have security issues that have since been fixed in the new version, and newer / bleeding edge / beta versions may have introduced new security issues.

测试所有版本的 API 是值得的。旧版本可能仍然存在安全问题,新版本已经解决了这些问题,而新版本/前沿/beta 版本可能引入了新的安全问题。

A common schema for api versioning is:

Api 版本控制的一个常见模式是:

/api/v1/
/api/v2/
/api/beta/

/api/v1/api/v2/api/beta/

It’s always worth checking for non-production route names such as:

qa
devenv
devenv1
devenv2
preprod
pre-prod
test
testing
staging
stage
dev
development
deploy
slave
master
review
prod
uat
prep
Version2

检查非生产路由的名称总是值得的,例如: qa devev devenv1 devenv2 preprod pre-prod test test staging stage dev development deploy slave master review prod uat prep Version2

This wordlist was taken from an example set in DNSCewl.

这个单词列表来自于 DNSCewl 中的一个例子。

Mitigation 缓解措施

API versions can be supported with defined lifecycles. For example, when you release version 2 of the API, you may notify your users that version 1 will reach End of Life (EoL) and be deprecated at a specific date in the future. Pre-production/beta versions should only be publicly accessible if they have been thoroughly tested for security issues.

API 版本可以支持定义的生命周期。例如,当您发布 API 的版本2时,您可能会通知您的用户版本1将到达生命终结(EoL) ,并在未来的某个特定日期被弃用。预生产/测试版本只有在经过安全问题的彻底测试后才能公开访问。

Rate Limiting 速率限制

Most of the time, APIs do not have any protection on the number of times a user can request them. This is termed as “lack of rate limiting” and it occurs when an attacker can call the API thousands of times to cause some unintended behaviour. The server will attempt to fulfill each of these requests and this can potentially:

在大多数情况下,api 对用户请求它们的次数没有任何保护。这被称为“缺乏速率限制”,当攻击者可以数千次调用 API 导致一些无意识的行为时,就会发生这种情况。服务器将尝试满足每个请求,这可能会:

  • DOS the server by overloading it with requests 通过过载请求来对服务器进行 DOS 操作
  • Allow the attacker to quickly exfiltrate sensitive user information such as: user IDs, usernames, emails etc. 允许攻击者快速过滤敏感的用户信息,如: 用户 id、用户名、电子邮件等
  • Bypass authentication by brute-forcing a login API 通过强制登录 API 绕过身份验证
  • Flood the victim’s inbox by brute-forcing a functionality which sends an email/SMS to the victim 洪水的受害者的收件箱强制一个功能,发送电子邮件/短信给受害者

Let’s look at an attack scenario where there is no rate limiting on an API endpoint that checks credentials:

让我们来看一个攻击场景,在这个场景中,对检查凭证的 API 端点没有速率限制:

GET /api/v1/user/1234/login/?password=mypassword

GET/api/v1/user/1234/login/? password = mypassword

Normally you would not see a password sent in a GET request like this, but for the purposes of this demonstration, let’s say that you do. To brute force the password in the endpoint above, an attacker can use BurpSuite’s Intruder tool. This tool allows us to customize different kinds of brute-force attacks but for this example, we will be feeding it a simple list of passwords.

通常情况下,您不会在这样的 GET 请求中看到密码发送,但是为了演示的目的,假设您看到了。为了暴力破解端点上的密码,攻击者可以使用 BurpSuite 的侵入工具。这个工具允许我们定制不同类型的暴力破解,但是在这个例子中,我们将提供一个简单的密码列表。

In the span of a few seconds, Intruder will make hundreds of API requests, attempting a different password on each request.

在几秒钟的时间内,入侵者将发出数百个 API 请求,尝试在每个请求上使用不同的密码。

GET /api/v1/user/1234/login/?password=notmypassword1
GET /api/v1/user/1234/login/?password=notmypassword2
GET /api/v1/user/1234/login/?password=notmypassword3
.
.
.
GET /api/v1/user/1234/login/?password=correctpassword!

Since there is no rate limit, the server will happily serve the responses to all these requests and the attacker can continue to brute-force different passwords as quickly as possible until the correct one is found.

由于没有速率限制,服务器将很乐意为所有这些请求提供响应,攻击者可以继续尽快暴力破解不同的密码,直到找到正确的密码。

To protect against rate limiting bugs, the application should implement a limit on how often a user can request an API within a certain timeframe. The exact limit that is set will depend on the use case for that API or endpoint.

为了防止速率限制错误,应用程序应该对用户在某个时间段内请求 API 的频率实施限制。设置的确切限制将取决于该 API 或端点的用例。

Mitigation 缓解措施

Rate-limiting can be implemented in many different ways. Per account, per IP address, per endpoint, for the entire API, etc. Some reverse proxies can also be used to implement application-wide throttling without additional development. The exact implementation that you use will depend on the requirements of your specific application.

速率限制可以用许多不同的方法实现。每个帐户,每个 IP 地址,每个端点,整个 API 等等。还可以使用一些反向代理来实现应用程序范围的节流,而无需进行额外的开发。您所使用的具体实现将取决于特定应用程序的需求。

Race Conditions 竞赛条件

A race condition is when two or more requests are sent at the same millisecond to an API. When an API does not have a mechanism to handle this scenario, it can lead to the API processing the requests in an unintended manner.

竞争条件是以相同的毫秒向 API 发送两个或多个请求。当一个 API 没有处理这个场景的机制时,它可能导致 API 以意想不到的方式处理请求。

A potential attack scenario for a race condition could arise while redeeming discounts or promo codes on a vulnerable e-commerce application.

在为易受攻击的电子商务应用程序赎回折扣或优惠代码时,可能会出现针对竞争条件的潜在攻击场景。

POST /api/v1/discount
Target: www.ecommerce.com
Connection: close

{
"code","first10",
"amount":"10"
}

BurpSuite has an extension called Turbo Intruder which allows users to test for race conditions using the in-built race.py script.

BurpSuite 有一个名为 Turbo Intruder 的扩展,允许用户使用内置 race.py 脚本测试竞态条件。

After configuring the attack in Turbo Intruder, an attacker can send multiple concurrent requests to the API for redeeming this promo code.

在 Turbo Intruder 中配置攻击后,攻击者可以向 API 发送多个并发请求,以赎回这个 promo 代码。

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

If the API does not invalidate the promo code immediately after receiving the first concurrent request, the discount amount could be doubled, tripled, etc.

如果 API 在接收到第一个并发请求后没有立即使促销代码失效,折扣金额可能会增加一倍,三倍,等等。

This attack is named “Race Condition” because it is a race between how fast an attacker sends requests to modify a resource and how fast the application updates that particular resource.

这种攻击被称为“竞争条件”,因为它是一场竞赛,一方面攻击者发送修改资源的请求的速度,另一方面应用程序更新特定资源的速度。

Mitigation 缓解措施

Unfortunately, mitigating race condition issues often means sacrificing performance. Methods to mitigate race conditions include utilizing locks and other thread-safe functionality. Most programming languages will have thread-safe functionality built in, but it usually needs to be manually specified.

不幸的是,缓解竞争条件问题通常意味着牺牲性能。减轻竞争条件的方法包括使用锁和其他线程安全功能。大多数编程语言都有内置的线程安全功能,但通常需要手动指定。

XXE injection XXE 注射剂

XXE stands for XML External Entity and this injection vulnerability can be tested anywhere an API is used to process XML data. SOAP APIs could also be vulnerable to XXE injection because they are based in XML.

XXE 代表 XML 外部实体,这个注入漏洞可以在使用 API 处理 XML 数据的任何地方进行测试。SOAP api 也可能容易受到 XXE 注入的影响,因为它们基于 XML。

An API endpoint that uses XML looks something like this:

使用 XML 的 API 端点如下所示:

POST /soap/v2/user HTTP/1.1
Host: example.com
Content-Type: text/xml


 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE dtd[<!ENTITY username SYSTEM "https://example.com/?username">]>
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<getUser>
<id>&username;</id>
</getUser>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

An XML document uses entities to represent a single object of data and an XML document type definition (DTD) is used to define the entities to be used, structure of the document, etc.

XML 文档使用实体表示单个数据对象,XML 文档类型定义(DTD)用于定义要使用的实体、文档结构等。

XXE injection refers to when an attacker injects custom external entities that are outside of the specified DTD. Once these external entities are parsed by the API, it can allow an attacker to access the application’s internal files, escalate to SSRF, leak sensitive data to an attacker-controlled domain or DOS the server.

XXE 注入是指当攻击者注入指定 DTD 之外的自定义外部实体时。一旦这些外部实体被 API 解析,它可以允许攻击者访问应用程序的内部文件,升级到 SSRF,泄漏敏感数据到攻击者控制的域或 DOS 服务器。

This is an example of a request where an attacker has injected an external custom entity called xxe and the purpose of this entity is to retrieve an internal file:

这是一个例子,攻击者注入了一个名为 xxe 的外部定制实体,这个实体的目的是检索一个内部文件:

POST /soap/v2/user HTTP/1.1
Host: example.com
Content-Type: text/xml

 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<getUser>
<id>&xxe;</id>
</getUser>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

If the API allows the usage of a standard XML parser to process the data, then this injected external entity will be processed by the application and will return the content of /etc/passwd to the attacker.

如果 API 允许使用标准 XML 解析器处理数据,那么应用程序将处理这个注入的外部实体,并将/etc/passwd 的内容返回给攻击者。

Mitigation 缓解措施

Ensure that the XML parser being utilised is set up to not parse XML entities.

确保所使用的 XML 解析器设置为不解析 XML 实体。

Switching Content Type 转换内容类型

Even though an API may use JSON as a data format to communicate, the underlying server/framework may still accept other data formats like XML. Therefore, when you see an API with a content-Type of application/json, you can still try testing for XXE by switching its value to Content-Type: text/xml

即使 API 可以使用 JSON 作为数据格式进行通信,底层服务器/框架仍然可以接受 XML 等其他数据格式。因此,当您看到一个包含 content-Type of application/json 的 API 时,仍然可以通过将其值切换为 content-Type: text/xml 来尝试对 XXE 进行测试

For example, if an API uses JSON:

例如,如果一个 API 使用 JSON:

POST /api/v1/user HTTP/1.1
Host: example.com
Content-Type: application/json

It can be modified to send XML data in this manner:

它可以修改为以这种方式发送 XML 数据:

POST /soap/v2/user HTTP/1.1
Host: example.com
Content-Type: text/xml

 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>

Mitigation 缓解措施

This bug only really exists on frameworks that are designed to accept multiple formats, where each format corresponds to a type of object. In these cases, the frameworks would normally have an option to whitelist available formats. It should be noted that this is quite rare in 2021.

这个缺陷只存在于设计用于接受多种格式的框架中,其中每种格式对应于一种对象类型。在这种情况下,框架通常可以选择白名单可用格式。值得注意的是,这在2021年是相当罕见的。

HTTP Methods

HTTP 方法

APIs usually support various types of HTTP methods. Some of the common ones are GET, POST, PATCH, DELETE and OPTIONS.If a GET request is sent at a point where an application expects a POST request, then this can lead to the application responding in unexpected ways.

Api 通常支持各种类型的 HTTP 方法。常见的有 GET、 POST、 PATCH、 DELETE 和 options.如果 GET 请求发送在应用程序需要 POST 请求的地方,那么这可能导致应用程序以意想不到的方式响应。

Let’s take CSRF as an example. CSRF (Cross-Site Request Forgery) is when an attacker tricks the victim into submitting a request which can cause state-changing actions to occur on the victim’s account. These changes can be anything from changing the victim’s personal details and in some cases, even changing the victim’s password leading to a full account takeover.

让我们以 CSRF 为例。CSRF (跨站请求伪造)是攻击者欺骗受害者提交一个请求,这可能导致受害者帐户上发生状态改变动作。这些改变可以是任何事情,从改变受害者的个人信息,在某些情况下,甚至改变受害者的密码,导致一个完整的帐户接管。

A normal request to change the victim’s personal details may look something like this:

一个改变受害者个人信息的正常请求可能看起来像这样:

POST /api/v1/user
Target: www.example.com
Content-Type: application/json

{
  "name","victim", 
  "email":"victim@example.com", 
  "location":"AU", 
  "csrftoken":"76hhs683bki0"
}

After observing the above request, we might conclude that a CSRF attack will not be possible since the csrftoken value is being sent in the request body. However, if an API does not restrict the HTTP methods which can be used for this request, then it may be possible for an attacker to bypass this protection by sending this request using the GET method.

在观察了上面的请求之后,我们可能会得出结论,CSRF 攻击是不可能的,因为 csrftoken 值是在请求主体中发送的。但是,如果 API 不限制可用于此请求的 HTTP 方法,那么攻击者可以通过使用 GET 方法发送此请求来绕过此保护。

GET /api/v1/user?name=hacked&email=attacker@example.com&location=FR
Target: www.example.com
Connection: close

Additionally, sometimes the server simply does not validate the CSRF token, or accepts the request if no CSRF token parameter exists at all in the request.

此外,有时服务器根本不验证 CSRF 令牌,或者在请求中根本不存在 CSRF 令牌参数时接受请求。

Another common vulnerability in REST APIs is when permissions have been correctly applied on an endpoint, but only for one HTTP verb. For example, you may not be able to GET other people’s records, but you may be able to edit their records by utilizing the PATCH verb.

REST api 中的另一个常见漏洞是,在端点上正确应用了权限,但只针对一个 HTTP 谓词。例如,您可能无法获取其他人的记录,但是您可以利用 PATCH 动词编辑他们的记录。

Mitigation 缓解措施

Manually specify HTTP verbs in your routes. Do not utilize verbs unnecessarily, and ensure that any endpoints that are specified do have the same controls applied against all verbs. Some frameworks will do this automatically, others will not.

在路由中手动指定 HTTP 谓词。不要不必要地使用动词,并确保指定的任何端点对所有动词都应用相同的控件。有些框架会自动完成这个任务,有些则不会。

Injection Vulnerabilities 注入漏洞

Server-side injection flaws like SQL injection, RCE, command injection and SSRF can exist on APIs in the same way they exist on regular web applications. Whenever any injected data is directly passed to the interpreter on the backend, it leaves room for an attacker to send targeted queries and commands to access internal data or execute arbitrary code.

服务器端注入缺陷,如 SQL 注入、 RCE、命令注入和 SSRF 等,可以像普通 web 应用程序一样存在于 api 上。每当任何注入的数据被直接传递给后端的解释器时,攻击者就有空间发送目标查询和命令来访问内部数据或执行任意代码。

For example, let’s test SSRF on the following API request:

例如,让我们在下面的 API 请求上测试 SSRF:

POST /api/v1/user
Target: www.example.com
Content-Type: application/json

{
  "name","victim", 
  "email":"victim@example.com", 
  "profile_pic_url":"https://www.example.com/me.jpg"
}

An attacker can attempt SSRF on the website field by sending a request like this:

攻击者可以在网站字段上尝试 SSRF,发送如下请求:

POST /api/v1/user
Target: www.example.com
Content-Type: application/json

{
  "name","victim", 
  "email":"victim@example.com", 
  "profile_pic_url":"http://localhost/admin"
}

If the backend interpreter does not validate the profile_pic_url value properly, then this can lead to an attacker exploiting SSRF and successfully accessing internal data.

如果后端解释器没有正确验证 profile _ pic _ url 值,那么这可能导致攻击者利用 SSRF 成功访问内部数据。

Similarly, an attacker can also attempt SQL injection if the data on this request is improperly validated:

类似地,如果该请求上的数据被不正确地验证,攻击者也可以尝试 SQL 注入:

POST /api/v1/orders
Target: www.example.com
Content-Type: application/json

{
  "offset":0,
  "limit":10,
  "scope":"orders_all",
}

By looking at the request body, we may get a hint that the values of these parameters are being sent to a backend database interpreter. Therefore, we can attempt SQL injection by modifying these values to targeted queries:

通过查看请求主体,我们可能会得到一个提示,即这些参数的值正在被发送到后端数据库解释器。因此,我们可以通过修改这些值来尝试 SQL 注入:

POST /api/v1/orders
Target: www.example.com
Content-Type: application/json

{
  "offset":0,
  "limit":10,
  "scope":"SELECT sleep(10)",
}

Once again, if the interpreter does not validate these values properly, then this can lead to a SQL injection where an attacker can cause a time delay in the database and even exfiltrate sensitive data.

再一次,如果解释器没有正确验证这些值,那么这可能导致 SQL 注入,攻击者可能在数据库中造成时间延迟,甚至可能将敏感数据转移出去。

Mitigation 缓解措施

Mitigating injection vulnerabilities in APIs is essentially the same as mitigating injection vulnerabilities in web applications. SAST/DAST scanners can help with this, but secure development practices are the best mitigation. Parameterize SQL queries, utilise ORMs and reputable libraries where possible, don’t trust user input!

缓解 api 中的注入漏洞与缓解 web 应用中的注入漏洞基本上是一样的。SAST/DAST 扫描器可以帮助解决这个问题,但是安全开发实践是最好的缓解方法。参数化 SQL 查询,尽可能使用 orm 和可信的库,不要相信用户输入!


Written by:
Hakluke and Farah Hawa
Detectify Crowdsource community members

作者: Hakluke 和 Farah Hawa Detectify Crowdsource 社区成员

Hakluke
A photo of Hakluke

My name is Luke Stephens but most know me as hakluke. I am currently living on the Sunshine Coast, in Australia. I recently resigned from my role as the Manager of Training and Quality Assurance for Bugcrowd to start my own consultancy, Haksec. I do a lot of penetration testing and bug bounties and create content for hackers. Check out my Youtube channel.

我的名字是卢克 · 斯蒂芬斯,但大多数人都知道我是哈克 · 卢克。我现在住在澳大利亚的阳光海岸。我最近辞去了培训和质量保证经理的职位,开始了我自己的咨询公司 Haksec。我做了很多渗透测试和 bug 赏金,并为黑客创建内容。看看我的 Youtube 频道。

Farah Hawa
Photo of Farah Hawa

法拉赫 · 哈瓦

Farah Hawa is from Mumbai, India. She works as an Application Security Engineer at Bugcrowd. She’s a part-time bug bounty hunter and also creates technical content for bug bounty hunters & web application pentesters for her YouTube channel with more than 30000 subscribers. You can also find her on LinkedIn.

来自印度孟买。她是 Bugcrowd 的应用安全工程师。她是一个兼职的 bug 赏金猎人,同时也为她拥有超过30000订阅者的 YouTube 频道的 bug 赏金猎人和 web 应用程序五角星创建技术内容。你也可以在 LinkedIn 上找到她。

Read More »

【转载】【漏洞分析】Critical Valve Bug Lets Gamers Add Unlimited Funds to Steam Wallets

A security researcher helped Valve, the makers of the gaming platform Steam, plug an easy-to-exploit hole that allowed users to add unlimited funds to their digital wallet. Simply by changing the account’s email address, the exploit allowed anyone to artificially boost their digital billfold to anything they wanted.

一位安全研究人员帮助游戏平台 Steam 的制造商 Valve 堵住了一个容易被利用的漏洞,这个漏洞允许用户向他们的数字钱包中添加无限的资金。仅仅通过改变账户的电子邮件地址,这个漏洞就可以让任何人人为地把他们的数字钱包提高到他们想要的任何东西。

Steam Wallet funds are exclusive to the Steam platform and are used to purchase in-game merchandise, subscriptions and Steam-related content. Valve restricts Steam credits (or money) from being transferred outside its network for purchase or trading. However, there are several unsanctioned ways to convert wallet funds into actual dollars.

Steam Wallet 基金是 Steam 平台的专用资金,用于购买游戏中的商品、订阅和 Steam 相关内容。Valve 限制 Steam 信贷(或货币)在其网络之外进行购买或交易。然而,有几种未经批准的方式将钱包基金转换成实际的美元。

Working for the HackerOne bug-bounty program, security researcher DrBrix, reported the bug last Monday. By Wednesday, Valve plugged the hole and paid DrBrix $7,500 for identifying the bug.

安全研究员 DrBrix 上周一报告了这个漏洞。到了周三,Valve 堵住了漏洞,并支付给 DrBrix 7500美元来识别漏洞。

The Hack: Turning $1 into $100 or $1M

黑客: 把1美元变成100美元或100万美元

The bug, which has since been patched, was exploited by abusing Valve’s own application programming interface (API) used to communicate with the third-party web payment firm Smart2Pay, owned by Nuvei.

这个漏洞后来得到了修补,但它被用来滥用 Valve 自己的应用程序编程接口(API)来与 Nuvei 旗下的第三方网络支付公司 Smart2Pay 进行通信的做法所利用。

According to DrBrix, the hack allowed an attacker to intercept the POST request sent from Valve to Smart2Pay. This was done via modifying the Steam user’s email address used by Smart2Pay as it passed through the Valve API.

根据 DrBrix 的说法,黑客可以拦截 Valve 发送给 Smart2Pay 的 POST 请求。这是通过修改 Steam 用户在通过 Valve API 时使用的电子邮件地址完成的。

“Firstly you will have to change yours steam account email to something like (I will explain why in next steps, amount100 is the important part): brixamount100abc@█████,” the researcher wrote.

研究人员写道: “首先,你必须把你的邮箱改成类似于(我会解释为什么接下来的步骤中 amount100是最重要的部分) : brixamount100abc@gmail。

This allows the attacker to manipulate communications between Valve and Smart2Pay, circumventing the cryptographic hash used to protect transaction data.

这允许攻击者操作 Valve 和 Smart2Pay 之间的通信,绕过用于保护交易数据的加密散列。

“We can’t change parameters as there is Hash field with signature, however signature is generated like that hash (ALL_FIELDS_NAMES_VALUES_CONTACTED),” DrBrix wrote. “So with our special email we can move parameters in a way that will change amount for us.”

DrBrix 写道: “我们不能改变参数,因为存在带签名的 Hash 字段,但是生成的签名类似于 Hash (ALL _ fields _ names _ values _ contacted)。”。“因此,通过我们的特殊电子邮件,我们可以移动参数,这将改变我们的数量。”

Where the Valve parameters might be,

阀门参数可能在哪里,

“hash(MerchantID1102MerchantTransactionID█████Amount2000…..)” the attacker can turn $1 into $100 simply by changing the format of the email request.

攻击者只需改变电子邮件请求的格式,就可以将 $1变成 $100。

“So with our special email we can move parameters in a way that will change amount for us. For example, we can change original Amount=2000 to Amount2=000 and after contacting it still will be Amount2000. Then we can change email from CustomerEmail=brixamount100abc%40████ to CustomerEmail=brix&amount=100&ab=c%40█████████ by this we are adding new field amount with our value,” DrBrix wrote.

Valve first rated the bug as of moderate importance. However, after investigating, it escalated the bug to critical in nature, scoring it “9-10”, with the highest possible rating 10.

阀门首先将这个漏洞评定为中等重要。然而,在调查之后,这个漏洞升级为本质上的严重漏洞,得到了“9-10”的评分,最高可能的评分为10。

Valve did not return a Threatpost press request for comment.

Valve 没有回复威胁邮报的置评请求。

【转载】【漏洞分析】Facebook Email/phone disclosure using Binary search


So in December I decided to hunt on Facebook, and chose to go with the Facebook Android App

所以在12月,我决定在 Facebook 上搜索,并选择了 Facebook Android 应用

I was analyzing the Facebook app’s password recovery flow.

我正在分析 Facebook 应用的密码恢复流程。

I noticed that the following endpoint was being used.

我注意到正在使用以下端点。

When a user enters his email/phone number his email is supplied in the following manner using parameter `q`

当用户输入他的电子邮件/电话号码时,他的电子邮件以下面的方式使用参数‘ q’提供

The endpoint contained manyyyyy parameters, more than it required.

端点包含许多 yyy 参数,超过了所需的参数。

So I was eager to test what those parameters did.

所以我急于测试这些参数的作用。

I quickly noticed that although the user’s email is being carried by `q` parameter, it also contains a `qs` parameter.

我很快注意到,虽然用户的电子邮件是通过‘ q’参数进行的,但它也包含一个‘ qs’参数。

Now, incase you don’t know;
In Facebook the character `s` behind a parameter means plural.

现在,以防你不知道; 在 Facebook 中,隐藏在参数后面的字符是复数的意思。

Example:
invite_id, Plural= invite_ids
user_id, Plural=user_ids

例如: invite _ id,Plural = invite _ ids user _ id,Plural = user _ ids

I knew that in plural parameters you can supply array of data
like:
user_ids=[“UserID1”,”UserID2″]

我知道可以使用复数参数提供数据数组,比如: user _ ids = [“ UserID1”,“ UserID2”]

so I supplied data in following manner:

因此,我以下列方式提供数据:

qs=[“vicitmemail1@gmail.com”,”victimemail2@gmail.com”]

[ vicitmemail1@gmail. com,vicemail2@gmail. com ]

But it gave an error stating the array key are invalid.

但是它给出了一个错误,说明数组键是无效的。

So this wasn’t a normal array, it had its own keys.

所以这不是一个普通的数组,它有自己的键。

So after some fuzzing I finally figured out that the parameter `qs` takes the value in json wrapped format along with the keys “phone” and “email” and the values of email/phone are the ones that will be supplied as an array

所以经过一些模糊处理之后,我最终发现参数‘ qs’将以 json 包装格式获取值,同时键“ phone”和“ email”以及 email/phone 的值将作为数组提供

Example:
q=victim@gmail.com
qs={“email”:[“
victim@gmail.com”],”phone”:[“981234567890”]}

例如: q = victim@gmail. com qs = {“ email”: [“ victim@gmail. com”] ,“ phone”: [“981234567890”]}

Now,
When you supply an email in the forget password endpoint, the data belonging to you is given in the response in encrypted format.

现在,当您在忘记密码端点中提供电子邮件时,属于您的数据将以加密格式在响应中给出。

The response will contain:
your encrypted userID ,contact points etc

响应将包含: 您的加密用户标识、联系人等

Along with the data there was a value `summary` and it was set to `1`.

除了数据之外,还有一个值“汇总”,它被设置为“1”。

Initially I thought it to be a Boolean.
But turns out:

起初我以为它是一个布尔值,但结果发现:

When we supply one email in `qs`
qs={“email”:[“user1@gmail.com”]}
Data of one user is obtained in response.
hence: summary=1

当我们提供‘ qs’= {“ email”: [“ user1@gmail. com”]}一个用户的数据作为响应获得,因此: summary = 1

When we supply two emails in `qs`
qs={“email”:[“user1@gmail.com”,”user2@gmail.com”]}
Data of two users is obtained in response.
Hence: summary=2

当我们提供“ qs”= {“ email”: [“ user1@gmail. com”,“ user2@gmail. com”]中的两封电子邮件时,会得到两个用户的回复数据,因此: summary = 2

But here comes the final part:

但是最后一部分来了:

Lets say I supply:
qs={“email”:[“victim1@gmail.com”,”victim2@gmail.com]}
Data of only 1 user is obtained.

比如说我提供: qs = {”email”: [“ victimit1@gmail. com”,“ victimit2@gmail. com ]}仅获得一个用户的数据。

What does that mean?
Both the emails belong to the same user and both emails pointed to same user resulting in the response “summary”:1

这是什么意思?两封电子邮件都属于同一个用户,而且两封电子邮件都指向同一个用户,结果得到的回复是“摘要”: 1

Now, basically it was bruteforce attack scenario.

现在,基本上这是一个残暴的攻击场景。

I supply victim’s username along with a email and if the email belonged to victim the response is “summary:1”

我提供受害者的用户名和电子邮件一起,如果电子邮件属于受害者的回复是“摘要: 1”

qs={“email”:[“victimUserName”,”Email”]}

Qs = {“ Email”: [“ victimUserName”,“ Email”]}

//Yup, We can supply username in email parameter

//是的,我们可以在 email 参数中提供用户名

 

BinarySearch to the rescue

搜索救援

Bruteforce attacks are noisyyy.
But using binary search, this attack became much easier.

野蛮部队的攻击是噪音的。但是使用二进制搜索,这种攻击变得容易得多。

Refer to this video to learn about BinarySearch:

参考这个视频来了解 BinarySearch:

Since, the endpoint was accepting an array of data:
I wasn’t forced to only submit
1 username+1 email

因为,端点是接受一系列的数据: 我没有被迫只提交1个用户名 + 1个电子邮件

I could supply
1username+ 100s of email.

我可以提供1个用户名 + 100个电子邮件。

Example;

例子;

qs={“email”:[“victimUserName”,”email1@gmail.com”,”email2@gmail.com”,”email3@gmail.com”]}

Qs = {“ email”: [“ victimUserName”,“ email1@gmail. com”,“ email2@gmail. com”,“ email3@gmail. com”]}

Now if any of the email from the request belonged to vicitmUserName:

现在,如果请求中的任何电子邮件属于 vicitmUserName:

Summary=3
//Response of email1+email2+email3

3//回复邮件1 + 邮件2 + 邮件3

Else summary=4
//Response of vicitmUsername+email1+email2+email3

4///响应 vicitmUsername + email1 + email2 + email3

This made it easier to bruteforce and effectively identify any user’s private email.

这样可以更容易地强制和有效地识别任何用户的私人电子邮件。

Diagram demonstrating the binarySearch

示范 binarySearch 的图表

I also received this sweeeet response from the Facebook team,
felt good 😉

我也收到了来自 Facebook 团队的甜蜜回复,感觉很好;)

Timeline
Submitted : January 3
Triaged: February 13
Bounty $XXXX Awarded :March 22

递交时间表: 1月3日分流: 2月13日赏金: XXXX: 3月22日

OWASP API安全 Top 10 (1)

OWASP API 安全Top 10 目录:

  • API1:2019-失效的对象级别授权(本篇)
  • API2:2019-失效的用户身份验证
  • API3:2019-过度的数据暴露
  • API4:2019-资源缺乏和速率限制
  • API5:2019-失效的功能级授权
  • API6:2019-批量分配
  • API7:2019-安全配置错误
  • API8:2019-注入
  • API9:2019-资产管理不当
  • API10:2019-日志和监视不足

API1:2019-失效的对象级别授权

漏洞原理

这个漏洞和IDOR是类似的,就是权限有问题,用户访问了不该访问的资源,其实就是我们常说的越权。

比如修改请求中的对象ID,达到对没有授权的对象ID的访问。导致敏感数据的未授权访问,数据丢失,数据被篡改,账号被接管等问题。

这个漏洞非常的普遍,在前几年,几乎随便都能测到这种漏洞。服务器因为不会完整的跟踪用户的状态,只会通过解析对象ID来返回结果,如果不做授权就会直接返回数据。

对象级的授权主要是在代码层面上进行访问控制的一种机制,检验用户是否可以访问对象,出现这种漏洞主要是因为很多厂商都没做这一块。

例子:

Broken Object Level Authorization

当用户向API发出请求的时候,主要是为了访问对象。用户只能访问已经被授权的对象,这是正常的流程。当授权不当的时候,用户就可以访问不应该被允许的数据。

比如我们访问下面这个API,就可以访问到12345用户的消息记录

https://pxiaoer.blog/messages/12345

如果我们把12345改成12346,则变成另外一个用户。如果这样访问就可以得到消息,那就存在越权的漏洞。

还比如,在POST的请求中,有如下的JSON

{
    "userId": "12345678",
    "oldPassword": "My_0ld_Pa$$",
    "newPassword": "$uperS3CurE"
}

我们更改userId如果没有权限验证的话,就会把用户的密码修改成功。

攻击场景

场景1:

一个电商网站的商铺接口

/shops/{shopName}/revenue_data.json

可以通过替换 shopName 来访问其他商铺的数据。

场景2:

在一个可穿戴设备流量中的HTTP头部,存在一个自定义的请求头User-Id:54796

可以通过更改User-Id后面的值来修改其他用户的账号数据

攻击手段

主要是有两种类型的对象

  • 基于user ID
  • 基于对象ID

于user ID

比如像 https://google.com/get_users_search_history?userID=1234

如果能够遍历userID就可以得到其他人的数据

我们可以通过验证userid来防止遍历:

if($_GET['userID'] === object.ownerID){
   ShowData()
}else{
  echo "You are not allowed to view this data"
  wait(5s)
  Redirect(Homepage)
} 

但是不要错误的以这种逻辑来验证:



if(!$_GET['userID'] === object.ownerID){
  echo "You are not allowed to view this data"
  wait(5s)
  Redirect(Homepage)
}
ShowData() 

上面的代码主要是因为可以使用回退按钮,就可以让数据显示。

基于对象ID

对象ID也是一样的,主要是需要记住对对象ID 进行权限限制

比如:

GET product.php?id=12
POST product.php?id=12
DELETE product.php?id=12
OPTIONS

上面三个接口: 得到商品信息,更新商品详情和删除商品

在后面的开发中,又想添加一个功能,把商品信息通过CSV导入,那就需要一个接口

POST /import.php?   {1,"test",12} 

这个时候,攻击者就可以通过修改CSV导入的内容来重写商品信息

POST updateProduct.php?productID?id=1
if($_GET['productID'].owner === object.ownerID){
  UpdateData()
}else{
  echo "You are not allowed to view this data"
  wait(5s)
  Redirect(Homepage)
}

POST /import.php?
StartUpdateData()

还有一种场景就是有跨团队调用的这种函数很容易忘记实现权限验证

比如,上面的例子中添加一个函数,每10分钟更新一次价格,这里的更新价格的函数就可以替换对象ID

TimerForProducts(){
   wait(24H)
   UpdatePrices($_GET[UsersProducts[])
}

UpdatePrices(products[]){
   for each product in products{
      getPrice()
   }
}

GET /updatePrices?UsersProducts=1,2,3,4

上面的程序中,攻击者很容易就可以通过后台调用来更新价格

GET /updatePrices?UsersProducts=1,2,3,4,5,6,7,8,9,...

防御手段

  • 主要是用户授权机制上,用户策略和继承关系来实现一定的授权机制。
  • 在接收用户输入和访问数据库等函数中,通过授权机制来检查登录用户是否有权在该记录上执行所请求的操作。
  • 多测试授权机制
  • 使用auth token来代替userID来作为参数,比如JWT等
  • 使用GUIDS来作为ID,GUIDS是一串很长的随机数,这样可以避免猜出其他用户的认证信息
  • 使用一个认证的解决方案
  • API安全网关

真实案例

1.[Razer Pay] Broken Access Control at /v1/verifyPhone/ allows enumeration of usernames and ID information

链接:https://hackerone.com/reports/752443

雷蛇的账户,允许用户枚举账户查看其他账户的用户名和手机号。

2.Private list members disclosure via GraphQL

链接:https://hackerone.com/reports/885539

3.User sensitive information disclosure

链接:https://hackerone.com/reports/975047

4.Disclose Any Store products, Files, Purchase Orders Via Email through Shopify Stocky APP

链接:https://hackerone.com/reports/763994

5.IDOR on stocky application-Low Stock-Varient-Settings-Columns

链接:https://hackerone.com/reports/853130

6.IDOR on Apple via “X-Dsid” header allows attacker to retrieve name, credit card information, addresses, and various PII of any Apple users via DSID

链接:https://twitter.com/samwcyo/status/1350025970615529473

挖掘建议

自动挖掘

自动化工具确实不太好检测这一类的漏洞,不过还是有一些人在尝试。

I. 黑盒+自动化

主要分给两个关键部分

  • 流量采集
    • 服务器出口日志采集
  • 请求重放
    • 多个账号重放请求
    • 结果对比
    • 排除误报

优点:在理想情况下,可以通过很少的人力去覆盖大量应用

缺点:大量的误报,安全产品死于误报;线上真实流量重放效果最好,却容易造成故障

II. 黑盒+半自动化

像ZTO的authcheck、BurpSuit插件AuthMatrix等差不多,就是手工对比。

  • 流量采集
    • 浏览器被动代理或爬虫方式采集
  • 请求重放
    • 多个账号重放请求
    • 对response进行简化
  • 人工确认
    • 对简化后的response进行判断是否存在漏洞

优点:最后输出的漏洞结果准确度较高,适合针对单一系统进行安全测试

缺点:在面对大量应用及大量迭代新增API时,效率太低

III. 白盒+自动化

这种方式有两种思路,一种是发现存在越权风险的接口,一种是发现不存在越权风险的接口,原理是差不多的

  • 白盒扫描
    • 入参是否包含可越权(可遍历)的参数
    • 是否有从cookie或session中或获取用户标识
  • 风险确认
    • 是否包含authcheck(xxid, userid)的判断逻辑
    • 是否包含@authcheck的注解

优点:仿佛看到了可以批量发现越权风险的方法,对于一些简单的水平越权可以有效发现,而且一般一个系统的权限缺陷都是相似的,发现一个,发现一片

缺点:误报率太高,不能发现复杂的越权风险

IV. 白盒+半自动化

这种思路和上面提到的”黑盒+半自动化“的思路差不多

  • 白盒扫描
    • 扫描器应用的API list
    • 标明入参及用户标识、判断逻辑
  • 人工确认
    • 通过白盒扫描出来的入参、用户标识、判断逻辑来判断是否存在越权风险

优点:对一部分水平越权、未授权访问的风险可以有效发现

缺点:API数量一多就不灵光了,很难发现复杂的越权

手工挖掘

手工比较好检测,主要是找到这些userID和对象ID,而且他们可能出现的位置是在URL,请求主体或者HTTP 头中。

主要是分析返回的响应结果来检查是否有漏洞存在。

手工挖掘工具

  • Chrome 开发者工具
  • Burp Suite
  • Postman

参考资源: