NMap NSE smb-enum-shares and smb-ls won't work with some open shares (NT_STATUS_WERR_INVALID_NAME) #266

Closed
JPvRiel opened this Issue Jan 5, 2016 · 11 comments

Comments

Projects
None yet
4 participants

JPvRiel commented Jan 5, 2016

Testing against an open, browsable share, smb-enum-shares bumps against NT_STATUS_WERR_INVALID_NAME verus a samba 4 server with anon access allowed.

nmap -PS445 -p445 --script=smb-os-discovery,smbv2-enabled,smb-enum-shares,smb-ls --script-args=ls.maxdepth=10 192.168.56.1

Starting Nmap 7.00 ( https://nmap.org ) at 2016-01-05 18:49 SAST
Nmap scan report for 192.168.56.1
Host is up (0.00082s latency).
PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb-enum-shares: 
|   account_used: <blank>
|   IPC$: 
|     Type: STYPE_IPC_HIDDEN
|     Comment: IPC Service (<hostname> windows file share service)
|     Users: 2
|     Max Users: <unlimited>
|     Path: C:\tmp
|     Anonymous access: READ/WRITE
|   OpenShare: 
|     warning: Couldn't get details for share: NT_STATUS_WERR_INVALID_NAME (srvsvc.netsharegetinfo)
|     Type: Not a file share
|_    Anonymous access: READ/WRITE
| smb-os-discovery: 
|   OS: Unix (Samba 4.1.17-Ubuntu)
|   Computer name: <hostname>
|   NetBIOS computer name: <hostname>
|   Domain name: 
|   FQDN: <hostname>
|_  System time: 2016-01-05T18:49:16+02:00
|_smbv2-enabled: Server supports SMBv2 protocol

In debug mode, the follwoing seemed to be relevant output

NSE: [smb-enum-shares 192.168.56.1] SMB: Invalid NTLM challenge message: unexpected signature.
NSE: [smb-enum-shares 192.168.56.1] SMB: WARNING: the server appears to be Unix; your mileage may vary.
NSE: [smb-enum-shares 192.168.56.1] SMB: Extended login to 192.168.56.1 as <hostname>\<blank> failed, but was given guest access (username may be wrong, or system may only allow guest)
NSE: [smb-enum-shares 192.168.56.1] SMB: Failed to get share info for OpenShare: NT_STATUS_WERR_INVALID_NAME (srvsvc.netsharegetinfo)
NSE: Finished smb-enum-shares against 192.168.56.1.

So I think smb-ls never gets going because smb-enum-shares doesn't properly find info about the open share It might be:

  • an unnecessary dependence on or problem with srvsvc.netsharegetinfo?
  • it shouldn't report Type: Not a file share given it's a valid file share both smbclient and windows can browse and use it by connecting with a null session to IPC$ (the ANONYMOUS LOGIN).

smbclient has no problems

$ smbclient -N -L 192.168.56.1
Anonymous login successful
Domain=[<domain>] OS=[Unix] Server=[Samba 4.1.17-Ubuntu]

    Sharename       Type      Comment
    ---------       ----      -------
    IPC$            IPC       IPC Service (<hostname> windows file share service)
    OpenShare       Disk      Read for all
...
$ smbclient -N \\\\192.168.56.1\\OpenShare -c ls
Anonymous login successful
Domain=[<domain>] OS=[Unix] Server=[Samba 4.1.17-Ubuntu]
  .                                   D        0  Tue Jan  5 18:07:31 2016
  ..                                  D        0  Tue Jan  5 17:38:52 2016
  Test                                D        0  Tue Jan  5 18:07:33 2016
  README.TXT                          N       20  Tue Jan  5 18:06:54 2016

        40301 blocks of size 8388608. 15439 blocks available

Windows 10 net command also works fine

>net view 192.168.56.1
Shared resources at 192.168.56.1

<hostname> windows file share service

Share name  Type  Used as  Comment

-------------------------------------------------------------------------------
OpenShare   Disk           Read for all
The command completed successfully.

With full debug -ddd, the following is noted

  • NetShareGetInfo() returned success
NSE: [smb-enum-shares M:24b71c0 192.168.56.1] MSRPC: Function call successful, 12 bytes of returned arguments
NSE: [smb-enum-shares M:24b71c0 192.168.56.1] MSRPC: NetShareGetInfo() returned successfully
NSE: [smb-enum-shares M:24b71c0 192.168.56.1] SMB: Sending SMB_COM_TREE_DISCONNECT

But looking at smb-enum-share.nse, the following logic in the source code gets triggered

if(type(share['details']) ~= 'table') then
      share_output['warning'] = string.format("Couldn't get details for share: %s", share['details'])
      -- A share of 'NT_STATUS_OBJECT_NAME_NOT_FOUND' indicates this isn't a fileshare
      if(share['user_can_write'] == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
        share_output["Type"] = "Not a file share"
      else
        table.insert(host.registry['smb_shares'], share.name)
      end

The commit to help smb-ls use smb-enum-shares is here: 4d0e7c9

And the hassles when trying to enumerate shares with might be related to MSRPC: NetShareGetInfo() which is at msrpc.lua

But at this point, I'm not familiar enough with SMB/CIFS to debug and understand how or why things break. Basically, if Windows and smbclient can list the share via the null session and then access it, there's no reason why nmap can't.

In passing, it also seems like nmap is incorrectly reporting anonymous write access to the test share

Anonymous access: READ/WRITE

For samba 4

$ net usershare info OpenShare
[OpenShare]
path=/home/<account>/Desktop/OpenShare
comment=Read for all
usershare_acl=Everyone:R,Unix User\<account>:F,
guest_ok=y

p-l- commented Jan 5, 2016

Hi,

Congrats on that nice catch!

Before commit 4d0e7c9, smb-ls had no way to discover the shares to browse automatically and needed to have a share passed as a parameter.

You can still use this behavior by specifying --script-args smb-ls.share=OpenShare (in your case). Does it work with this?

The bug, IMO, is in smb-enum-shares: it should not consider that OpenShare is "not a file share".

The heuristic "a share of NT_STATUS_OBJECT_NAME_NOT_FOUND indicates this isn't a fileshare" seems to be wrong, but it would be interesting to know why it is used and see if we can refine it.

JPvRiel commented Jan 26, 2016

For nmap 7.01, the smb-ls script fails an assertion in all three cases

  1. with or explicit credentials in smbdomain, smbuser and smbpass supplied in --script-args
  2. without credentials (try guest and anon/blank user)
  3. with smb-ls.share=OpenShare specified AND correct explicit credentials

Again, smbclient can enum the shares with anon user or an explicit user

Example full command (without debug)

nmap -PS445 -p445 --script=smb-enum-shares,smb-ls --script-args=ls.maxdepth=10,smbdomain=<DOMAIN>,smbuser=<USER>,smbpass='<PASSWORD>',smb-ls.share=PubShare <FQDN>

Starting Nmap 7.01 ( https://nmap.org ) at 2016-01-26 16:30 SAST
Nmap scan report for <FQDN> (<IP>)
Host is up (0.0026s latency).
PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb-enum-shares: 
|   account_used: <DOMAIN>\<USER>
|   ADMIN$: 
|     warning: Couldn't get details for share: NT_STATUS_WERR_ACCESS_DENIED (srvsvc.netsharegetinfo)
|     Anonymous access: <none>
|     Current user access: <none>
|   C$: 
|     warning: Couldn't get details for share: NT_STATUS_WERR_ACCESS_DENIED (srvsvc.netsharegetinfo)
|     Anonymous access: <none>
|     Current user access: <none>
|   D$: 
|     warning: Couldn't get details for share: NT_STATUS_WERR_ACCESS_DENIED (srvsvc.netsharegetinfo)
|     Anonymous access: <none>
|     Current user access: <none>
|   IPC$: 
|     warning: Couldn't get details for share: NT_STATUS_WERR_ACCESS_DENIED (srvsvc.netsharegetinfo)
|     Type: Not a file share
|     Anonymous access: READ
|     Current user access: READ/WRITE
|   PubShare: 
|     warning: Couldn't get details for share: NT_STATUS_WERR_ACCESS_DENIED (srvsvc.netsharegetinfo)
|     Anonymous access: READ
|_    Current user access: READ
|_smb-ls: ERROR: Script execution failed (use -d to debug)

Nmap done: 1 IP address (1 host up) scanned in 1.05 seconds

Debug gainst Samba 3

NSE: Starting smb-ls against <LINUX_IP>.
NSE: [smb-ls <LINUX_IP>] LM Password: 
NSE: [smb-ls <LINUX_IP>] SMB: Invalid NTLM challenge message: unexpected signature.
NSE: [smb-ls <LINUX_IP>] SMB: WARNING: the server appears to be Unix; your mileage may vary.
NSE: [smb-ls <LINUX_IP>] SMB: Extended login to <LINUX_IP> as <hostname>\guest failed, but was given guest access (username may be wrong, or system may only allow guest)
NSE: smb-ls against <LINUX_IP> threw an error!
/usr/bin/../share/nmap/nselib/tab.lua:52: assertion failed!
stack traceback:
    [C]: in function 'assert'
    /usr/bin/../share/nmap/nselib/tab.lua:52: in function 'add'
    /usr/bin/../share/nmap/nselib/ls.lua:217: in function 'add_file'
    /usr/bin/../share/nmap/scripts/smb-ls.nse:142: in function 'list_files'
    /usr/bin/../share/nmap/scripts/smb-ls.nse:204: in function </usr/bin/../share/nmap/scripts/smb-ls.nse:170>
    (...tail calls...)

Against Windows 2008

NSE: [smb-ls <WINDOWS_IP>] LM Password: 
NSE: [smb-ls <WINDOWS_IP>] SMB: Invalid NTLM challenge message: unexpected signature.
NSE: smb-ls against <hostname> (<WINDOWS_IP>) threw an error!
/usr/bin/../share/nmap/nselib/tab.lua:52: assertion failed!
stack traceback:
    [C]: in function 'assert'
    /usr/bin/../share/nmap/nselib/tab.lua:52: in function 'add'
    /usr/bin/../share/nmap/nselib/ls.lua:217: in function 'add_file'
    /usr/bin/../share/nmap/scripts/smb-ls.nse:142: in function 'list_files'
    /usr/bin/../share/nmap/scripts/smb-ls.nse:204: in function </usr/bin/../share/nmap/scripts/smb-ls.nse:170>
    (...tail calls...)

Just to note, NetBIOS over TCP is disabled for the windows server, but enabled and allowed in the linux samba 3 sever. Either way, same assertion errors for smb-ls result.

p-l- commented Jan 26, 2016

Can you apply the following patch, run again and post the output?

diff --git a/nselib/ls.lua b/nselib/ls.lua
index f1d116d..7c69ed4 100644
--- a/nselib/ls.lua
+++ b/nselib/ls.lua
@@ -214,6 +214,9 @@ function add_file(output, file)
   local curvol = output.curvol
   local files = curvol["files"]
   for i, info in ipairs(file) do
+    stdnse.debug1("ADD_FILES_1 %d", i)
+    stdnse.debug1("ADD_FILES_2 %s", type(file))
+    stdnse.debug1("ADD_FILES_3 %s", file)
     tab.add(files, i, info)
   end
   local size = get_size(file[curvol.hasperms and 4 or 1])

cldrn commented Jan 26, 2016

Thanks for the detailed reports. I've been looking into it and it seems we have several 'broken' things with the library right now. Hopefully soon we will fix all these issues.

@cldrn Any update on this issue? Should we be looking into it further?

cldrn commented Aug 19, 2016

I haven't had a chance to keep working on this but I will re take it this week.

JPvRiel commented Aug 19, 2016

Just a quick, somewhat arbitrary note, but perhaps useful in testing:

  • Seems modern versions of Windows don't play nice trying to setup anonymous / truly open shares. I did get it right, but only after hacking around with several windows security policy settings for SMB and null sessions.
  • Seems much easier to setup a null/anonymous share with Samba.

cldrn commented Aug 19, 2016

Do you remember what settings did you change? A friend was telling me about this and he couldn't get it to work (not sure how much time he spent on this).

JPvRiel commented Aug 21, 2016

@cldrn I'm afraid I can't recall the exact details, but have some old notes. It's hairy enough for me to denounce it as "black magic" when I eventually got null session file share enumeration working with Windows 10...

IIRC, fiddling with policies for ‘Accounts: Guest account status’, ‘Network access: Let Everyone permissions apply to anonymous users’, and ‘Network access: Restrict anonymous access to Named Pipes and Shares’ can be left alone with the more secure defaults if the ‘Shares that can be accessed anonymously’ policy is set… if the 'public' share endpoint is fully known in advance (i.e. don't need to discover share, just use it). BUT listing shares with a null session is where things get messy. In order to list shares, a null session must be allowed to connect to the '$IPC' services that enumerate the share info.

The default settings for Win Vista+ don’t allow the null session user (ANONYMOUS USER) to enumerate shares, so even if ANON access to a share is allowed, that share can’t be discovered (but can be accessed if known in advance).

For the anon user to enumerate shares, I think it needs anon access to the named pipe srvsvc, and you have to go to great lengths to allow this. Windows has two levels of security checks, and even if NULL Session/Anon User is explicitly allowed for that named pipe, it trips up on a second check…

  • Even when srvsvc is specified in ‘Network access: Named pipes that can be accessed anonymously’ = srvsvc
  • The ‘Network access: Let Everyone permissions apply to anonymous users’ = Enabled is needed to get past the second ‘integrity level’ security check set for security tokens.

I can share some resources I found helpful:

Many blog/forum posts confuse this issue and enable guest access with everyone permissions. That is some kind of authentication (e.g. guest account with blank password or a set password) versus anon access which can still use the ‘IPC$’ service, A.K.A. the ‘null session’ to connect and get info, such as OS version and shares available (if enumeration is allowed). Guest is more like a shared unprivileged account (which can have a password set) whereas anonymous is in fact blank/empty/null account and can never have a password set.

cldrn commented May 25, 2017

I have found some issues with the library not using fully qualified paths as share names. After fixing this, all scripts seem to work fine against modern Windows versions (I haven;t tested it against Samba yet)

Hopefully this patch solves your issues.

nmap-bot closed this in b0228a2 May 27, 2017

JPvRiel commented Jun 1, 2017

@cldrn, thanks - hope to retest this at some point in the near future. I eventually ended up using Nessus to do the windows file share security checks, but nice to see nmap might once more be an option here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment