local nmap = require "nmap" local shortport = require "shortport" local stdnse = require "stdnse" local string = require 'string' local table = require "table" local vulns = require 'vulns' local spdy = stdnse.silent_require "spdy" description = [[ Checks for a vulnerability (CVE-2014-0088) in nginx 1.5.10, which might allow an attacker to corrupt worker process memory by using, a specially crafted request, potentially resulting in arbitrary code execution (CVE-2014-0088). The problem affects nginx 1.5.10 on 32-bit platforms, compiled with the ngx_http_spdy_module module (which is not compiled by default), if the "spdy" option of the "listen" directive is used in a configuration file. ]] --- -- @usage -- nmap -p 443 --script spdy-vuln-cve2014-0088 -- -- @output -- PORT STATE SERVICE REASON -- 443/tcp open unknown syn-ack 0 -- | spdy-vuln-cve2014-0088: -- | VULNERABLE: -- | nginx SPDY memory corruption vulnerability (CVE-2014-0088). -- | State: VULNERABLE -- | Risk factor: High -- | Description: -- | The spdy implementation in nginx v1.5.10 is affected by a -- | vulnerability which might allow an attacker to corrupt worker -- | process memory by using, a specially crafted request, potentially -- | resulting in arbitrary code execution (CVE-2014-0088). -- | -- | The problem only affects nginx 1.5.10 on 32-bit platforms, compiled with -- | the ngx_http_spdy_module module (which is not compiled by default), if -- | the "spdy" option of the "listen" directive is used in a configuration -- | file. -- | -- | -- | References: -- | http://mailman.nginx.org/pipermail/nginx-announce/2014/000132.html -- | http://nginx.org/download/patch.2014.spdy.txt -- |_ http://nginx.org/en/security_advisories.html author = "Claudiu Perta " license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "safe"} portrule = shortport.port_or_service(443, "", "tcp", "open") local check_vulnerability = function(host, port) local helper = spdy.Helper:new({version="3.1"}) local syn_frame = helper:new_frame() syn_frame:set_type(spdy.Frame.SYN_STREAM) syn_frame:set_flag(spdy.SPDY_CONTROL_FLAGS["CONTROL_FLAG_FIN"]) syn_frame:set_stream_id(1) local user_agent = "Mozilla/5.0 (compatible; Nmap Scripting Engine;" .. "http://nmap.org/book/nse.html)" -- Some standard headers local headers = { [":host"] = host.targetname, [":method"] = "GET" , [":path"] = "/", [":version"] = "HTTP/1.1", [":scheme"] = "https", ["user-agent"] = user_agent, ["accept"] = "*/*", ["accept-encoding"] = "gzip, deflate" } -- Add a few very long headers. This will trigger a '400 Bad Request' on -- non affected implementations. local long_header = "" for i=1, 4096 do long_header = long_header .. string.char(math.random(32, 126)) end headers["a"] = long_header headers["b"] = long_header headers["c"] = long_header headers["d"] = long_header headers["e"] = long_header headers["f"] = long_header syn_frame:set_name_value_pairs(headers) -- Set a huge number of Num/Value pairs, which, on a vulnerable -- implementation, will be used to allocate the initial list for parsing -- the headers. This will trigger a malloc error, which will result in an -- RST_STREAM frame being sent back to the client. syn_frame:set_num_name_value_pairs(4000000000) -- Send the frame local status, err local session = helper:new_session(host, port) status, err = session:open() if not status then return false end status, err = session:send_frame(syn_frame) if not status then return false end while true do local frames, err = session:receive_frames() if not frames then return false end for _,frame in ipairs(frames) do local frame_type = frame:get_type() if frame_type == "RST_STREAM" then return true elseif frame_type == "SYN_REPLY" then return false elseif frame_type == "GOAWAY" then return false end end end return false end action = function(host, port) local vuln_table = { title = "nginx SPDY memory corruption vulnerability (CVE-2014-0088).", state = vulns.STATE.NOT_VULN, risk_factor = "High", description = [[ The spdy implementation in nginx v1.5.10 is affected by a vulnerability which might allow an attacker to corrupt worker process memory by using, a specially crafted request, potentially resulting in arbitrary code execution (CVE-2014-0088). The problem affects nginx 1.5.10 on 32-bit platforms, compiled with the ngx_http_spdy_module module (which is not compiled by default), if the "spdy" option of the "listen" directive is used in a configuration file. ]], references = { 'http://nginx.org/en/security_advisories.html', 'http://mailman.nginx.org/pipermail/nginx-announce/2014/000132.html', 'http://nginx.org/en/security_advisories.html' } } local report = vulns.Report:new(SCRIPT_NAME, host, port) local vulnerable = check_vulnerability(host, port) if vulnerable then vuln_table.state = vulns.STATE.VULN end return report:make_output(vuln_table) end