SMB Protocol, Versions, And Badlock
Thursday 31st March, 2016 16:53
With a patch and details being disclosed in the next couple of weeks for the Badlock bug, and a recent query from a friend about unauthenticated SMB requests, I thought it'd be useful to collate my knowledge of SMB.
There were subtle differences between SMB and Samba, with Samba reporting version numbers that were lower than the OS version returned by Windows hosts in an attempt to avoid winning elections; but for file sharing it essentially behaved the same. Versions before Samba 3.5 only supported SMB 1, and could only be domain members (not domain controllers).
Microsoft introduced SMB 2 with Windows Vista. Although this was another proprietary protocol, the specification was published to allow other systems to interoperate, making it easier for Samba to develop support (although it still took them years). The first release with experimental support for SMB 2 was Samba 3.5, with full support as of Samba 3.6. With lots of users still clinging onto Windows XP, and/or hating Vista's UAC and huge memory requirements, I suspect very few people were that concerned.
SMB 2 offered several major improvements over SMB 1 such as:
SMB 2 allows clients to build a pipeline of requests instead of waiting for a response before sending the next request, which improves performance using a high latency network. It uses a credit based flow control, allowing the server to control a client's behaviour. The server starts with a small number of credits and scales up as needed to better utilize available bandwidth.
The reduced complexity in the command set for the SMB 2 protocol was accomplished by allowing an arbitrary set of commands to be compounded in a single request, allowing it to mimic SMB 1 without the complexity of a larger command set (e.g. the RENAME command can be replaced with three compounded SMB 2 commands). These compounded commands can even be unrelated. This improves performance due to the reduced number of network round trips.
There are apparently four types of opportunistic locks:
Batch Locks
To mitigate performance issues associated with repeatedly opening and closing a file in a short period of time, a client may ask for an Oplock of type "batch". The client delays sending the close request, and if a subsequent open request is given, the two requests cancel each other.
Exclusive Locks (SMB 2 only)
If a file is only opened in "shared mode" from an SMB server, the client receives an exclusive Oplock from the server. The client can safely assume that it is the only process with access to the file, allowing the client to cache all changes before committing them to the server, which improves performance. If another client tries to open the same file, the server sends a "break" request to the client which invalidates the exclusive lock. The client then flushes all changes to the file.
Level 2 Oplocks
After a client has relinquished its exclusive Oplock, to allow another client to have write/read access, the original client may then receive a "Level 2 Oplock" from the server. This allows the caching of read requests, but excludes write caching.
Filter Locks
A filter opportunistic lock locks a file so that it cannot be opened for either write or delete access. All clients must be able to share the file. Filter locks allow applications to perform nonintrusive filtering operations on file data (for example, a compiler opening source code or a cataloging program). A filter opportunistic lock differs from a level 2 opportunistic lock in that it allows open operations for reading to occur without sharing-mode violations in the time span between your application's opening the file and receiving the lock.
An Oplock is broken in different ways, depending on whether you're using SMB 1 or SMB 2:
To disable Oplocks on a Windows client:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MRXSmb\Parameters
OplocksDisabled = 1
To disable Oplocks on a Windows server:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters
EnableOplocks = 0
You cannot turn off opportunistic locking for SMB 2.
Unfortunately, SMB 2 also had a pretty nasty security flaw that was addressed in MS09-050. This was the SMBv2 Negotiation Vulnerability (CVE-2009-3103). Public exploit code existed, but the original proof-of-concept only resulted in a denial of service. In later weeks and months, this would eventually become a fairly reliable exploit.
I'm fairly sure I read on an old Microsoft blog that SMB 2.0.2 will fall back to SMB 1 if an older version of SMB 2 (i.e. 2.0.1) is negotiated. This is backed up by Microsoft's latest documents, which state that SMB 2 must have certain SMB 2 header values. For example, the DialectRevision must be set to 0x0202 and the dialect string must be set to "SMB 2.002" in order to negotiate support for SMB 2.0.2.
Just like how Windows 7 is actually version 6.1 behind the scenes, SMB 3.0 was originally developed as SMB 2.2 and was rebranded as SMB 3.0 when Windows 8 and Windows Server 2012 were released. Windows 10 and Server 2016 currently use SMB 3.1.1; I wouldn't expect to see SMB 4.0 anytime soon.
If the SMB server does not implement the SMB 2.1 or 3.x dialect family, it follows the old 2.0.2 negotiation process mentioned above. Microsoft produced a nice diagram in their SMB 2 documentation to show this negotiation:
SMB 2.1 is essentially the same as SMB 2.0, but there are some minor performance enhancements and a new opportunistic locking mechanism. This "client Oplock leasing model" can improve performance by controlling caching of network files by the client. The primary types of leases available are:
SMB 3.1.1 was introduced in Windows 10, and will be used in Windows Server 2016. It makes secure negotiation mandatory when connecting to clients using SMB 2.x and higher (it could be disabled in older versions because "some third-party implementations of SMB did not correctly perform this negotiation", which probably means Samba's implementation?), and adds optional support for AES-128-GCM encryption (and signing with AES-CMAC). It turns out that AES-128-GCM performs better in most modern processors, and can double the speed of large file transfers.
However, it's been suggested that you can get this information from SMB 2 if you send a session setup request using NTLMSSP (NTLMSSP_Negotiate). When the server responds with an NTLMSSP_Challenge the packet will includes information such as the OS, DNS, Domain, time. Hopefully Nmap will have better results on newer systems once the script has been updated.
To disable SMB 1 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb20/nsi
sc.exe config mrxsmb10 start= disabled
To enable SMB 1 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb10/mrxsmb20/nsi
sc.exe config mrxsmb10 start= auto
To disable SMB 2 and SMB 3 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb10/nsi
sc.exe config mrxsmb20 start= disabled
To enable SMB 2 and SMB 3 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb10/mrxsmb20/nsi
sc.exe config mrxsmb20 start= auto
PS C:\> dir \\localhost\c$
PS C:\> gsmbc -ServerName localhost
The Dialect column will reveal the version that was negotiated, which is 3.1.1 on my Windows 10 host.
You can also enable auditing of SMB 1 traffic using PowerShell, to create events if clients are still using SMB 1.
To enable auditing of SMB 1 traffic, use the cmdlet:
Set-SmbServerConfiguration –AuditSmb1Access $true
To view the SMB 1 events, use the cmdlet:
Get-WinEvent -LogName Microsoft-Windows-SMBServer/Audit
You can also uninstall SMB 1 on modern versions of Windows (that support SMB 3.0.2 or higher?) using the cmdlet:
Remove-WindowsFeature FS-SMB1
It's a real anti-climax. I thought, given the hype and its name, it might be related to the LockFile and/or LockFileEx functions that lock a specified range of bytes in a file. According to Microsoft's own documentation, the range "may extend beyond the current end of the file". I thought that Badlock's use of the Heartbleed design on their site might be a clue that it was a similar issue where an attacker requests a bad range, resulting in a buffer over-read. I wondered if this range was copied into (kernel) memory on the server and the range exceeds the actual file size (or can be used to access arbitrary memory) then could it return kernel data? Or could it allow arbitrary kernel memory to be overwritten when flushing data, e.g. when the lock is broken? It turns out it wasn't any of that.
This isn't the first time that someone may be able to gain privileged access on hosts due to a vulnerability in SMB, but this isn't the most exciting one either. Older versions of Samba allowed anonymous users to gain root access through an error in Samba's RPC; and as mentioned above Windows Vista had a nasty vulnerability that allowed unauthenticated users to gain SYSTEM privileges on a host. This is the first time that someone's given the vulnerability a decent name and logo, hence the publicity.
With most organisations using Windows Update (or WSUS, or other patch management software) to regularly deploy security fixes, I suspect most Windows users will be protected within a matter of hours or days.
SMB
The original SMB protocol was introduced a long, long time ago by Microsoft. Their original implementation for Windows NT 4.0 is actually called CIFS, but to keep things simple I will call it all SMB (or SMB 1). This was a proprietary protocol, but the Samba team created an implementation of SMB for UNIX, and it's now very well supported on Linux and BSD. SMB was originally designed to run on top of the NetBIOS/NetBEUI API (NBF, NetBIOS over IPX/SPX, or NBT). Since Windows 2000, SMB uses "direct host SMB" running over TCP port 445 rather than TCP port 139.There were subtle differences between SMB and Samba, with Samba reporting version numbers that were lower than the OS version returned by Windows hosts in an attempt to avoid winning elections; but for file sharing it essentially behaved the same. Versions before Samba 3.5 only supported SMB 1, and could only be domain members (not domain controllers).
SMB 2
When people talk about SMB 2 they are probably talking about SMB 2.x and 3.x. Also, versions of SMB 2 before 2.0.2 are already obsolete!Microsoft introduced SMB 2 with Windows Vista. Although this was another proprietary protocol, the specification was published to allow other systems to interoperate, making it easier for Samba to develop support (although it still took them years). The first release with experimental support for SMB 2 was Samba 3.5, with full support as of Samba 3.6. With lots of users still clinging onto Windows XP, and/or hating Vista's UAC and huge memory requirements, I suspect very few people were that concerned.
SMB 2 offered several major improvements over SMB 1 such as:
- Reduced complexity - from over 100 commands and subcommands to just 19
- Request compounding - allows for sending multiple SMB 2 requests as a single network request
- Larger reads and writes - making better use of faster networks, even with high latency
- Caching of folder and file properties - clients keep local copies of folders and files
- Durable handles - allow for connection to transparently reconnect to the server if there is a temporary disconnection
- Improved message signing - HMAC SHA-256 replaces MD5 as hashing algorithm
- Improved scalability for file sharing - number of users, shares, and open files per server greatly increased
- Support for symbolic links
- Client oplock leasing model - limits the data transferred between the client and server, improving performance on high-latency networks and increasing SMB server scalability
- Large MTU support - for better use of 10GB Ethernet connections
- Improved energy efficiency - clients that have open files to a server can sleep
- Better support for NAT - VC count was removed)
SMB 2 allows clients to build a pipeline of requests instead of waiting for a response before sending the next request, which improves performance using a high latency network. It uses a credit based flow control, allowing the server to control a client's behaviour. The server starts with a small number of credits and scales up as needed to better utilize available bandwidth.
The reduced complexity in the command set for the SMB 2 protocol was accomplished by allowing an arbitrary set of commands to be compounded in a single request, allowing it to mimic SMB 1 without the complexity of a larger command set (e.g. the RENAME command can be replaced with three compounded SMB 2 commands). These compounded commands can even be unrelated. This improves performance due to the reduced number of network round trips.
There are apparently four types of opportunistic locks:
Batch Locks
To mitigate performance issues associated with repeatedly opening and closing a file in a short period of time, a client may ask for an Oplock of type "batch". The client delays sending the close request, and if a subsequent open request is given, the two requests cancel each other.
Exclusive Locks (SMB 2 only)
If a file is only opened in "shared mode" from an SMB server, the client receives an exclusive Oplock from the server. The client can safely assume that it is the only process with access to the file, allowing the client to cache all changes before committing them to the server, which improves performance. If another client tries to open the same file, the server sends a "break" request to the client which invalidates the exclusive lock. The client then flushes all changes to the file.
Level 2 Oplocks
After a client has relinquished its exclusive Oplock, to allow another client to have write/read access, the original client may then receive a "Level 2 Oplock" from the server. This allows the caching of read requests, but excludes write caching.
Filter Locks
A filter opportunistic lock locks a file so that it cannot be opened for either write or delete access. All clients must be able to share the file. Filter locks allow applications to perform nonintrusive filtering operations on file data (for example, a compiler opening source code or a cataloging program). A filter opportunistic lock differs from a level 2 opportunistic lock in that it allows open operations for reading to occur without sharing-mode violations in the time span between your application's opening the file and receiving the lock.
An Oplock is broken in different ways, depending on whether you're using SMB 1 or SMB 2:
- For SMB, the server sends an Oplock break to the client using SMB_LOCK_ANDX. The LockType field is the level that the Oplock is broken into.
- For SMB 2, there is a specific command (SMB2_OPLOCK_BREAK,0x12) used to send the Oplock break notification to the client.
To disable Oplocks on a Windows client:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MRXSmb\Parameters
OplocksDisabled = 1
To disable Oplocks on a Windows server:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters
EnableOplocks = 0
You cannot turn off opportunistic locking for SMB 2.
Unfortunately, SMB 2 also had a pretty nasty security flaw that was addressed in MS09-050. This was the SMBv2 Negotiation Vulnerability (CVE-2009-3103). Public exploit code existed, but the original proof-of-concept only resulted in a denial of service. In later weeks and months, this would eventually become a fairly reliable exploit.
I'm fairly sure I read on an old Microsoft blog that SMB 2.0.2 will fall back to SMB 1 if an older version of SMB 2 (i.e. 2.0.1) is negotiated. This is backed up by Microsoft's latest documents, which state that SMB 2 must have certain SMB 2 header values. For example, the DialectRevision must be set to 0x0202 and the dialect string must be set to "SMB 2.002" in order to negotiate support for SMB 2.0.2.
SMB 2.1 and SMB 3.x
The SMB server scans the dialect provided by the client for the string "SMB 2.???". The DialectRevision must also be set to at least 0x02FF (I believe that later versions of SMB have the DialectRevision of 0x0300, 0x0302, and 0x0311).Just like how Windows 7 is actually version 6.1 behind the scenes, SMB 3.0 was originally developed as SMB 2.2 and was rebranded as SMB 3.0 when Windows 8 and Windows Server 2012 were released. Windows 10 and Server 2016 currently use SMB 3.1.1; I wouldn't expect to see SMB 4.0 anytime soon.
If the SMB server does not implement the SMB 2.1 or 3.x dialect family, it follows the old 2.0.2 negotiation process mentioned above. Microsoft produced a nice diagram in their SMB 2 documentation to show this negotiation:
SMB 2.1 is essentially the same as SMB 2.0, but there are some minor performance enhancements and a new opportunistic locking mechanism. This "client Oplock leasing model" can improve performance by controlling caching of network files by the client. The primary types of leases available are:
- Read-caching lease: allows caching reads and can be shared by multiple clients.
- Write-caching lease: allows caching writes and is exclusive to only one client.
- Handle-caching lease: allows caching handles and can be shared by multiple clients.
- Transparent Failover - clients reconnect without interruption to cluster nodes during maintenance or failover
- Scale Out – concurrent access to shared data on all file cluster nodes
- Multichannel - aggregation of network bandwidth and fault tolerance if multiple paths are available between client and server
- SMB Direct – adds RDMA networking support for very high performance, with low latency and low CPU utilization
- Encryption – Provides end-to-end AES-128-CCM encryption
- Directory Leasing - Improves application response times through caching
- Performance Optimizations - for small random read/write I/O
SMB 3.1.1 was introduced in Windows 10, and will be used in Windows Server 2016. It makes secure negotiation mandatory when connecting to clients using SMB 2.x and higher (it could be disabled in older versions because "some third-party implementations of SMB did not correctly perform this negotiation", which probably means Samba's implementation?), and adds optional support for AES-128-GCM encryption (and signing with AES-CMAC). It turns out that AES-128-GCM performs better in most modern processors, and can double the speed of large file transfers.
Unauthenticated Requests
Something that was flagged by Daniel Miller on Twitter, and verified by myself, around Christmas 2015 was that Nmap's smb-os-discovery script wasn't getting the same amount of detail back from versions of Windows Server, but the full information was returned from desktop OS such as Windows 7. When valid credentials are supplied, all versions of Windows returned the full information. However, when using NULL authentication, which the Nmap script (and attackers) will generally use, for some reason the servers don't return as much information. This suggests there's an inconsistency in the way that Windows Server generates the response, which may be down to tighter group policy settings, but is possibly just an undocumented quirk.However, it's been suggested that you can get this information from SMB 2 if you send a session setup request using NTLMSSP (NTLMSSP_Negotiate). When the server responds with an NTLMSSP_Challenge the packet will includes information such as the OS, DNS, Domain, time. Hopefully Nmap will have better results on newer systems once the script has been updated.
SMB Versions
This table shows the version of SMB that will be negotiated between two hosts, assuming that everyone's running a fully patched version of Windows with default configurations.OS | 10 / 2016 | 8.1 / 2012 R2 | 8 / 2012 | 7 / 2008 R2 | Vista / 2008 | Previous |
---|---|---|---|---|---|---|
10 / 2016 | SMB 3.1.1 | SMB 3.0.2 | SMB 3.0 | SMB 2.1 | SMB 2.0.2 | SMB 1.x |
8.1 / 2012 R2 | SMB 3.0.2 | SMB 3.0.2 | SMB 3.0 | SMB 2.1 | SMB 2.0.2 | SMB 1.x |
8 / 2012 | SMB 3.0 | SMB 3.0 | SMB 3.0 | SMB 2.1 | SMB 2.0.2 | SMB 1.x |
7 / 2008 R2 | SMB 2.1 | SMB 2.1 | SMB 2.1 | SMB 2.1 | SMB 2.0.2 | SMB 1.x |
Vista / 2008 | SMB 2.0.2 | SMB 2.0.2 | SMB 2.0.2 | SMB 2.0.2 | SMB 2.0.2 | SMB 1.x |
Previous | SMB 1.x | SMB 1.x | SMB 1.x | SMB 1.x | SMB 1.x | SMB 1.x |
Disabling and Enabling SMB Protocols
More information is available here from Microsoft, but you can use sc.exe to reconfigure the relevant service (from an elevated command prompt, and a reboot is required). For example:To disable SMB 1 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb20/nsi
sc.exe config mrxsmb10 start= disabled
To enable SMB 1 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb10/mrxsmb20/nsi
sc.exe config mrxsmb10 start= auto
To disable SMB 2 and SMB 3 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb10/nsi
sc.exe config mrxsmb20 start= disabled
To enable SMB 2 and SMB 3 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb10/mrxsmb20/nsi
sc.exe config mrxsmb20 start= auto
PowerShell
In Windows 8 or Windows Server 2012, there is a PowerShell cmdlet that can help determine what version of SMB the client has negotiated. This is called Get-SmbConnection, or "gsmbc" for short. After issuing a command to retrieve a file (or directory listing) from an SMB server, you have about 10 seconds to execute the cmdlet. To test it against yourself, run the following PowerShell commands from an elevated PowerShell:PS C:\> dir \\localhost\c$
PS C:\> gsmbc -ServerName localhost
The Dialect column will reveal the version that was negotiated, which is 3.1.1 on my Windows 10 host.
You can also enable auditing of SMB 1 traffic using PowerShell, to create events if clients are still using SMB 1.
To enable auditing of SMB 1 traffic, use the cmdlet:
Set-SmbServerConfiguration –AuditSmb1Access $true
To view the SMB 1 events, use the cmdlet:
Get-WinEvent -LogName Microsoft-Windows-SMBServer/Audit
You can also uninstall SMB 1 on modern versions of Windows (that support SMB 3.0.2 or higher?) using the cmdlet:
Remove-WindowsFeature FS-SMB1
Badlock
I've updated and published this post now that details of Badlock have been released, with more details about what appears to be a man-in-the-middle issue that can be mitigated by following best practice recommendations from the last decade of enforcing SMB signing and requiring NTLMv2 (or ideally disabling it completely and only using Kerberos).It's a real anti-climax. I thought, given the hype and its name, it might be related to the LockFile and/or LockFileEx functions that lock a specified range of bytes in a file. According to Microsoft's own documentation, the range "may extend beyond the current end of the file". I thought that Badlock's use of the Heartbleed design on their site might be a clue that it was a similar issue where an attacker requests a bad range, resulting in a buffer over-read. I wondered if this range was copied into (kernel) memory on the server and the range exceeds the actual file size (or can be used to access arbitrary memory) then could it return kernel data? Or could it allow arbitrary kernel memory to be overwritten when flushing data, e.g. when the lock is broken? It turns out it wasn't any of that.
This isn't the first time that someone may be able to gain privileged access on hosts due to a vulnerability in SMB, but this isn't the most exciting one either. Older versions of Samba allowed anonymous users to gain root access through an error in Samba's RPC; and as mentioned above Windows Vista had a nasty vulnerability that allowed unauthenticated users to gain SYSTEM privileges on a host. This is the first time that someone's given the vulnerability a decent name and logo, hence the publicity.
With most organisations using Windows Update (or WSUS, or other patch management software) to regularly deploy security fixes, I suspect most Windows users will be protected within a matter of hours or days.
Sources
- [MS-SMB2-Diff]: Server Message Block (SMB) Protocol Versions 2 and 3
- https://support.microsoft.com/en-us/kb/2696547
- https://blogs.technet.microsoft.com/josebda/2013/10/02/windows-server-2012-r2-which-version-of-the-smb-protocol-smb-1-0-smb-2-0-smb-2-1-smb-3-0-or-smb-3-02-are-you-using/
- https://blogs.technet.microsoft.com/josebda/2015/05/05/whats-new-in-smb-3-1-1-in-the-windows-server-2016-technical-preview-2/
- https://blogs.technet.microsoft.com/josebda/2008/12/09/smb2-a-complete-redesign-of-the-main-remote-file-protocol-for-windows/
- https://blogs.msdn.microsoft.com/openspecification/2009/05/22/client-caching-features-oplock-vs-lease/
- https://msdn.microsoft.com/en-us/library/cc246805.aspx
- https://msdn.microsoft.com/en-us/library/windows/hardware/ff547373(v=vs.85).aspx
- https://en.wikipedia.org/wiki/Samba_(software)
- https://en.wikipedia.org/wiki/Server_Message_Block