2008-09-04:

Google Chrome's Sandbox

chrome:easy:windows:security:re
Yesterday I had some free time to look into the Google Chrome's sandbox, so I'll write a little 'bout it today.

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:

(NT) NtCreateFile
(NT) NtOpenFile
(NT) NtQueryAttributesFile
(NT) NtQueryFullAttributesFile
(NT) NtSetInformationFile
(NT) NtOpenThread
(NT) NtOpenProcess
(NT) NtOpenProcessToken
(NT) NtSetInformationThread
(NT) NtOpenThreadToken
(NT) NtOpenProcessTokenEx
(NT) NtOpenThreadTokenEx
(NT) NtCreateKey
(NT) NtOpenKey
(EAT) CreateNamedPipeW
(EAT) CreateProcessW
(EAT) CreateProcessA
(EAT) CreateEventW
(EAT) OpenEventW
(NT) NtMapViewOfSection
(NT) NtUnmapViefOfSection

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 OldPriv;
 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.

 FreeLibrary(NtDll);
}

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:

 interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx",
   INTERCEPTION_SMART_SIDESTEP, function);
 interceptions.AddToPatchedFunctions(L"b.dll",
   "TheIncredibleCallToSaveTheWorld", INTERCEPTION_EAT, function);
 interceptions.AddToPatchedFunctions(L"a.dll", "BIsLame",
   INTERCEPTION_EAT, function);
 interceptions.AddToPatchedFunctions(L"a.dll", "ARules",
   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:

USER anonymous
PASS IEUser@

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.

Comments:

2008-09-05 15:24:59 = AlienRancher
{
Looks like the interceptions are not for security, I mean from reading the doc you link:

"Emulation is not security: Emulation and virtual machine solutions do not by themselves provide security. The sandbox should not rely on code emulation, code translation, or patching to provide security."

}
2008-09-06 06:59:59 = Gynvael Coldwind
{
Hi, and thanks for the comment, You're the first one to comment on the English side of my blog hehe ;>

As for the interceptions, I think they are for security, because they limit access to files, registry keys, and some functionality. Please note that they do not provide virtual file system / registry functionality, nor do they provide emulation or virtualizing code. They provide additional limitation in accessing files, registry, and other functionality, which is normally considered as security.
So imho, they are there for security, and I can't find any other reason for them to be there (if I am missing something, please point it out ;>).

As for the "patching" - As I have noted in the post, the authors of the Sandbox are well aware of the weakness of the interceptions, and it is only one of several methods used. So it's OK to say that the Sandbox does not rely on it, however it still uses it, because it still provides some security.

As for the quote. One thing is interesting - the Google guys say that "Emulation and virtual machine solutions do not by themselves provide security". On the other hand, the VM in Quake 3 according to some sources was developed to "limit the damage a rogue or malicious QVM program can wreak" (direct quote from http://icculus.org/~phaethon/q3mc/q3vm_specs.html), which is in fact a security reason. Of course a mistake is to compare a browser and a game. Or is it? ;>
}
2008-09-07 00:11:44 = AlienRancher
{
No seriously, they are not for security, they are for compatibility *if* wanted. If you care to read the TargetXXXXX functions it will become obvious.

}
2008-09-07 03:20:04 = Gynvael Coldwind
{
Quote from the docs:
"The interceptions (also known as hooks) are how Windows API calls are forwarded via the sandbox IPC to the broker. It is up to the broker to re-issue the API calls and return the results or simply fail the calls. The interception + IPC mechanism does not provide security; it is designed to provide compatibility when code inside the sandbox cannot be modified to cope with sandbox restrictions."

If I understand correctly, it is designed, as You say, to make code that is having problems with the restrictions run OK. This would mean that this mechanism would allow to reach additionally, normally unreachable due to the restrictions, files/keys from the sandbox. OK, so far it makes sens.
What I don't understand is why this compatibility mechanism additionally limits places that are normally accessible from the sandbox. Call it what You want, but I call 'limiting access' a security mechanism.
}
2008-09-07 17:36:26 = AlienRancher
{

>> compatibility mechanism additionally limits places that are normally

Looks like in the TargetXXX intercepts the first thing done is to call the orginal NtXXXX function, so it does not seem to place additional limits.

See for example TargetNtCreateFile :
http://src.chromium.org/viewvc/chrome/trunk/src/sandbox/src/filesystem_interception.cc?view=annotate

Line 27, the first thing done is to call the original. If the error code is not access denied then it just returns, if the error code is access denied it does a bunch more things.

What do you think?
}
2008-09-08 02:53:05 = Gynvael Coldwind
{
Hmmm.... The code seems to confirm that it is for compatibility.

I researched a little more to find how come I got some files restricted while testing, and why weren't they restricted after the interceptions have been removed, and it looks like I mixed up some flags during tests. Ups ;D

Thanks for straighting things up in that case ;> I'll write some correcting news later today.
}
2008-09-25 00:29:46 = cocoa
{
Attaching a process to other desktop it does not stop you from breaking out that "sandbox"
http://blogs.msdn.com/david_leblanc/archive/2007/07/31/practical-windows-sandboxing-part-3.aspx
But i havent read all the sandbox code of chrome
BTW nice blog.
}
2008-09-25 16:57:22 = Gynvael Coldwind
{
@cocoa
Thank you for your post, especially for the link ;>
Hmm I'll have to check later if Chrome does some desktop magic like described in the link provided by you. If not, well, it looks like the desktop switching really does not provide the security it should.
}
2009-04-24 13:05:15 = Achintya Sharma
{
Hi,
You have a nice description of the chrome sandbox.
I was reading the comments and came across some people suggesting that the chrome sandbox does not provide security via the API hooking. That's not exactly true.
The chrome sandbox utilizes the job object and tokens to sandbox the process. The reason why the API is called immediately in the handler is to check whether the process is allowed to access the resource. If it is allowed by the kernel despite the job and the token boundries, then the call is allowed to be made. If the call fails due to an access denied, then the sandbox informs the host and the host decides how to handle the resource request.
I just wanted to clarify this so that others don't get thrown off by the comments like I did :-)
}

Add a comment:

Nick:
URL (optional):
Math captcha: 3 ∗ 4 + 3 =