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

Add output to http-default-accounts.nse if fingerprint not found #2077

Closed
l0nedigit opened this issue Jul 8, 2020 · 6 comments
Closed

Add output to http-default-accounts.nse if fingerprint not found #2077

l0nedigit opened this issue Jul 8, 2020 · 6 comments
Assignees
Labels

Comments

@l0nedigit
Copy link

@l0nedigit l0nedigit commented Jul 8, 2020

When running http-default-accounts.nse if a fingerprint is not matched during the setup_check function loop, add output to stdout and into the output file (nmap, gnmap, xml) that a fingerprint was not found. This would be more apparent to end users and allow easier methods to identify web hosts that do not have a fingerprint.

Script:
https://github.com/nmap/nmap/blob/master/scripts/http-default-accounts.nse

Example POC code:
(lines 416-446)

local fingerprint_found = nil

  for _, fingerprint in ipairs(fingerprints) do
    local target_check = fingerprint.target_check or default_target_check
    local credentials_found = false
    stdnse.debug(1, "Processing %s", fingerprint.name)
    for _, probe in ipairs(fingerprint.paths) do
      local result = results[pathmap[probe.path]]
      if result and not credentials_found then
        local path = basepath .. probe.path
        if target_check(host, port, path, result) then
          fingerprint_found = true
          local out, txtout = test_credentials(host, port, fingerprint, path)
          if out then
            output[fingerprint.name] = out
            table.insert(text_output, txtout)
            credentials_found = true
          end
        end
      end
    end
  end
  if not fingerprint_found then
    stdnse.debug(1, "Fingerprint not found")
    local txtout = "Fingerprint not found"
    table.insert(text_output,("%s"):format(stdnse.string_or_blank(txtout)))
  end
  if #text_output > 0 then
    return output, stdnse.format_output(true, text_output)
  end
end

This would output Fingerprint not found at the end of the for loop and also inside of an output file if specified. However, there may be a more elegant solution, was just a proof of concept to see how level of effort was.

Perhaps, like in XML, create a Fingerprint.name tag and if nil, it would be empty.

@nnposter nnposter self-assigned this Jul 8, 2020
@nnposter
Copy link

@nnposter nnposter commented Jul 8, 2020

Thank you for the ask; there is definitely merit to it.

There is a related shortcoming in the existing script in that it does not explicitly inform (at some debug level) that a fingerprint target check was matched, which can be useful to some users (although other scripts are meant to cover this). Right now this match can be only inferred by observing debug message "Processing (some fingerprint)" immediately followed by at least one "Trying login combo -> (some user):(some password)". If the fingerprint did not match then this "Trying login combo..." is absent.

As a result, we should perhaps approach your ask differently. The negative match is not something that the script should report by default because this could massively clutter the output, especially when scanning a large number of HTTP hosts/ports. The standard script behavior is to stay silent unless there is a positive find of whatever the given script is testing for.

I am inclined to implement two changes:

  1. Pushing maintenance debug messages, such as those concerned with fingerprint loading, to debug level 2. Leaving debug level 1 reserved for error messages and finds (either a target check match, which would be a new message, and a credential match).

  2. Adding a new script parameter, http-default-accounts.out=all, which will force output of all matched fingerprint targets even if none of the credentials matched. The XML output structure would not change but <table key="credentials"> would have no elements.

Normal output (no credentials found, http-default-accounts.out=all):

PORT   STATE SERVICE
80/tcp open  http
| http-default-accounts:
|   [Cacti] at /
|_  [Nagios] at /nagios/

XML output (no credentials found, http-default-accounts.out=all):

<table key="Cacti">
  <elem key="cpe">cpe:/a:cacti:cacti</elem>
  <elem key="path">/</elem>
  <table key="credentials">
  </table>
</table>
<table key="Nagios">
  <elem key="cpe">cpe:/a:nagios:nagios</elem>
  <elem key="path">/nagios/</elem>
  <table key="credentials">
  </table>
</table>

Your goal of reporting completely unrecognized targets is then represented by the lack of output. Would this help?

One item to keep in mind is that this output should not be perceived as true fingerprinting because in many cases, particularly with HTTP basic authentication, the target check cannot collect enough HTTP data to be reliable.

@nnposter nnposter changed the title [FEATURE] Add output to http-default-accounts.nse if fingerprint not found Add output to http-default-accounts.nse if fingerprint not found Jul 8, 2020
@l0nedigit
Copy link
Author

@l0nedigit l0nedigit commented Jul 9, 2020

@nnposter
Copy link

@nnposter nnposter commented Jul 12, 2020

Instead of implementing a special script parameter, I have opted to tie the additional output to Nmap verbosity:

$ nmap --script http-default-accounts -p 80 192.168.1.1
...
PORT   STATE SERVICE
80/tcp open  http

Now with -v:

$ nmap --script http-default-accounts -p 80 -v 192.168.1.1
...
PORT   STATE SERVICE
80/tcp open  http
| http-default-accounts:
|   [Cacti] at /
|     (no valid default credentials found)
|   [Nagios] at /nagios/
|_    (no valid default credentials found)

As outlined before, the XML output structure has remained unchanged but the list of credentials is empty:

<table key="Cacti">
  <elem key="cpe">cpe:/a:cacti:cacti</elem>
  <elem key="path">/</elem>
  <table key="credentials">
  </table>
</table>
<table key="Nagios">
  <elem key="cpe">cpe:/a:nagios:nagios</elem>
  <elem key="path">/nagios/</elem>
  <table key="credentials">
  </table>
</table>

Before committing any changes, please give this patch a spin a report back if it meets your needs.

@nnposter
Copy link

@nnposter nnposter commented Jul 21, 2020

The patch has been committed as r37965.

@nmap-bot nmap-bot closed this in c4f9e48 Jul 22, 2020
@cnotin
Copy link

@cnotin cnotin commented Aug 4, 2020

@nnposter just discovered your commit, and this is exactly what I wanted, so thank you very much!
Thanks @l0nedigit for raising this too!

@nnposter
Copy link

@nnposter nnposter commented Aug 5, 2020

You are welcome. I am glad that some people find it useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.