Windows: Limited Bypass of Traverse Permissions in Kernel Object Manager
Platform: Windows 7 32/64 bit, Windows 8+
Class: Security Bypass
Windows has the concept of traversal permission which allows a user to open
resources under a directory where they don't have read permissions on the
directory itself, this can be expressed using the FILE_TRAVERSE permission or
DIRECTORY_TRAVERSE permissions for the file system or object manager. Most
tokens have the SeChangeNotifyPrivilege available which is used to always
grant traverse permissions regardless of the actual DACL on the object.
When a token doesn't have this privilege (say the Anonymous token, or something
like the heavily restricted Chrome sandbox token) it falls back to the access
check. However there's some unusual behaviour in the SeFastTraverseCheck method
which could grant traverse permissions to tokens which wouldn't normally be
able to get it.
The SeFastTraverseCheck enumerates a directory's DACL for any access allowed
ACE granting the Everyone group traverse permissions. It doesn't take into
account whether the caller actually has the Everyone group enabled. If this
check succeeds then it doesn't perform the full access check. This can give a
very limited token traverse permissions to parts of the object manager, for
example the root directory, \Devices, \RPC Control etc.
At least in the development of the Chrome sandbox there was an assumption that
the traverse permission is enforced consistently, certainly when running with a
restricted token (which blocks NULL DACL access for example). However because
of this limitation it's possible for low privilege chrome code to access some
device objects where it shouldn't be possible even determine they exist.
Looking at the implementation of SeFastAccessCheck it does check the Access
State flags for the flag 0x10 and fails if it's set. This might correspond to
the Token flag TOKEN_IS_RESTRICTED however looking at SeCreateAccessState this
flag is never set so it isn't clear what its purpose is.
I don't really expect this will be considered a bulletin class issue, if it's
considered an issue at all. It's possible it's by design however I'm reporting
as it does cause minor security impact for Chrome and it's in a security
related area. If I were to guess this code is probably a relic of when tokens
typically had the Everyone group (including the Anonymous token) which is no
longer a safe assumption to make.
Attached is a simple PoC which demonstrates the issue for execution on Windows
7/8. Just execute the file and observe the displayed output. I've verified that
the bypass occurs due to success in the SeFastAccessCheck method.
Expected Result:
Both calls to open an non-existent name should return ERROR_ACCESS_DENIED (5)
Observed Result:
First check fails with ERROR_ACCESS_DENIED while second fails with
ERROR_FILE_NOT_FOUND (2) indicating that traversal permissions were granted.
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.
Original issue reported on code.google.com by fors...@google.com on 2 Dec 2014 at 2:27
Original issue reported on code.google.com by
fors...@google.com
on 2 Dec 2014 at 2:27Attachments: