If you're a returning visitor to our CTF Recaps, feel free to dive straight into the insights! For first-time explorers, let us quickly introduce you to the essence of these recaps. Wizer CTFs were introduced to challenge developers, encouraging them to adopt a hacker's mindset and thereby code more securely. This initiative is a pivotal part of our new security awareness training, specially crafted for development teams - Wizer's Secure Code Training for Developers!
After a challenge retires, our Wizer Wizard and CTO, Itzik Spitzen, crafts takeaways that offer valuable insights into the challenge, focusing on the defensive perspective for your script. Curious to test-drive a CTF before delving into the notes? Visit wizer-ctf.com – it's free, and there's something for all skill levels!
In this challenge, we're identifying an SSRF (Server Side Request Forgery) vulnerability in the code below. Let's dive right into it.
Description of code
The code below showcases a couple of endpoints taken from a certain publicly accessible app and an endpoint from a different internal app, which isn't exposed externally. The end point of the public app stores and retrieves a company logo as an image URL. The first endpoint showcased is `/setCompanyLogo` which receives a company ID and an ImageURL to store on the server. The second endpoint is `/getCompanyLogo` which receives a company ID and retrieves the company logo image from the URL. The internal app portion which is showcased, retrieves the list of users from some sort of a CRM, which isn't accessible externally (see the specific code which is responsible for this limitation below).
This endpoint is assumed protected, since it's not accessible to the external network, hence doesn't implement any kind of authentication or authorization.
What’s wrong with that approach?
The code is exposed to an SSRF vulnerability, since the logo can be maliciously used to perform an unintended request within the network directly from the server. By doing so, an attacker could target the internal service and get unauthorized access to CRM information.
What would a successful SSRF attack look like in this case?
An attacker who knows about the internal service could easily identify the SSRF vulnerability. Once they discover the `/CRMUsers` endpoint, they can then store an "imageUrl": "http://localhost:4001/CRMUsers" using the `/setCompanyLogo` endpoint, which could then be executed upon invoking the `/getCompanyLogo` of the specific company ID stored.
SSRF allows an attacker to perform server side requests as if they are connected to the organizational network, injecting requests into the internal network and expanding the attack surface to potentially new endpoints which exist only internally. Having access to hop into the network could be very dangerous depending on what services are actually accessible from within the organizational network. SSRF could also take advantage of trusted-apps interconnection by causing a trusted-app to perform an unintended request on its behalf and hence bypassing critical authentication and/or authorization. In the wild, SSRF has commonly been used to exploit cloud environments, as these use internal cloud metadata endpoints (Metadata Endpoints) to communicate with other applications. This has often led to the leakage of cloud credentials. So it's best not to underestimate the risk of an SSRF as shown in the code here!
- SSRF hides behind innocent functionality, be on the lookout for it:
An innocent image URL could become dangerous when the URL is controlled by user-input. Whenever possible, avoid situations where requests are made to URLs which are controlled by user-input. In our case, we should prefer storing an image file on our server than keeping a URL and performing requests to it at runtime. But in case you absolutely need live request functionality, and the URL should be provided by the user, several protective measures are possible at the Application and Network layers. Here's a good resource to help you think about SSRF prevention: Server-Side Request Forgery Prevention Cheat Sheet (Credit to OWASP Cheat Sheet Series).
- Always assume that attackers can find ways into your internal network:
It is easy to make that mistake and assume that only our employees have access to our internal network. There are multiple reasons for which this assumption is very dangerous, SSRF is only one of them, but not the only one. Here are a couple of examples why you can't assume internal facing apps are safe: (1) firewall configuration could be revised overtime, mistakenly exposing some services externally and (2) over time stuff changes in an organizational setting, people leave and different decisions could be made, making certain services accessible externally directly or indirectly. With that understanding in mind, always make sure that authentication and authorization are fully implemented in all of your apps and endpoints regardless if they are external or internal.
Wanna join us on our next challenge? Sign up for our mailing list at wizer-ctf.com.