Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Better output indentation from script ssh-run #1637

Closed
nnposter opened this issue Jun 15, 2019 · 5 comments

Comments

Projects
None yet
2 participants
@nnposter
Copy link

commented Jun 15, 2019

Output example from the current version of script ssh-run, executing lsb_release -a:

PORT   STATE SERVICE
22/tcp open  ssh
| ssh-run.nse:
|   output:
|     No LSB modules are available.\x0D
| Distributor ID:       Ubuntu\x0D
| Description:  Ubuntu 16.04.6 LTS\x0D
| Release:      16.04\x0D
|_Codename:     xenial\x0D

Note the inconsistent indentation of the output and the trailing CR characters.

A possibly better output would be:

PORT   STATE SERVICE
22/tcp open  ssh
| ssh-run:
|   output:
|     No LSB modules are available.
|     Distributor ID:   Ubuntu
|     Description:      Ubuntu 16.04.6 LTS
|     Release:  16.04
|_    Codename: xenial

The following patch implements the change:

--- ssh-run.nse.old     2019-06-14 20:17:33.114635000 -0600
+++ ssh-run.nse 2019-06-14 20:27:24.848635000 -0600
@@ -1,5 +1,6 @@
 local stdnse = require "stdnse"
 local shortport = require "shortport"
+local stringaux = require "stringaux"
 local table = require "table"
 local libssh2_util = require "libssh2-utility"

@@ -77,7 +78,6 @@
   local output, err_output = conn:run_remote(cmd)
   stdnse.verbose("Output of command: " .. output)
   local result = stdnse.output_table()
-  result.output = {}
-  table.insert(result.output, output)
+  result.output = stringaux.strsplit("\r?\n", output:gsub("\r?\n$", ""))
   return result
 end

One side effect is that the XML output is now broken down by individual lines:

<table key="output">
<elem>No LSB modules are available.</elem>
<elem>Distributor ID:&#x9;Ubuntu</elem>
<elem>Description:&#x9;Ubuntu 16.04.6 LTS</elem>
<elem>Release:&#x9;16.04</elem>
<elem>Codename:&#x9;xenial</elem>
</table>

The same output was a one-liner before:

<table key="output">
<elem>No LSB modules are available.\x0D&#xa;Distributor ID:&#x9;Ubuntu\x0D&#xa;Description:&#x9;Ubuntu 16.04.6 LTS\x0D&#xa;Release:&#x9;16.04\x0D&#xa;Codename:&#x9;xenial\x0D&#xa;</elem>
</table>

Opinions?

@dmiller-nmap

This comment has been minimized.

Copy link

commented Jun 17, 2019

My preference would be to have the XML contain the exact bytes returned by the server (encoded as necessary), and only modify the screen output (unindent or indent, remove control characters, etc.). This can be done by returning structured and screen output separately, or by using a __tostring metamethod on the program output table.

@nnposter

This comment has been minimized.

Copy link
Author

commented Jun 17, 2019

This was my original thought as well, until I realized that the current version is already modifying the XML output. Note the backslash-escaped CR characters vs the preserved LFs.

@nnposter nnposter closed this Jun 17, 2019

@nnposter

This comment has been minimized.

Copy link
Author

commented Jun 24, 2019

Here is a more comprehensive update:

  • Cleans up the documentation
    • Simplifies @usage by removing unnecessary options
    • Updates @output
    • Adds @xmloutput
  • Attempts to treat command output as line-based when composing screen output
    • Interprets CR/LF as line breaks
    • Replaces tabs (HT) with the right amount of space to preserve output alignment
    • Strips off all other control characters
    • Properly indents the lines
  • Does not try to treat command output as line-based when populating XML output (as requested above)
    • The entire command output is a single <elem>
    • Does not try to work around a NSE bug/feature that causes backslash-escaping of CR's
--- a/scripts/ssh-run.nse
+++ b/scripts/ssh-run.nse
@@ -1,5 +1,6 @@
 local stdnse = require "stdnse"
 local shortport = require "shortport"
+local stringaux = require "stringaux"
 local table = require "table"
 local libssh2_util = require "libssh2-utility"
 
@@ -8,22 +9,25 @@
 ]]
 
 ---
--- @usage nmap -p 22 -v -d --script=ssh-run --datadir=./ \
+-- @usage nmap -p 22 --script=ssh-run \
 -- --script-args="ssh-run.cmd=ls -l /, ssh-run.username=myusername, ssh-run.password=mypassword" <target>
 --
 -- @output
