2. James Forshaw @tiraniddo
Obligatory Background Slide
2
● Researcher in Google’s Project Zero
● Specialize in Windows
○ Especially local privilege escalation
● Never met a logical vulnerability I didn’t like
3. James Forshaw @tiraniddo
What I’m Going to Talk About
● Privilege escalation in Windows
○ Good places to look for bugs, mixture of user mode and kernel mode
tips
● Fun tricks you can use to exploit vulnerabilities
○ Some even many at Microsoft weren’t aware of
● Mainly logical vulnerabilities, not worrying about memory corruption
3
10. James Forshaw @tiraniddo
System Services and Drivers
10
Windows 7
SP1
Windows
8.1 Windows 10
Services 150 169 196
Drivers 238 253 291
7 8 10
11. James Forshaw @tiraniddo
Service Privilege Levels
11
Windows 7
SP1 Windows 8.1 Windows 10
Local System 53.69% 56.89% 61.14%
Local Service 32.21% 31.14% 28.50%
Network
Service 14.09% 11.98% 10.36%
7 8 10
12. James Forshaw @tiraniddo
Service Start Mode
12
Windows 7 Windows 8.1 Windows 10
Auto 30.07% 26.19% 24.10%
Disabled 5.23% 3.57% 2.05%
Manual 53.59% 43.45% 42.56%
Triggered 11.11% 26.79% 31.28%
7 8 10
15. James Forshaw @tiraniddo
Example: Mozilla Maintenance Service
/**
* Main entry point when running as a service.
*/
void WINAPI
SvcMain(DWORD argc, LPWSTR *argv) {
// ...
ExecuteServiceCommand(argc, argv);
}
15
17. James Forshaw @tiraniddo
Simple C# Test Program
class Program {
static void Main(string[] args) {
if (args.Length < 1) {
Console.WriteLine("Usage: ServiceName args");
Environment.Exit(1);
}
ServiceController service = new ServiceController(args[0]);
if (service.Status == ServiceControllerStatus.Stopped) {
service.Start(args);
}
}
}
17
23. James Forshaw @tiraniddo
Opening a Device Name
DeviceHarddisk1SomeName
DeviceHarddisk1 SomeName
Device Path
Native NT Path
Device
Namespace Path
24. James Forshaw @tiraniddo
Opening a Device Name
DeviceHarddisk1SomeName
DeviceHarddisk1 SomeName
Device Path
Native NT Path
Device
Namespace Path
Harddisk Driver
Create File
Handler
25. James Forshaw @tiraniddo
Securing the Device Namespace
● So what’s the problem?
○ By default security of device path enforced by kernel
○ Security of namespace IS NOT enforced by kernel
● If the driver doesn’t do its own checking or sets appropriate flags
there’s NO security
27. James Forshaw @tiraniddo
Example: Windows Sockets
● On Linux/OSX sockets implemented as system calls
● Implemented in the Ancillary Function Driver
● You interact with it via DeviceAfd
● But you must open the device namespace passing it DeviceAfd
Endpoint
● No security on the namespace :(
● Further interaction via DeviceIoControl
29. James Forshaw @tiraniddo
Talk to Any Registered IP Endpoint
● For example SMB or DCE/RPC
29
https://code.google.com/p/google-security-research/issues/detail?id=222
30. James Forshaw @tiraniddo
What to Look For?
● Best place to look is in the handlers for:
○ IRP_MJ_DEVICE_CONTROL
○ IRP_MJ_FILE_SYSTEM_CONTROL
○ Classic IOCTL bugs
● Control Code encodes what permissions the device handle needs
to call and includes parameter passing information.
30
Device Type
bits 30 - 16
Required
Access
15-14
Function Code
12-2
Transfer
Type
1-0
METHOD_BUFFERED 0
METHOD_IN_DIRECT 1
METHOD_OUT_DIRECT 2
METHOD_NEITHER 3
FILE_ANY_ACCESS 0
FILE_READ_ACCESS 1
FILE_WRITE_ACCESS 2
33. James Forshaw @tiraniddo
Per-Process DeviceMap
const int ProcessDeviceMap = 23;
struct PROCESS_DEVICEMAP_INFORMATION {
HANDLE DirectoryHandle;
};
bool SetProcessDeviceMap(HANDLE hDir) {
PROCESS_DEVICEMAP_INFORMATION DeviceMap = {hDir};
NTSTATUS status = NtSetInformationProcess(
GetCurrentProcess(),
ProcessDeviceMap,
&DeviceMap,
sizeof(DeviceMap));
return status == 0;
}
33
34. James Forshaw @tiraniddo
Using Per-Process Device Map
NTSTATUS DoDeviceIoControl(DRIVER_OBJECT *Driver, PIRP Irp) {
// Potentially vulnerable
PIO_STACK_LOCATION stack_loc = ...;
if (stack_loc‐>DeviceIoControl.IoControlCode ==
IOCTL_SOMETHING) {
UNICODE_STRING name = L"??C:";
UNICODE_STRING target = L"DeviceTarget":
IoCreateSymbolicLink(&name, &target);
}
}
HANDLE hDir;
UNICODE_STRING name = L"GLOBAL??";
NtOpenDirectoryObject(&hDir, DIRECTORY_TRAVERSE, &ObjAttr);
SetProcessDeviceMap(hDir);
34
https://code.google.com/p/google-security-research/issues/detail?id=538
35. James Forshaw @tiraniddo
The Hand Which Giveth…
● MS15-111 Removed Per-Process Device Map from Sandboxes
if (ProcessInformationClass ==
ProcessDeviceMap) {
if (RtlIsSandboxedToken(NULL)) {
return STATUS_ACCESS_DENIED;
}
return ObSetDeviceMap(ProcessHandle,
DirectoryHandle);
}
35
37. James Forshaw @tiraniddo
Impersonation and DeviceMaps
● When a privileged service impersonates a user they also
impersonate their device map.
● Dropping a C: symbolic link in per-user device map directory allows
control over where that service things the C: is while
impersonating.
● Prior to MS15-038 you could use this load DLLs in the target
process
○ This was fixed by adding a new object attribute
OBJ_IGNORE_IMPERSONATED_DEVICEMAP which disables the
impersonation device map.
● But still useful, for example process creation while impersonating
still vulnerable
● Also reading of “protected” configuration.
● Original DLL version available at
https://code.google.com/p/google-security-research/issues/detail?
id=240
37
38. James Forshaw @tiraniddo
Use Process Monitor
● Process Monitor logs the impersonation context on file creation
events.
● Use this to see if any system service is impersonating the user
while opening anything useful (DLLs probably don’t count).
38
Look for this value
39. James Forshaw @tiraniddo
Interesting Object Attribute Flags
39
Flag Name Value Description
OBJ_CASE_INSENSITIVE 0x0040
Interesting if system is
configured as case
sensitive (default is no)
OBJ_OPENLINK 0x0100
Opens a “link” object. Used
to open a registry key
symbolic link
OBJ_KERNEL_HANDLE 0x0200
If not set in kernel mode,
exposed handle to current
process
OBJ_FORCE_ACCESS_CHECK 0x0400
If not set in kernel mode will
open the resource with no
security checks
OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x0800
Ignore the impersonated
device map
40. James Forshaw @tiraniddo
Default ACLs and Owners
● A file or object’s permissions depend one of three things:
○ The inherited permissions from its container (e.g. a Directory) and/or,
○ The default permissions from the current active token
○ An explicit Security Descriptor passed to kernel system call
40
Default
GROUP
Default
DACL
Default
OWNER
Integrity Level also Inherited
from Token
41. James Forshaw @tiraniddo
What if DeviceMap Doesn’t Exist?
NTSTATUS SeGetTokenDeviceMap(TOKEN *token,
DEVICE_MAP **device_map) {
if (!token‐>LogonSession‐>pDeviceMap) {
swprintf_s(
&SourceString,
L"Sessions0DosDevices%08x‐%08x",
token‐>AuthenticationId.HighPart,
token‐>AuthenticationId.LowPart);
InitializeObjectAttributes(&ObjectAttributes,
SourceString, OBJ_KERNEL_HANDLE, ...);
ZwCreateDirectoryObject(&DirectoryHandle,
DIRECTORY_ALL_ACCESS, &ObjectAttributes);
ObSetDirectoryDeviceMap(&token‐>LogonSession,
DirectoryHandle);
}
*device_map = token‐>LogonSession‐>pDeviceMap;
}
41
42. James Forshaw @tiraniddo
Default Security
● Because devicemap directory created in-process on demand it
gains the permissions of the caller:
○ Owner set
○ Default DACL
● Means we can access the device map
● We can use this in limited ways to circumvent loss of per-process
Device Map
● Also works for many other resources such as Registry Keys and
Files
1. Get a token (such as from S4U) with an uninitialized devicemap
2. Impersonate token and access device map to create it
3. Open resource/call kernel function while impersonating the user
42
43. James Forshaw @tiraniddo
Win32 Automatic Redirection
43
● Win32 APIs redirect certain file names when called native APIs e.g.
○ COM1 -> ??COM1
○ NUL -> ??NUL
○ And others
● System services rarely guard against it.
● If you can get the call under impersonation you can redirect the file
access even if you don’t have control over the complete path
● For example
○ If the service will open c:somepathyourfile you can redirect to
another file
○ Potentially exploitable for configuration information
44. James Forshaw @tiraniddo
Path Canonicalization
● Path canonicalization is fundamentally different between Windows
and Linux/OSX
● In Linux or OSX the path is passed to the kernel as is
○ Kernel responsible for path canonicalization
○ Both . and .. directories are real directory entries
● In Windows it must be passed as an absolute path to kernel
○ Relative path components removed in user mode
○ Current directory processed
○ Both . and .. are simulated
44
45. James Forshaw @tiraniddo
Path Canonicalization
45
A B C
Path Linux/OSX Windows
A/B/C Valid Valid
A/B/C/../../B Valid Valid
A/B/D/../C Invalid Valid
A/B/D”/../C Invalid Valid
const char* path = "c:myapp.exe" ....windowsnotepad.exe";
if (CheckSig(path)) {
snprintf(cmdline, ""%s" arg", path);
CreateProcess(NULL, cmdline, ...);
}
53. James Forshaw @tiraniddo
AiCheckSecureApplicationDirectory Bypass
53
● Need to be able to write a file with a secure path
● How can we write to C:Windows without writing to C:Windows?
c:windows malicious.exe
ALLOWED
c:windows ????
ALLOWED?
54. James Forshaw @tiraniddo
NTFS Alternate Data Streams FTW!
54
c:windows tracing:malicious.exe
ALLOWED
● Only need FILE_WRITE_DATA/FILE_ADD_FILE access right on
directory to created named stream.
● Bug only fixed in Windows 10, not in Windows 8.1 and below.
55. James Forshaw @tiraniddo
Windows Symbolic Links
Windows NT 3.1 - July 27 1993
Object Manager Symbolic Links
Registry Key Symbolic Links
Windows 2000 - Feb 17 2000
NTFS Mount Points and
Directory Junctions
Windows Vista - Nov 30 2006
NTFS Symbolic Links
56. James Forshaw @tiraniddo
Mitigated in Sandboxes
56
NTFS Mount Points
Registry Key Symbolic
Links
Object Manager
Symbolic Links
BANNED
LIMITED
LIMITED
57. James Forshaw @tiraniddo
Weird Default Permissions
● Both C:WindowsTemp and C:ProgramData have permissions
which allow a normal user to create new files
● If you can find a program misusing these you can create new files
or symbolic links to attack them
● You can’t delete files necessarily, but of course worth finding a way
of doing so.
57
59. James Forshaw @tiraniddo
The Tools of the Trade (well my choice)
59
● SysInternals
○ Process Explorer
○ Process Monitor
○ WinObj
● WinDBG
● Rohitab API Monitor (http://www.rohitab.com/apimonitor)
● RPCView (http://www.rpcview.org/)
● OleView.NET (https://github.com/tyranid/oleviewdotnet)
● Sandbox Analysis Tools (
https://github.com/google/sandbox-attacksurface-analysis-tools
● IDA Pro