State of API Security Report Q3 2022

Learn more

API Threat Research: Server-side Request Forgery on FinTech Platform Enabled Administrative Account Takeover

Salt Labs
Apr 7, 2022

Incident Synopsis

The Salt Labs team helps customers and prospects discover vulnerabilities in their APIs. In this case, we investigated the platforms of a large US-based FinTech company. This company offers a “digital transformation” service for banks of all sizes,  allowing them to switch many of their traditional banking services to online services. The platform is already actively integrated into many banks’ systems, and its services are being used daily by millions of people.

As a result of API vulnerabilities that our researchers identified, they were able to launch attacks where:

  • Attackers could gain administrative access to the banking system using this platform
  • Attackers could leak users’ personal data
  • Attackers could access users’ banking details and financial transactions
  • Attackers could perform unauthorized funds transfers into their own bank accounts

Platforms such as this one are considered to be very prime targets by attackers looking to abuse API vulnerabilities. Why? Two main reasons. One, their API landscape and overall functionality is very rich and complex, which leaves a lot of room for mistakes or overlooking details in development. Two, if a bad actor can successfully abuse this type of platform, the potential profits are huge, since it could allow control of millions of users’ bank accounts and funds.

As with many flawed API implementations, a number of the issues that make it possible to exploit the services map to the OWASP API Security Top 10, including:

Maintaining the anonymity of this service provider is essential, so we have sanitized any technical details that could identify the organization. Upon identifying the vulnerability, we reviewed our findings and provided recommended mitigation to the organization. As part of the broader Salt Labs mission, we are sharing the findings here to increase awareness around API vulnerabilities, including explaining the attack pattern, detailing the steps to propagating the attack, and highlighting mitigation techniques.

Our Research Approach

As Salt Labs researchers engage with such an environment, the first observation is that we are dealing with a huge ecosystem. The FinTech company is providing digital services to many banks and credit unions, each with its own website, mobile application, custom integrations, webhooks and so on. Our first and most important task in looking for critical API issues: Focus.

From our years of experience looking into real-world API issues, we have developed a form of “sixth sense” that allows us to mark potential places within this ecosystem which might be more error prone than others and in which our chances of finding critical API bugs in a relatively short time are dramatically higher.

In this specific case, our focus was on external interactions. More specifically, we focused our efforts on two major parts of one of the bank’s websites: webhooks and third-party integrations. Any banking site must have such integrated functionalities, since they usually allow functions such as advanced notification options, funds transfer, and so on.

Incident Specifics

Our initial strategy in such cases would simply be to browse the relevant website regions while recording all of the traffic sent and received. Later we can take a closer look at the traffic to pinpoint places that may contain bugs. During one of our initial scans, we came across this service:

This page on the FinTech company site supports the platform’s funds transfer functionality. It does exactly what you would expect it to do – let you transfer funds to an external bank. The user can choose which bank to transfer funds to and fill in all the necessary details – then the funds get transferred.

The functionality is straightforward for the customer, but what does it look like behind the scenes? Let's look at the actual traffic being sent once funds have been transferred.

No surprise – the web browser calls an API to handle this request. This specific API is using the endpoint located at “/workflows/tasks/{TASK_GUID}/values,” the HTTP method used to call it is PUT, and the specific request data is sent in the HTTP body section.

One more interesting aspect to notice is that the request body carries a JWT Bearer token. A JWT token, in case you are not familiar with it, is a cryptographically signed key that lets the server know who is the requesting user and what permissions he has.

Up to this point, everything seems to be ok. It's a valid request, and it carries a legitimate and secured authentication token. But now, let's take a closer look at the request data themselves.

The request parameters include, as they should, the required data for this funds transfer. But for any of you who have been dealing with web security, one parameter immediately stands out: InstitutionUrl.

“InstitutionUrl” is a user-provided value that includes a URL pointing to some GUID value placed on the receiving bank website. It is not important at the moment to understand what this GUID value means or how it is used. The more interesting part to understand is, how does our bank's web server handle a user-supplied URL? Does the platform try to contact that URL itself? What happens if a user inserts an arbitrary URL, such as www.google.com? Will the webserver still try to reach it? If it does, that would be a potentially very critical security issue – a  Server Side Request Forgery (SSRF).

How can we determine if the server actually contacts any arbitrary domain provided by the user? Easy – we’ll just provide our own URL. Sure the funds transfer will most probably fail, but by listening for incoming traffic on our own URL we’ll be able to verify that point and further inspect the received traffic.

We go ahead with the plan – we forge a malformed request containing our own domain, cross our fingers, and wait. A few seconds later … Bingo! We got a connection coming in to our server. Seeing this traffic validates our suspicion and means the server blindly trusts domains provided to it in this parameter and issues a request to that URL.

Let’s inspect this new request coming into our server:

The request itself seems pretty useless, and there is not much information in it for us to use. However, as with our original request to the API endpoint, it too contains a JWT token used for authentication. Since JWT tokens contain simply encoded (and signed) text fields, we can very easily inspect its contents. Looking inside, we see:

Wow – it seems like the server request contained a different JWT token than our original one, and this token contains a scope called “service-request/request,” also different from the original request’s JWT. It seems this new token contains no group restrictions.

At this point, we wonder how we can use this new JWT token with the web site. Scratching our memory (and research notes), we tried embedding  this new JWT token into a request we had previously encountered. This API request went to an endpoint named “/accounts/account.” When used with the original JWT token, this request simply returned our account information. What will it return if we use our new JWT token?

Amazing! The API endpoint recognized our new JWT administrative token and very gracefully returned a list of every user and its details across the platform.

That revelation is bad enough, but we wanted to see how deep this rabbit hole would go. So we made yet another request to a different API endpoint. This time we used the “/transactions/transactions” endpoint. Can you guess what we got in response?

Yes. A list of all transactions made by every user on the banking system.

This vulnerability is a critical flaw, one that completely compromises every bank user. Had bad actors discovered this vulnerability, they could have caused serious damage for both the FinTech company and its users. At a minimum, an attacker could have leaked all the platform users’ personal data and all their banking transactions. For reasons of business ethics, we did not pursue any further  research efforts, but we’re confident the potential damage would have been much more significant, potentially allowing manipulation of user funds and perhaps even emptying accounts of all their funds.

Lessons Learned

As we always do, we followed coordinated disclosure practices, and we are happy to report that all the issues we discovered are now fixed.

How can other companies prevent such a potential disaster? User controlled input is the big culprit. Such parameters should never be blindly trusted. Software and API developers should always make sure to apply as many protections as possible to any user input, especially if the input values are susceptible to attacks such as URL values that may lead to SSRF or other vulnerability classes.

In our opinion, the most effective protection would be a combination of both static protections – such as basic sanitation or whitelisting – combined with runtime protections that would identify API traffic anomalies. Such protections would be able to close any gaps or bypasses made to the static methods.

This threat research outlines the risk and potential damage that comes along with every API implementation. The most worrisome aspect about this situation is that the entire attack – all our research – went completely unnoticed by the bank. The FinTech company was using traditional WAF solutions to protect its sites, and these devices unfortunately cannot detect the subtle manipulations characteristic of API attacks.

This FinTech company is by no means alone. We at Salt Labs see vulnerabilities like this one and other API-related issues on a daily basis. We will continue to surface such discoveries to promote awareness for API security, because the consequences of such flaws may be severe, and we strongly believe that education is a fundamental part of finding and resolving these issues.

Stay tuned for more research on API issues from the trenches in the near future. And until then, keep safe!

Go back to blog

Learn everything you need to know to keep your APIs secure

Sign up for blog digest