Coming primarily from a UNIX background, I’ve been relatively ignorant of the internals of the Windows OS until this point, and what prompted this bit of research is the fact most the vulnerabilities exploited in my recent pen test were in some way SMB-related, and I should have determined beforehand exactly how those exploits worked.
How relevant this post is in the real world (with it being Server 2003) is debatable, but a handful of exploits for just two SMB vulnerabilities enabled us to gain access to NTDS.DIT, grab the password hashes for every account, perform administrative tasks and get a VNC connection from a client machine, all without being logged onto the domain. Another trick gives me control of a much larger network with four Domain Controllers running a later version of Windows Server. Unfortunately the specifics of why it happens aren’t very well documented.
Nessus Scan Results
A good point to start with is the Nessus scan against a machine running a default installation of Windows Server 2003, and the two critical vulnerabilities that were discovered:
* MS08-067: Microsoft Windows Server Service Crafted RPC Request Handling Remote Code Execution (958644) (uncredentialed check).
* MS09-001: Microsoft Windows SMB Vulnerabilities Remote Code Execution (958687) (uncredentialed check)
After spending the better part of a day interpreting the scan results (eliminating status messages from the genuine ‘Info’ vulnerabilities, consulting OSVDB, researching, etc. etc.), it turned out that eliminating just those two criticals also solves the vast majority of the other SMB-related vulnerabilities, and the pie chart below shows the degree to which this would reduce the ‘attack surface’. We can ignore the SSL and Mail vulnerabilities – they were intentional here.
As it turned out, both vulnerabilities could be dealt with by blocking ports 135 – 139 and 445 (incoming). This means shared files and resources could be accessed by all the machines within the network, but not accessed from outside the perimeter firewall.
SMB in More Detail
That’s the basic stuff, but I still wanted to understand why this was the case. SMB is a protocol for sharing files, resources and other things on a network between Windows machines, and this alone makes it seem the ideal thing for an attacker to focus on.
Essentially SMB works either at the application layer or alongside it, that is it works above other things like NetBIOS, TCP, etc. In this case, we actually know it was using NetBIOS (which itself is an API) over TCP.
SMB also has a component for sharing files, and another for Inter-Process Communication and Remote Procedure Calls over the network. The latter can enable certain malicious code to perform actions on the server from across the network. In other words, ‘remote code execution’.
So, to summarise, it would mean SMB is making NetBIOS API function calls, and those function calls are being encapsulated as TCP packets and carried over the network, so NetBIOS tells the server which resource the SMB traffic is for.
It means that someone theoretically could also do this from outside the network, if the server’s IP address and NetBIOS name were known, which is why it’s recommended that TCP ports 135-139 and 445 (inbound) are closed.
SMB, Authentication and NTLM
Client machines running Microsoft Windows authenticate each other over the NT LAN Manager (NTLM) protocol, which involves the client sending a hash of its credentials to the server. The client and server generated hashes are compared to determine whether they match.
If I remember correctly, SMBv1 had a flaw that allowed a malicious process to authenticate itself as a server through a ‘man-in-the-middle reflection‘ that returned an acceptable hash value. It’s also relevant here because our Zenmap scan showed our server installation only supported SMBv1.
Now we know that TCP and NetBIOS are carrying SMB traffic over the network, but how exactly are the exploits using this?
A cursory search gave me a generic example of an exploit that causes a Windows 7/Vista system to crash, and it turns out the principle’s almost the same as that behind the payload crafting thing I posted about the other week. Laurent Gaffie’s Python example goes something like:
host = "IP_ADDR", 445
buff = (
s = socket()
So, what’s happening here is the program’s dumping the shellcode in its buffer to a network socket (which I described here as being merely a virtual file), and the contents of that socket are sent to a given IP address on TCP port 445. This is (I believe) automatically read as an SMB request, because of the port number.
Well, that’s my intoduction to SMB. There’ll probably be more here on this in future.