How to Hack APIs in 2021(API漏洞利用)

How to Hack APIs in 2021

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.

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:

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

Chart: Web application model 10 years ago

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.

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

图表。10年前的网络应用程序模型

许多现代的网络应用往往遵循一种不同的模式,通常被称为SPA(单页应用)。在这种模式下,通常有一个API后端、一个JavaScript UI和数据库。API只是作为网络应用程序和数据库之间的一个接口。所有对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

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.

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 .

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.

图。现代网络应用倾向于遵循一种不同的模式,通常被称为SPA

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

相反,同一个页面的不同组件会神奇地更新,给人一种类似于本地应用程序的感觉。这种模式也变得更加流行,因为百亿⁽ᶜᶦᵗᵃᵗᶦ ⁿᵉᵈ⁾ 不同的前端JavaScript框架(React、Vue和Angular等)已经出现了。心存疑虑的人可能会得出这样的结论:今天的JavaScript框架数量之多令人发指,这是由光照派煽动的一个协调的尝试,旨在减缓Web应用开发的进展。但这可能不是真的。

所有这些都是为了说明--现在到处都是API,所以我们应该知道如何入侵和保护它们。如果你还在阅读--你的手指可能正徘徊在ctrl+w上。你的大脑正在思考 "这篇文章的标题承诺教我黑客,而不是SPA是什么。我是一个知识分子,作者的幽默尝试是徒劳的,生命是短暂的,我正在浪费我的时间来阅读这个stuppi...." 等一下!"。我们就要到了。我保证。冷却你的喷气。Goooooosfraba。

Setting up for testing APIs

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.

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是一个方便的应用程序,使API安全测试变得轻而易举。你可以从其官方网站下载Postman。从本质上讲,Postman只是另一个HTTP客户端,可以用来轻松地修改和发送对API的请求。

如果你有一个文件中的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请求将在右边被看到。此外,请求的不同部分将被分成若干部分,如参数、授权、头信息、请求正文等。这将允许你轻松地玩弄每个部分。

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相同的方式修改请求头和正文。要分析对你的测试案例的响应,你可以简单地点击右上方的发送按钮。

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中大多存在的功能。例如,通过点击请求方法旁边的这个下拉箭头,你可以看到大量不同的请求动词来测试。

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:

  1. Click the three dots on the side of the collection/sub-collection name and choose the Edit option
  2. 你也可以通过以下步骤为整个集合或子集合添加授权值。

        点击集合/子集合名称边上的三个点,选择编辑选项
    authorization step 1
  3. Go to the Authorization tab, select the type of auth and add its value.
    authorization step 2
  4. Lastly, go to an individual API request and select the Inherit auth from parent option  ##最后,进入一个单独的API请求,选择从父级继承授权选项
    authorization step 3

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

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 & port to match your Burp Suite proxy settings. The default values are 127.0.0.1 and 8080.
      Your final settings should look like this:
      Final settings
  3. To proxy HTTPS requests without any errors, you can switch off SSL certificate validation under the General tab.
    toggle ssl certs

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

Types of API Vulnerabilities

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 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:

  • 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.internal.example.com) and Google dorking.
  • Pivoting: Discovering an exploit like SSRF on an external host may allow you to pivot into an internal 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.

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.

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.

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.

Mitigation

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

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.

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.

JWT Weaknesses

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. 

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

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

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.

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

API漏洞的类型

API有很多形状和大小,攻击API的方法也因这些形状和大小而大不相同。要在一篇博客中涵盖所有的攻击类型是不可能的,但我们将对其中的一些类型进行分析。
API暴露

与网络应用程序一样,API也有不同程度的可见性。有些可能是可以进入互联网的,而有些则是只能在内部使用。一个更初级的API黑客是简单地获得对你来说应该是不可访问的API的访问权。这可以通过各种方法实现,包括。

    强制浏览。如果你很幸运,一个供内部使用的API可能会意外地暴露在互联网上,要么是通过错误的配置,要么只是因为假定没有人能够找到它。API的位置可以通过很多方式发现,包括分析JavaScript文件、分析暴露的源代码、观察主机名(如api.internal.example.com)和Google dorking。
    枢轴。在外部主机上发现像SSRF这样的漏洞,可以让你转向内部的API。

缓解措施

有许多最佳实践可以帮助缓解无意中暴露的API,包括实施严格的部署实践,通过IAM和网络分段强制执行最小权限原则。
错误配置的缓存

对于需要认证的API,返回的数据往往是动态的,并且是针对每个API密钥的范围。例如,以Bob的身份访问/api/v1/userdetails应该返回Bob的详细信息,而以Jane的身份访问同一终端应该返回Jane的详细信息。

一个常见的错误配置发生在API不使用标准的授权头,而使用一个自定义的头,如X-API-Key。缓存服务器可能无法识别这是一个经过验证的请求,并可能将其缓存。

如果是这种情况,并且没有Cache-Control或Pragma头,那么简单地访问/api/v1/userdetails可能会显示出另一个用户的信息。
补救措施

解决这个问题的方法是实现Cache-Control或Pragma头并利用标准的Authorization头。
暴露的令牌

我们不应该忽视最基本的认证黑客。通过任何方式发现一个API密钥可能会让你获得对API的访问。更糟糕的是,供内部使用的API往往不需要实施复杂的认证流程,因此可能会实施静态令牌作为其认证。秘密令牌可能在代码库、客户端JavaScript、拦截流量等方面被发现。
缓解措施

在你的开发管道中实施代码扫描,通常会在API密钥被部署到不应该部署的地方之前捕获它们。一些代码库供应商(包括GitHub)也有能力在推送API密钥之前检测它们。
JWT的弱点

如果你的API令牌是由两个点(...)分开的三个base64 blobs,它可能是一个JSON网络令牌(JWT)。像许多东西一样,这些令牌在理论上是安全的,但有许多方法可以扰乱实现,从而引入安全问题。在我们深入研究JWT攻击之前,我们先来看看JWT的简单介绍。

这里有一个JWT令牌的例子,为了你的审美欣赏,它被着色了。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

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

如果我们对第一部分,也就是标题进行解码,我们将看到以下内容。

{
"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!

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

{
"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).

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.

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.

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:

  • 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.
  • 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 this tool. A full write-up on the method can be found on Auth0’s blog.
  • 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 here.
  • The iat timeout is not honoured, so JWT tokens remain valid forever.

Mitigation

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

Authorization Issues / 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

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.

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

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

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:

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.

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.

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.

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. 
    • Set up Burp Suite to proxy the application traffic
    • Use all the application features
    • Check the endpoints that were used by viewing the Target tab.
  • 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/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.
  • Use Kiterunner, a tool by Assetnote that is designed for content discovery on APIs
  • Brute force endpoints, there are some excellent API wordlists on 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.

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.

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.

A common schema for api versioning is:

/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

This wordlist was taken from an example set in 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.

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:

  • DOS the server by overloading it with requests
  • Allow the attacker to quickly exfiltrate sensitive user information such as: user IDs, usernames, emails etc.
  • Bypass authentication by brute-forcing a login 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:

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.

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

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.

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.

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.

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.

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

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.

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 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. 

An API endpoint that uses XML looks something like this:

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.

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.

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:

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.

Mitigation

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

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

For example, if an API uses 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:

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.

HTTP Methods

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.

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.

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.

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.

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.

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.

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.

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

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:

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.

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

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:

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.

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!


Written by:
Hakluke and Farah Hawa
Detectify Crowdsource community members

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.

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.


 
原文地址:https://www.cnblogs.com/Gouwa/p/15138409.html