Windows: SMBv2 Symlink to Local File Vulnerability
Platform: Windows 7, 8.1 Update 32/64 bit
Class: Security Bypass/Information Disclosure
SMBv2 supports symlinks on remote file systems by returning a special status code (STATUS_STOPPED_ON_SYMLINK) when a symlink is encountered on the remote share. It also returns a symlink reparse data buffer to be processed to determine where to redirect the request. While this is supported functionality by default Windows 7+ is configured to not follow symlinks from a server. This includes remote->remote and remote->local, presumably for security reasons. The verification of the remote->local or remote->remote is done within the object manager during a reparse operation.
Unfortunately even though [MS-SMB2] states that the reparse buffer must be of type IO_REPARSE_TAG_SYMLINK no code (such as in MRXSMB20.sys) actually checks. The only checks on the buffer is a call to FsRtlValidateReparsePointBuffer in MRXSMB20.sys, which is happy to validate IO_REPARSE_TAG_MOUNT_POINT buffers. This causes a reparse to occur in the IO manager, and because it isn't a symlink the source device is not considered, instead only the destination device (which can be a disk drive) is checked. Exploiting this allows a malicious SMBv2 server to force a client to open arbitrary local files. For example it might be possible to serve a HTML file from the share and use XMLHttpRequest to access local files through this vulnerability. Also even though mount points are supposed to only be used with directories once the buffer is in the object manager it doesn't make such a distinction, so this can be used to open files or directories.
It's also interesting that no effort is made to verify the header values either (either the length or the SymLinkErrorTag), although it isn't obvious this would cause any security issues.
Demonstrating the issue isn't trivial, it can be done either by modifying the reparse buffer in a kernel debugger or instead using a modified samba server. I've attached a patch for samba 4.1.13 which sends back the reparse point response when the file "badgers.txt" is requested from the share. The reparse point buffer redirects the request to \??\c:\windows\win.ini. When a request is made for the filename it will instead open the local file.
This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.