In our original release post about smbls, we talked about some use-cases and examples for SMB share scanning tool. Since then, we’ve been continually updating it with minor updates, in addition to a large overhaul with version 2. With that, smbls is able to gather and format a significant amount of useful data from scans.

To recap, smbls is a free and open source script that can connect to many Windows hosts over the SMB protocol in order to verify credentials, gather host information, and retrieve share information. At ivision, we use it as part of our internal pentests, but we also encourage defenders to use it to regularly scan their own networks.

Since the initial release, we’ve added a bunch of new features. Here are the top 5:

One: The most obvious UX change is the addition of smblsreport. It is a standalone script that parses the JSON data files generated by smbls and can print flexible reports. There are three parameters: the report type (hosts or shares), a list of filters to select which entries to print, and a list of extra data fields to print for each entry. So for example you can create a shares report, select only shares which were readable, and print out the share remark and a listing of the top-level contents. The output is tab-separated values (TSV), so you can import the output into a spreadsheet or pipe it into some other utility to further process it (mlr is a good choice). Of course, you can still pull data out of the JSON files if that fits your workflow better.

Two: The most interesting change to me was the greatly expanded permission data gathered. For technical details, see the project README on GitHub, but to summarize briefly: to access a file share through SMB, the server checks multiple sets of access controls. One of those is share permissions, which can limit access to the share regardless of filesystem permissions. smbls now pulls that access control out of the SMB handshake, which required reimplementing a small part of protocol to get more low-level control. The underlying file system also has permission data, called a discretionary access control list (DACL). Clients can request this data from the SMB protocol, which smbls now does for the roots of share directories. DACLs can be reviewed to determine which users or groups have access to certain file objects.

Three: smbls now also has functionality to verify write access by attempting to create and delete an object on shares. It is off by default but can be turned on with the -w flag.

Four: Another off-by-default feature is the ability to gather the contents of the root directory of shares (-l). This can make it extremely quick to glance at shares and determine if there’s anything on them worth further investigation.

Five: Last on the list is the addition of metadata to the JSON data files. These record what credentials were used and when the scan started and stopped.

Here is an example terminal transcript:

$ smbls -c example/user:password -o example1.json hosts.txt -wl
0/10 scanned 10.0.0.1 with example_user, error: conn
1/10 scanned 10.0.0.3 with example_user,
2/10 scanned 10.0.0.7 with example_user, ADMIN
...
$ smblsreport -f example1.json hosts -s admin
10.0.0.7	WORKSTATION1
...
$ smblsreport -f example1.json hosts -s noerror -p os,signing
10.0.0.3	SERVER1	Windows 10.0 Build 14393	True
10.0.0.7	WORKSTATION1	Windows 10.0 Build 14393	False
...
$ smblsreport -f example1.json shares -s readable -p writable,contents
10.0.0.3	SERVER1	'IPC$'	True	[]
10.0.0.3	SERVER1	Public	False	['Data', 'Images']
10.0.0.7	WORKSTATION1	'ADMIN$'	True	[...]
10.0.0.7	WORKSTATION1	'C$'	True	['$Recycle.Bin', 'Documents and Settings', 'pagefile.sys', 'PerfLogs', 'Program Files', 'Program Files (x86)', 'ProgramData', 'Recovery', 'System Volume Information', 'Users', 'Windows']
10.0.0.7	WORKSTATION1	'IPC$'	True	[]
...

In that example, a scan is run against a host list with the user account example/user and with -wl flags, which tests for writing and gathers file listings. After that, reports are generated from the JSON data file created by the scan. The first report is a list of hosts where the scanning user was admin. The second report is from hosts that were successfully authenticated against and shows the OS information and whether client SMB signing is required by the server. The final report is a list of shares where the scanning user was able to read their contents, whether the user was also able to write to the share, and a list of the file objects in the root directory of the share.

Here is another example:

$ cat credfile
example/user:password
localhost/Administrator#aad3b435b51404eeaad3b435b51404ee:0123456789abcdef0123456789abcdef
$ echo 10.0.0.3 | smbls -C credfile -O example2/ -wl -
0/1 scanned 10.0.0.3 with example_user,
0/1 scanned 10.0.0.3 with localhost_Administrator, ADMIN
$ ls example2/
example_user.json  localhost_Administrator.json
$ smblsreport -f example2/localhost_Administrator.json shares -s writable -p dacl
version 2.1.0
version_tuple [2, 1, 0]
start_time 2024-04-23T20:06:47+00:00
end_time 2024-04-23T20:06:47+00:00
args Namespace(creds=None, creds_file='credfile', out_file=None, out_dir='test2/', targets=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='utf-8'>, threads=32, write=True, list=True, list_ipc=False, auth_only=False)
creds {'domain': 'localhost', 'username': 'Administrator', 'lmhash': 'aad3b435b51404eeaad3b435b51404ee', 'nthash': '0123456789abcdef0123456789abcdef'}
$ smblsreport -f example2/localhost_Administrator.json shares -s writable -p dacl
10.0.0.3	SERVER1	'ADMIN$'	[...]
10.0.0.3	SERVER1	'C$'	['ALLOWED,System (or LocalSystem),GENERIC_ALL', 'ALLOWED,Administrators,GENERIC_ALL', 'ALLOWED,Users,GENERIC_EXECUTE|GENERIC_READ', 'ALLOWED,Users,FILE_APPEND_DATA', 'ALLOWED,Users,FILE_WRITE_DATA', 'ALLOWED,Creator Owner ID,GENERIC_ALL']
10.0.0.3	SERVER1	'IPC$'	-
10.0.0.3	SERVER1	Public	['ALLOWED,System (or LocalSystem),GENERIC_ALL', 'ALLOWED,Administrators,GENERIC_ALL', 'ALLOWED,Users,GENERIC_EXECUTE|GENERIC_READ', 'ALLOWED,Users,FILE_APPEND_DATA', 'ALLOWED,Users,FILE_WRITE_DATA', 'ALLOWED,Creator Owner ID,GENERIC_ALL']

In this example, a scan is run against a single host with multiple users, one of which is specified with its NTLM password hash instead of its plaintext password. This generated one JSON data file for each set of credentials. Metadata for the scan is printed, which includes the credentials used and timing information. Then a report is generated for the admin user which retrieves the DACL (permission data) for all shares where it has write access. IPC$ is a special share, so by default its contents aren’t listed, but they can be with -i.

You can grab a copy of the source code from GitHub or install it with pip install smbls (add -U to upgrade). As always, please open an issue with any feedback.