1local stdnse = require "stdnse" 2local shortport = require "shortport" 3local stringaux = require "stringaux" 4local table = require "table" 5local libssh2_util = require "libssh2-utility" 6 7description = [[ 8Runs remote command on ssh server and returns command output. 9]] 10 11--- 12-- @usage nmap -p 22 --script=ssh-run \ 13-- --script-args="ssh-run.cmd=ls -l /, ssh-run.username=myusername, ssh-run.password=mypassword" <target> 14-- 15-- @output 16-- 22/tcp open ssh 17-- | ssh-run: 18-- | output: 19-- | total 91 20-- | drwxr-xr-x 2 root root 4096 Jun 5 11:56 bin 21-- | drwxr-xr-x 4 root root 3072 Jun 5 12:42 boot 22-- | drwxrwxr-x 2 root root 4096 Jun 22 2017 cdrom 23-- | drwxr-xr-x 20 root root 4060 Jun 23 10:26 dev 24-- | drwxr-xr-x 127 root root 12288 Jun 5 11:56 etc 25-- | drwxr-xr-x 3 root root 4096 Jun 22 2017 home 26-- .... 27-- |_ drwxr-xr-x 13 root root 4096 Jul 20 2016 var 28-- 29-- @xmloutput 30-- <elem key="output">total 91\x0D
drwxr-xr-x 2 root root 4096 Jun 5 11:56 bin\x0D
drwxr-xr-x 4 root root 3072 Jun 5 12:42 boot\x0D
drwxrwxr-x 2 root root 4096 Jun 22 2017 cdrom\x0D
drwxr-xr-x 20 root root 4060 Jun 23 10:26 dev\x0D
drwxr-xr-x 127 root root 12288 Jun 5 11:56 etc\x0D
drwxr-xr-x 3 root root 4096 Jun 22 2017 home\x0D
....\x0D
drwxr-xr-x 13 root root 4096 Jul 20 2016 var\x0D
</elem> 31-- 32-- @args ssh-run.username Username to authenticate as 33-- @args ssh-run.password Password to use if using password authentication 34-- @args ssh-run.privatekey Privatekeyfile to use if using publickey authentication 35-- @args ssh-run.passphrase Passphrase for privatekey if using publickey authentication 36-- @args ssh-run.cmd Command to run on remote server 37 38 39author = "Devin Bjelland" 40license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 41 42categories = { 43 'intrusive', 44} 45 46portrule = shortport.ssh 47 48local username = stdnse.get_script_args 'ssh-run.username' 49local cmd = stdnse.get_script_args 'ssh-run.cmd' 50local password = stdnse.get_script_args 'ssh-run.password' 51local privatekey = stdnse.get_script_args 'ssh-run.privatekey' 52local passphrase = stdnse.get_script_args 'ssh-run.passphrase' 53 54local function remove_tabs (str, tabsize) 55tabsize = tabsize or 8 56local out = str:gsub("(.-)\t", function (s) 57 return s .. (" "):rep(tabsize - #s % tabsize) 58 end) 59 return out 60end 61 62function action (host, port) 63 local conn = libssh2_util.SSHConnection:new() 64 if not conn:connect(host, port) then 65 return "Failed to connect to ssh server" 66 end 67 if username and password and cmd then 68 if not conn:password_auth(username, password) then 69 conn:disconnect() 70 stdnse.verbose "Failed to authenticate" 71 return "Authentication Failed" 72 else 73 stdnse.verbose "Authenticated" 74 end 75 elseif username and privatekey and cmd then 76 if not conn:publickey_auth(username, privatekey, passphrase) then 77 conn:disconnect() 78 stdnse.verbose "Failed to authenticate" 79 return "Authentication Failed" 80 else 81 stdnse.verbose "Authenticated" 82 end 83 84 else 85 stdnse.verbose "Failed to specify credentials and command to run." 86 return "Failed to specify credentials and command to run." 87 end 88 stdnse.verbose("Running command: " .. cmd) 89 local output, err_output = conn:run_remote(cmd) 90 stdnse.verbose("Output of command: " .. output) 91 92 local out = stdnse.output_table() 93 out.output = output 94 95 local txtout = {} 96 for _, line in ipairs(stringaux.strsplit("\r?\n", output:gsub("\r?\n$", ""))) do 97 local str = line:gsub("[^\t\x20-\x7f]", "") 98 table.insert(txtout, remove_tabs(str)) 99 end 100 txtout.name = "output:" 101 102 return out, stdnse.format_output(true, {txtout}) 103end 104