What is SSRF?
"Server-Side Request Forgery" (SSRF) is a type of security vulnerability which allows an attacker to cause a server to make a request, and usually return the response or some metadata to the attacker. The attacker could just make this request themselves (by typing the URL into their browser), but the server may have access to resources that the attacker does not, usually because it is on the other side of a firewall or other network partition. By convincing a remote server to make these requests with its elevated permissions, the attacker can execute commands or read information they should not be able to.
For example, if a company hosts a plaintext list of passwords on their internal corporate network at http://intern.corp.net/passwords.txt, an attacker may be prevented from accessing this resource directly (that is: over the internet, by just typing the URL into their browser) by a firewall or VPN. However, if the attacker can convince some other service which is hosted on the internal corporate network to make this request on their behalf (and return the response to them), they could use that service to read the password list.
Obviously, this example is pretty silly because no reasonable company would put a list of plaintext passwords at http://intern.corp.net/passwords.txt. Instead, every EC2 server using "IAM Roles" hosts the plaintext list of passwords at http://169.254.169.254/passwords.txt, which is completely different.
In some cases, SSRF may not need to return data to be dangerous. For example, if a service exposes an endpoint at http://intern.corp.net/delete-all-data.php which deletes all data when accessed, the access itself may cause damage. In other cases, attackers may use the response success/error code (even without any response data) to simply search for servers they may be able to attack.
How do you prevent SSRF attacks?
Generally, SSRF can be mitigated with these techniques:
- Do not expose endpoints, particularly HTTP endpoints, which respond to unauthenticated requests with plaintext lists of credentials.
- This effectively includes "do not use IAM Roles", as their design is largely indistinguishable from passwords.txt.
- Do not expose endpoints, particularly HTTP endpoints, which perform destructive actions in response to unauthenticated requests.
- Do not expose services which can make requests to internal resources.
Most discussion of SSRF mitigation focuses on (3), because achieving (1) and (2) are not remotely realistic in a modern network environment.
What qualifies as an SSRF vulnerability in Phabricator?
Phabricator is a service which can make requests to other resources, and makes an effort to prevent users from making requests to internal resources and performing SSRF attacks. However, Phabricator must balance concerns between two competing pressures: preventing SSRF attacks on the one hand; and allowing Phabricator to interact with internal resources that administrators reasonably expect it to be able to interact with on the other.
It is extremely common to reasonably want to configure Phabricator to interact with internal services. Some common internal services that are likely to be hosted in private IP space and which many Phabricator administrators expect Phabricator to be able to interact with are: build servers, repository servers, and authentication servers.
Phabricator generally balances these concerns by (in the default configuration) allowing administrators configure Phabricator to make requests to internal servers, but disallowing requests from unprivileged users. Some of these rules can be changed in configuration. In particular:
- Requests that unprivileged users can make are restricted by the security.outbound-blacklist Config setting, which defaults to standard private IP space.
- Services which often need to make requests into private IP space (builds, repositories, Auth) can only be edited by administrators.
- Some services can be additionally locked to reduce access: notably, Auth configuration can be locked with bin/auth lock, and a banner in the application reminds you to lock it once you're done with setup.
- Phabricator generally does not limit the responses shown to users when they make a request they are authorized to make. For example, if you configure an invalid Auth provider, you may be able to get an entire HTTP response body. Phabricator could just say "an error occurred" instead, but this would be less useful for identifying and resolving the problem, and the user is nominally authorized to make the request (they have Administrator permission, or the appropriate reconfigured permission, and Auth is not locked).
Requests that follow these rules are working as designed and not considered SSRF vulnerabilities. For an attack to represent an SSRF vulnerability in Phabricator, it must generally satisfy this requirement:
These are not SSRF vulnerabilities, since they are Phabricator working as designed:
- By design: Administrators can configure Phabricator to make requests to internal resources.
- By design: Phabricator can be configured to allow more users (not just administrators) to make requests to internal resources (for example, by emptying security.outbound-blacklist or changing policies from "Administrators" to "All Users").
- By design: Users who are authorized by other rules to make a request can get complete information about errors and responses, even in cases where this information disclosure isn't strictly necessary: this is generally desirable to make troubleshooting easier. Opaque errors are often fairly hostile and hard to figure out and fix.
DNS Rebinding Attacks
Phabricator also includes protections against SSRF via DNS rebinding attacks. This is a larger topic (and a more complex attack), and discussed in greater detail in T6755.