--- 22/tcp open  ssh     syn-ack 0
--- | run-remote:
+-- 22/tcp open  ssh
+-- | ssh-run:
 -- |   output:
--- |     total 124
--- | drwxr-xr-x   2 root       root        4096 Jun 23 09:34 bin
--- | drwxr-xr-x   3 root       root        4096 Jun 19 12:42 boot
--- | drwxr-xr-x   2 root       root        4096 Feb  6  2013 cdrom
--- | drwxr-xr-x  16 root       root        4340 Jul 17 13:37 dev
--- | drwxr-xr-x 162 root       root       12288 Jul 20 12:10 etc
--- | drwxr-xr-x  15 root       root        4096 Jun 23 15:20 home
--- | ...
--- |_drwxr-xr-x  14 root       root        4096 Jun  6 14:58 var
+-- |     total 91
+-- |     drwxr-xr-x   2 root root  4096 Jun  5 11:56 bin
+-- |     drwxr-xr-x   4 root root  3072 Jun  5 12:42 boot
+-- |     drwxrwxr-x   2 root root  4096 Jun 22  2017 cdrom
+-- |     drwxr-xr-x  20 root root  4060 Jun 23 10:26 dev
+-- |     drwxr-xr-x 127 root root 12288 Jun  5 11:56 etc
+-- |     drwxr-xr-x   3 root root  4096 Jun 22  2017 home
+-- ....
+-- |_    drwxr-xr-x  13 root root  4096 Jul 20  2016 var
+--
+-- @xmloutput
+-- <elem key="output">total 91\x0D&#xa;drwxr-xr-x   2 root root  4096 Jun  5 11:56 bin\x0D&#xa;drwxr-xr-x   4 root root  3072 Jun  5 12:42 boot\x0D&#xa;drwxrwxr-x   2 root root  4096 Jun 22  2017 cdrom\x0D&#xa;drwxr-xr-x  20 root root  4060 Jun 23 10:26 dev\x0D&#xa;drwxr-xr-x 127 root root 12288 Jun  5 11:56 etc\x0D&#xa;drwxr-xr-x   3 root root  4096 Jun 22  2017 home\x0D&#xa;....\x0D&#xa;drwxr-xr-x  13 root root  4096 Jul 20  2016 var\x0D&#xa;</elem>
 --
 -- @args ssh-run.username    Username to authenticate as
 -- @args ssh-run.password    Password to use if using password authentication
@@ -47,6 +51,14 @@
 local privatekey = stdnse.get_script_args 'ssh-run.privatekey'
 local passphrase = stdnse.get_script_args 'ssh-run.passphrase'
 
+local function remove_tabs (str, tabsize)
+tabsize = tabsize or 8
+local out = str:gsub("(.-)\t", function (s)
+                                 return s .. (" "):rep(tabsize - #s % tabsize)
+                               end)
+  return out
+end
+
 function action (host, port)
   local conn = libssh2_util.SSHConnection:new()
   if not conn:connect(host, port) then
@@ -76,8 +88,16 @@
   stdnse.verbose("Running command: " .. cmd)
   local output, err_output = conn:run_remote(cmd)
   stdnse.verbose("Output of command: " .. output)
-  local result = stdnse.output_table()
-  result.output = {}
-  table.insert(result.output, output)
-  return result
+
+  local out = stdnse.output_table()
+  out.output = output
+
+  local txtout = {}
+  for _, line in ipairs(stringaux.strsplit("\r?\n", output:gsub("\r?\n$", ""))) do
+    local str = line:gsub("[^\t\x20-\x7f]", "")
+    table.insert(txtout, remove_tabs(str))
+  end
+  txtout.name = "output:"
+
+  return out, stdnse.format_output(true, {txtout})
 end

@nnposter nnposter reopened this Jun 24, 2019

@nnposter nnposter self-assigned this Jun 26, 2019

@nnposter

This comment has been minimized.

Copy link
Author

commented Jun 30, 2019

The fix for backslash-escaping of CRs in XML output is proposed in #1648.

@nnposter

This comment has been minimized.

Copy link
Author

commented Jun 30, 2019

The code will be committed on or after July 15 unless concerns are raised.

@nmap-bot nmap-bot closed this in ddcbf14 Jul 21, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.