Skip to content

Instantly share code, notes, and snippets.

@h0ng10
Created January 11, 2013 18:09
Show Gist options
  • Save h0ng10/4512753 to your computer and use it in GitHub Desktop.
Save h0ng10/4512753 to your computer and use it in GitHub Desktop.
This is a nmap script to check servers for Ruby on Rails installations that are vulnerable to CVE-2013-0156. Just a port of the metasploit auxiliary module, from HD Moore: https://github.com/rapid7/metasploit-framework/blob/master/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb It's my first nmap script and might need some additional te…
local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local vulns = require "vulns"
description = [[
Detects Ruby on Rails installations that are vulnerable to CVE-2013-0156, This critical vulnerability allows unauthenticated attackers to execute code remotely.
This is the nmap/lua port of the metasploit scanner module from hd moore
]]
---
-- @usage
-- nmap -sV --script http-vuln-cve2013-0156 <target>
-- nmap -p3000 --script http-vuln-cve2013-0156 --script-args http-vuln-cve2013-0156.uri=/xxxx,http-vuln-cve2013-0156.hostname=www.foo.bar <target>
-- @output
-- PORT STATE SERVICE VERSION
-- 3000/tcp open http WEBrick httpd 1.3.1 (Ruby 1.9.3 (2012-04-20))
-- | http-vuln-cve2013-0156:
-- | VULNERABLE:
-- | Ruby on Rails XML Processor YAML Deserialization
-- | State: LIKELY VULNERABLE
-- | IDs: CVE:2013-0156
-- | Description:
-- | There are multiple weaknesses in the parameter parsing code for Ruby on Rails
-- | which allows attackers to bypass authentication systems, inject arbitrary SQL,
-- | inject and execute arbitrary code, or perform a DoS attack on a Rails application.
-- | Disclosure date: 2013-01-08
-- | References:
-- | http://cve.mitre.org/cgi-bin/cvename.cgi?name=2013-0156
-- | https://groups.google.com/forum/#!topic/rubyonrails-security/61bkgvnSGTQ/discussion
-- |_ https://community.rapid7.com/community/metasploit/blog/2013/01/09/serialization-mischief-in-ruby-land-cve-2013-0156
--
-- @args http-vuln-cve2013-0156.uri URI Default: /
-- @args http-vuln-cve2013-0156.hostname sets the host header in case of virtual
-- hosting
---
author = "h0ng10 (Hans-Martin Muench)"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"vuln","save"}
portrule = shortport.http
action = function(host, port)
local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or "/"
local hostname = stdnse.get_script_args(SCRIPT_NAME..".uri") or host
local vuln = {
title = 'Ruby on Rails XML Processor YAML Deserialization',
state = vulns.STATE.NOT_VULN, -- default
IDS = {CVE = '2013-0156'},
description = [[
There are multiple weaknesses in the parameter parsing code for Ruby on Rails
which allows attackers to bypass authentication systems, inject arbitrary SQL,
inject and execute arbitrary code, or perform a DoS attack on a Rails application.]],
references = {
'https://groups.google.com/forum/#!topic/rubyonrails-security/61bkgvnSGTQ/discussion',
'https://community.rapid7.com/community/metasploit/blog/2013/01/09/serialization-mischief-in-ruby-land-cve-2013-0156',
},
dates = {
disclosure = {year = '2013', month = '01', day = '08'},
},
}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local resp1 = send_probe(host, port, hostname, uri, "string", "hallo")
local resp2 = send_probe(host, port, hostname, uri, "yaml", "--- !ruby/object:Time {}\n")
local resp3 = send_probe(host, port, hostname, uri, "yaml", "--- !ruby/object:\x00")
if not resp1 then
stdnse.print_debug("%s:%s No reply to the initial XML request", host, port)
return
end
if not resp2 then
stdnse.print_debug("%s:%s No reply to the initial YAML probe", host, port)
return
end
if not resp3 then
stdnse.print_debug("%s:%s No reply to the second YAML probe", host, port)
return
end
if string.find(resp1, '[45]') then
stdnse.print_debug("%s:%s The server replied with %s for our initial XML request, double check PATH", host, port, resp1)
end
if string.find(tostring(resp1),'[23]') and resp3 ~= resp2 and resp3 ~= "200" then
vuln.state = vulns.STATE.LIKELY_VULN
end
return vuln_report:make_output(vuln)
end
send_probe = function(host, port, hostname, uri, type, data)
local data = '<?xml version="1.0" encoding="UTF-8"?>\n<probe type="' .. type .. '"><![CDATA[\n' .. data .. '\n]]></probe>'
local options = {
header = {
Host = hostname,
Connection = "close",
["User-Agent"] = "Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)",
["Content-Type"] = "application/xml",
},
content = data
}
response = http.generic_request(host, port, "POST", uri, options)
return tostring(response.status)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment