A10:2021 - Server Side Request Forgery (SSRF)
For the information about Server Side Request Forgery (SSRF), visit page (opens in a new tab)
Server Side Request Forgery (SSRF)
CWE-918: Server Side Request Forgery (SSRF)
About
SSRF (Server-Side Request Forgery) vulnerabilities arise when a web application fails to verify the user-provided URL when requesting a remote resource. This flaw enables attackers to manipulate the application into sending a customized request to an unintended destination, even if the system is safeguarded by network access controls such as firewalls or VPNs.
Attack
As an attacker, you are going to try different URLs to access the internal resources of the application.
- For launching the attack, you are going to use Burp Suite, with which you have already familiarized yourself in the previous chapters.
- Open Burp Suite and in the designated browser, navigate to the
http://localhost:3001/login
. - Log in with a valid user account.
- Right in front of you is an input field, which should be used to enter the URL of a patient`s Electronic Health Record (EHR). The application will then fetch the EHR from the URL and display it to the user.
- In the input field, enter the following URL:
https://www.hack-health.tech/
. - In Burp Suite
HTTP history
, you can see that the web server has sent a request to the URL you entered and received a response.
POST request with a user-provided URL was sent to a /url
route on a web server.
When you navigate to the definition of /url
route in the source code, you can see that the axios library is used to send a GET request to the provided URL and returns the response data to the client.
- Right-click on the request and send the request to Repeater.
- In the Repeater, change the URL to
http://localhost:5000/health
and send the request.
As you can see, we were able to access the /health
route on the web server, which should not be accessible from the outside world.
- Now, in the Repeater change the URL to
http://ifconfig.pro
and send the request.
In the rendered response, you can see the IP address of the web server and some additional information. The public IP matches your IP address because the server is running locally. However, if the server was deployed, the information we will receive could serve as a valuable asset for an attacker.
Prevention
Whenever you are working with user-provided URLs, you should always make sure that the URL is valid and that it is not pointing to an internal resource. You can use the following technique to prevent SSRF attacks:
- In the
externalSource.ts
file, define a whitelist of allowed domains.
// Define a list of approved external domains
const approvedDomains = [
"https://www.healthit.gov"
];
- Before requesting the URL, check if the URL is in the whitelist.
// Check if the requested URL is in the list of approved domains
const isApproved = approvedDomains.some(domain => url.startsWith(domain));
if (!isApproved) {
throw new Error("Requested URL is not approved");
}
- Final implementation should be:
const express = require("express");
const router = express.Router();
const axios = require("axios");
// Define a list of approved external domains
const approvedDomains = [
"https://www.healthit.gov"
];
router.post("/", async (req, res) => {
try {
const {url} = req.body;
// Check if the requested URL is in the list of approved domains
const isApproved = approvedDomains.some(domain => url.startsWith(domain));
if (!isApproved) {
throw new Error("Requested URL is not approved");
}
// Make a request to the URL provided by the user
const response = await axios.get(url);
// Return the response from the URL to the client
res.send(response.data);
} catch (error) {
console.error(error);
res.status(500).send("Something went wrong");
}
});
module.exports = router;
Verification
- Into the input field, enter the following URL:
http://localhost:5000/health
. - Open Developer Tools -> Console
- Submit the URL.
- In the console, you should see the following error:
- In the same way, you can try other requests used for attack, every time you should see the same error and failure to fetch the data.
- Try to enter a valid URL, for example,
https://www.healthit.gov/faq/what-electronic-health-record-ehr
. The application should fetch the data from the URL and display them in the console.
We have successfully implemented prevention from SSRF attacks. Now, the application will only allow requests to the domains defined in the whitelist, and any other internal or external URL will be rejected.
In this tutorial, we have only covered register endpoint, but in the next chapter, branch will already contain multiple other endpoints. The logic for creating them is almost the same. In the following chapters, we will also adjust the implementation to use middleware and jwt authentication.
Sources
- https://sethsec.blogspot.com/2015/12/exploiting-server-side-request-forgery.html (opens in a new tab)
- https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/ (opens in a new tab)
- https://www.youtube.com/watch?v=Zyt7lUO3mY8 (opens in a new tab)
- https://www.youtube.com/watch?v=-pNYmgK_dWo (opens in a new tab)