justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 1 | # Sandbox |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | ## Overview |
| 6 | |
| 7 | Security is one of the most important goals for Chromium. The key to security is |
| 8 | understanding: we can only truly secure a system if we fully understand its |
| 9 | behaviors with respect to the combination of all possible inputs in all possible |
| 10 | states. For a codebase as large and diverse as Chromium, reasoning about the |
| 11 | combined behavior of all its parts is nearly impossible. The sandbox objective |
| 12 | is to provide hard guarantees about what ultimately a piece of code can or |
| 13 | cannot do no matter what its inputs are. |
| 14 | |
| 15 | Sandbox leverages the OS-provided security to allow code execution that cannot |
| 16 | make persistent changes to the computer or access information that is |
| 17 | confidential. The architecture and exact assurances that the sandbox provides |
| 18 | are dependent on the operating system. This document covers the Windows |
| 19 | implementation as well as the general design. The Linux implementation is |
Ryan Landay | c1a28f25 | 2024-09-09 19:11:35 | [diff] [blame] | 20 | described [here](../../linux/sandbox/linux/README.md), the OSX implementation |
| 21 | [here](https://dev.chromium.org/developers/design-documents/sandbox/osx-sandboxing-design). |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 22 | |
| 23 | If you don't feel like reading this whole document you can read the |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 24 | [Sandbox FAQ](sandbox_faq.md) instead. A description of what the sandbox does |
| 25 | and doesn't protect against may also be found in the FAQ. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 26 | |
| 27 | ## Design principles |
| 28 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 29 | * **Do not re-invent the wheel:** It is tempting to extend the OS kernel with |
| 30 | a better security model. Don't. Let the operating system apply its security |
| 31 | to the objects it controls. On the other hand, it is OK to create |
| 32 | application-level objects (abstractions) that have a custom security model. |
| 33 | * **Principle of least privilege:** This should be applied both to the |
| 34 | sandboxed code and to the code that controls the sandbox. In other words, |
| 35 | the sandbox should work even if the user cannot elevate to super-user. |
| 36 | * **Assume sandboxed code is malicious code:** For threat-modeling purposes, |
| 37 | we consider the sandbox compromised (that is, running malicious code) once |
| 38 | the execution path reaches past a few early calls in the `main()` function. |
| 39 | In practice, it could happen as soon as the first external input is |
| 40 | accepted, or right before the main loop is entered. |
| 41 | * **Be nimble:** Non-malicious code does not try to access resources it cannot |
| 42 | obtain. In this case the sandbox should impose near-zero performance impact. |
| 43 | It's ok to have performance penalties for exceptional cases when a sensitive |
| 44 | resource needs to be touched once in a controlled manner. This is usually |
| 45 | the case if the OS security is used properly. |
| 46 | * **Emulation is not security:** Emulation and virtual machine solutions do |
| 47 | not by themselves provide security. The sandbox should not rely on code |
| 48 | emulation, code translation, or patching to provide security. |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 49 | |
| 50 | ## Sandbox Windows architecture |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 51 | |
| 52 | The Windows sandbox is a user-mode only sandbox. There are no special kernel |
| 53 | mode drivers, and the user does not need to be an administrator in order for the |
| 54 | sandbox to operate correctly. The sandbox is designed for both 32-bit and 64-bit |
Alex Gough | 665e875 | 2023-01-25 01:29:37 | [diff] [blame] | 55 | processes and has been tested on all Windows OS flavors from Windows 10. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 56 | |
| 57 | Sandbox operates at process-level granularity. Anything that needs to be |
| 58 | sandboxed needs to live on a separate process. The minimal sandbox configuration |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 59 | has two processes: one that is a privileged controller known as the *broker*, |
| 60 | and one or more sandboxed processes known as the *target*. Throughout the |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 61 | documentation and the code these two terms are used with that precise |
| 62 | connotation. The sandbox is provided as a static library that must be linked to |
| 63 | both the broker and the target executables. |
| 64 | |
| 65 | ### The broker process |
| 66 | |
| 67 | In Chromium, the broker is always the browser process. The broker, is in broad |
| 68 | terms, a privileged controller/supervisor of the activities of the sandboxed |
| 69 | processes. The responsibilities of the broker process are: |
| 70 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 71 | 1. Specify the policy for each target process |
| 72 | 1. Spawn the target processes |
| 73 | 1. Host the sandbox policy engine service |
| 74 | 1. Host the sandbox interception manager |
| 75 | 1. Host the sandbox IPC service (to the target processes) |
| 76 | 1. Perform the policy-allowed actions on behalf of the target process |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 77 | |
| 78 | The broker should always outlive all the target processes that it spawned. The |
| 79 | sandbox IPC is a low-level mechanism (different from Chromium's IPC) that is |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 80 | used to transparently forward certain Windows API calls from the target to the |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 81 | broker: these calls are evaluated against the policy. The policy-allowed calls |
| 82 | are then executed by the broker and the results returned to the target process |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 83 | via the same IPC. The job of the interceptions manager is to patch the Windows |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 84 | API calls that should be forwarded via IPC to the broker. |
| 85 | |
| 86 | ### The target process |
| 87 | |
| 88 | In Chromium, the renderers are always target processes, unless the |
| 89 | `--no-sandbox` command line has been specified for the browser process. The |
| 90 | target process hosts all the code that is going to run inside the sandbox, plus |
| 91 | the sandbox infrastructure client side: |
| 92 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 93 | 1. All code to be sandboxed |
| 94 | 1. The sandbox IPC client |
| 95 | 1. The sandbox policy engine client |
| 96 | 1. The sandbox interceptions |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 97 | |
| 98 | Items 2,3 and 4 are part of the sandbox library that is linked with the code to |
| 99 | be sandboxed. |
| 100 | |
| 101 | The interceptions (also known as hooks) are how Windows API calls are forwarded |
| 102 | via the sandbox IPC to the broker. It is up to the broker to re-issue the API |
| 103 | calls and return the results or simply fail the calls. The interception + IPC |
| 104 | mechanism does not provide security; it is designed to provide compatibility |
| 105 | when code inside the sandbox cannot be modified to cope with sandbox |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 106 | restrictions. To save unnecessary IPCs, policy is also evaluated in the target |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 107 | process before making an IPC call, although this is not used as a security |
| 108 | guarantee but merely a speed optimization. |
| 109 | |
| 110 | It is the expectation that in the future most plugins will run inside a target |
| 111 | process. |
| 112 | |
| 113 |  |
| 114 | |
| 115 | ## Sandbox restrictions |
| 116 | |
| 117 | At its core, the sandbox relies on the protection provided by four Windows |
| 118 | mechanisms: |
| 119 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 120 | * A restricted token |
| 121 | * The Windows *job* object |
| 122 | * The Windows *desktop* object |
| 123 | * Integrity levels |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 124 | |
| 125 | These mechanisms are highly effective at protecting the OS, its configuration, |
| 126 | and the user's data provided that: |
| 127 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 128 | * All the securable resources have a better than null security descriptor. In |
| 129 | other words, there are no critical resources with misconfigured security. |
| 130 | * The computer is not already compromised by malware. |
| 131 | * Third party software does not weaken the security of the system. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 132 | |
| 133 | ** Note that extra mitigations above and beyond this base/core will be described |
| 134 | in the "Process Mitigations" section below. |
| 135 | |
| 136 | ### The token |
| 137 | |
| 138 | One issue that other similar sandbox projects face is how restricted can the |
| 139 | token and job be while still having a properly functioning process. For the |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 140 | Chromium sandbox, the most restrictive token takes the following form: |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 141 | |
| 142 | #### Regular Groups |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 143 | |
| 144 | * Logon SID : mandatory |
| 145 | * All other SIDs : deny only, mandatory |
| 146 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 147 | #### Restricted Groups |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 148 | |
| 149 | * S-1-0-0 : mandatory |
| 150 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 151 | #### Privileges |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 152 | |
| 153 | * None |
| 154 | |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 155 | #### Integrity |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 156 | |
| 157 | * Untrusted integrity level label (S-1-16-0x0) |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 158 | |
| 159 | With the caveats described above, it is near impossible to find an existing |
| 160 | resource that the OS will grant access with such a token. As long as the disk |
| 161 | root directories have non-null security, even files with null security cannot be |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 162 | accessed. The Chromium renderer runs with this token, which means that almost |
| 163 | all resources that the renderer process uses have been acquired by the Browser |
| 164 | and their handles duplicated into the renderer process. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 165 | |
| 166 | Note that the token is not derived from anonymous or from the guest token; it is |
| 167 | derived from the user's token and thus associated to the user logon. As a |
| 168 | result, any auditing that the system or the domain has in place can still be |
| 169 | used. |
| 170 | |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 171 | By design, the sandbox token cannot protect the non-securable resources such as: |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 172 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 173 | * Mounted FAT or FAT32 volumes: The security descriptor on them is effectively |
| 174 | null. Malware running in the target can read and write to these volumes as |
| 175 | long it can guess or deduce their paths. |
| 176 | * TCP/IP: The security of TCP/IP sockets in Windows 2000 and Windows XP (but |
| 177 | not in Vista) is effectively null. It might be possible for malicious code |
| 178 | in the target to send and receive network packets to any host. |
| 179 | * Some unlabelled objects, such as anonymous shared memory sections (e.g. |
| 180 | [bug 338538](https://crbug.com/338538)) |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 181 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 182 | See NULL DACLs and Other Dangerous ACE Types, *Secure Coding Techniques*, |
| 183 | 195-199 for more information. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 184 | |
| 185 | ### The Job object |
| 186 | |
| 187 | The target process also runs under a Job object. Using this Windows mechanism, |
| 188 | some interesting global restrictions that do not have a traditional object or |
| 189 | security descriptor associated with them are enforced: |
| 190 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 191 | * Forbid per-use system-wide changes using `SystemParametersInfo()`, which can |
| 192 | be used to swap the mouse buttons or set the screen saver timeout |
| 193 | * Forbid the creation or switch of Desktops |
| 194 | * Forbid changes to the per-user display configuration such as resolution and |
| 195 | primary display |
| 196 | * No read or write to the clipboard |
| 197 | * Forbid Windows message broadcasts |
| 198 | * Forbid setting global Windows hooks (using `SetWindowsHookEx()`) |
| 199 | * Forbid access to the global atoms table |
| 200 | * Forbid access to USER handles created outside the Job object |
| 201 | * One active process limit (disallows creating child processes) |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 202 | |
| 203 | Chromium renderers normally run with all these restrictions active. Each |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 204 | renderer runs in its own Job object. Using the Job object, the sandbox can (but |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 205 | currently does not) prevent: |
| 206 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 207 | * Excessive use of CPU cycles |
| 208 | * Excessive use of memory |
| 209 | * Excessive use of IO |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 210 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 211 | More information about Windows Job Objects can be found |
| 212 | [here](https://docs.microsoft.com/en-us/windows/desktop/procthread/job-objects). |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 213 | |
| 214 | ### The alternate desktop |
| 215 | |
| 216 | The token and the job object define a security boundary: that is, all processes |
| 217 | with the same token and in the same job object are effectively in the same |
| 218 | security context. However, one not-well-understood fact is that applications |
| 219 | that have windows on the same desktop are also effectively in the same security |
| 220 | context because the sending and receiving of window messages is not subject to |
| 221 | any security checks. Sending messages across desktops is not allowed. This is |
| 222 | the source of the infamous "shatter" attacks, which is why services should not |
| 223 | host windows on the interactive desktop. A Windows desktop is a regular kernel |
| 224 | object that can be created and assigned a security descriptor. |
| 225 | |
| 226 | In a standard Windows installation, at least two desktops are attached to the |
| 227 | interactive window station; the regular (default) desktop, and the logon |
| 228 | desktop. The sandbox creates a third desktop that is associated to all target |
| 229 | processes. This desktop is never visible or interactive and effectively isolates |
| 230 | the sandboxed processes from snooping the user's interaction and from sending |
| 231 | messages to windows operating at more privileged contexts. |
| 232 | |
| 233 | The only disadvantage of an alternate desktop is that it uses approximately 4MB |
| 234 | of RAM from a separate pool, possibly more on Vista. |
| 235 | |
| 236 | More information about Window Stations |
| 237 | |
| 238 | ### The integrity levels |
| 239 | |
| 240 | Integrity levels are available on Windows Vista and later versions. They don't |
| 241 | define a security boundary in the strict sense, but they do provide a form of |
| 242 | mandatory access control (MAC) and act as the basis of Microsoft's Internet |
| 243 | Explorer sandbox. |
| 244 | |
| 245 | Integrity levels are implemented as a special set of SID and ACL entries |
| 246 | representing five levels of increasing privilege: untrusted, low, medium, high, |
| 247 | system. Access to an object may be restricted if the object is at a higher |
| 248 | integrity level than the requesting token. Integrity levels also implement User |
| 249 | Interface Privilege Isolation, which applies the rules of integrity levels to |
| 250 | window messages exchanged between different processes on the same desktop. |
| 251 | |
| 252 | By default, a token can read an object of a higher integrity level, but not |
| 253 | write to it. Most desktop applications run at medium integrity (MI), while less |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 254 | trusted processes like Internet Explorer's protected mode and our GPU sandbox |
| 255 | run at low integrity (LI), while our renderer processes run at the lowest |
| 256 | Untrusted integrity level. |
| 257 | |
| 258 | A low integrity level token can access only the following shared resources: |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 259 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 260 | * Read access to most files |
| 261 | * Write access to `%USER PROFILE%\AppData\LocalLow` |
| 262 | * Read access to most of the registry |
| 263 | * Write access to `HKEY_CURRENT_USER\Software\AppDataLow` |
| 264 | * Clipboard (copy and paste for certain formats) |
| 265 | * Remote procedure call (RPC) |
| 266 | * TCP/IP Sockets |
| 267 | * Window messages exposed via `ChangeWindowMessageFilter` |
| 268 | * Shared memory exposed via LI (low integrity) labels |
| 269 | * COM interfaces with LI (low integrity) launch activation rights |
| 270 | * Named pipes exposed via LI (low integrity) labels |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 271 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 272 | While an Untrusted integrity level can only write to resources which have a null |
| 273 | DACL or an explicit Untrusted Mandatory Level. |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 274 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 275 | You'll notice that the previously described attributes of the token, job object, |
| 276 | and alternate desktop are more restrictive, and would in fact block access to |
| 277 | everything allowed in the above list. So, the integrity level is a bit redundant |
| 278 | with the other measures, but it can be seen as an additional degree of |
| 279 | defense-in-depth, and its use has no visible impact on performance or resource |
| 280 | usage. |
| 281 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 282 | The integrity level of different Chrome components will change over time as |
| 283 | functionality is split into smaller services. At M75 the browser, crash handler, |
| 284 | and network utility processes run at Medium integrity, the GPU process at Low |
| 285 | and most remaining services including isolated renderers at Untrusted. |
Alex Gough | fec822f | 2019-06-17 22:06:29 | [diff] [blame] | 286 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 287 | More information on integrity levels can be found |
| 288 | [here](http://msdn.microsoft.com/en-us/library/bb625963.aspx) and in Chapter 7 |
| 289 | of *Windows Internals, Part 1, 7th Ed.*. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 290 | |
| 291 | ### Process mitigation policies |
| 292 | |
| 293 | Most process mitigation policies can be applied to the target process by means |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 294 | of SetProcessMitigationPolicy. The sandbox uses this API to set various policies |
| 295 | on the target process for enforcing security characteristics. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 296 | |
| 297 | #### Relocate Images: |
| 298 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 299 | * >= Win8 |
| 300 | * Address-load randomization (ASLR) on all images in process (and must be |
| 301 | supported by all images). |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 302 | |
| 303 | #### Heap Terminate: |
| 304 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 305 | * >= Win8 |
| 306 | * Terminates the process on Windows heap corruption. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 307 | |
| 308 | #### Bottom-up ASLR: |
| 309 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 310 | * >= Win8 |
| 311 | * Sets random lower bound as minimum user address for the process. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 312 | |
| 313 | #### High-entropy ASLR: |
| 314 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 315 | * >= Win8 |
| 316 | * Increases randomness range for bottom-up ASLR to 1TB. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 317 | |
| 318 | #### Strict Handle Checks: |
| 319 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 320 | * >= Win8 |
| 321 | * Immediately raises an exception on a bad handle reference. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 322 | |
| 323 | #### Win32k.sys lockdown: |
| 324 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 325 | * >= Win8 |
| 326 | * `ProcessSystemCallDisablePolicy`, which allows selective disabling of system |
| 327 | calls available from the target process. |
| 328 | * Renderer processes now have this set to `DisallowWin32kSystemCalls` which |
| 329 | means that calls from user mode that are serviced by `win32k.sys` are no |
| 330 | longer permitted. This significantly reduces the kernel attack surface |
| 331 | available from a renderer. See |
| 332 | [here](https://docs.google.com/document/d/1gJDlk-9xkh6_8M_awrczWCaUuyr0Zd2TKjNBCiPO_G4) |
| 333 | for more details. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 334 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 335 | #### Disable Extension Points (legacy hooking): |
| 336 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 337 | * >= Win8 |
| 338 | * `ProcessExtensionPointDisablePolicy` |
| 339 | * The following injection vectors are blocked: |
| 340 | * AppInit DLLs Winsock Layered Service Providers (LSPs) |
| 341 | * Global Window Hooks (not thread-targeted hooks) |
| 342 | * Legacy Input Method Editors (IMEs) |
Alex Gough | 665e875 | 2023-01-25 01:29:37 | [diff] [blame] | 343 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 344 | #### Control Flow Guard (CFG): |
| 345 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 346 | * >= Win8.1 Update 3 (KB3000850) |
| 347 | * Enabled in all chrome.exe processes. Not compiled into all chrome binaries. |
| 348 | * Takes advantage of CFG security in Microsoft system DLLs in our processes. |
| 349 | * Compiler/Linker opt-in, not a run-time policy opt-in. See |
| 350 | [MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065\(v=vs.85\).aspx). |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 351 | |
Vitaly Buka | 5987fd4 | 2020-10-20 22:58:05 | [diff] [blame] | 352 | #### CET Shadow Stack: |
| 353 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 354 | * Available in Windows 10 2004 December Update. |
| 355 | * Is not enabled in the renderer. See |
| 356 | [ticket](https://bugs.chromium.org/p/chromium/issues/detail?id=1136224), |
| 357 | [MSDN](https://docs.microsoft.com/en-us/cpp/build/reference/cetcompat?view=vs-2019). |
Vitaly Buka | 5987fd4 | 2020-10-20 22:58:05 | [diff] [blame] | 358 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 359 | #### Disable Font Loading: |
| 360 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 361 | * >= Win10 |
| 362 | * `ProcessFontDisablePolicy` |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 363 | |
Will Harris | 0dbe1dc | 2019-08-23 02:25:48 | [diff] [blame] | 364 | #### Disable Loading of Unsigned Code (CIG): |
| 365 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 366 | * >= Win10 TH2 |
| 367 | * `ProcessSignaturePolicy` |
| 368 | * Prevents loading unsigned code into our processes. This means attackers |
| 369 | can't just LoadLibrary a DLL after gaining execution (which shouldn't be |
| 370 | possible anyway due to other sandbox mitigations), but more importantly, |
| 371 | prevents third party DLLs from being injected into our processes, which can |
| 372 | affect stability and our ability to enable other security mitigations. |
| 373 | * Enabled (post-startup) for all sandboxed child processes. |
| 374 | * Enabled (pre-startup) for sandboxed renderer processes. This eliminates a |
| 375 | process launch time gap where local injection of improperly signed DLLs into |
| 376 | a renderer process could occur. |
| 377 | * See |
| 378 | [msedgedev blog](https://blogs.windows.com/msedgedev/2017/02/23/mitigating-arbitrary-native-code-execution/) |
| 379 | for more background on this mitigation. |
Will Harris | 0dbe1dc | 2019-08-23 02:25:48 | [diff] [blame] | 380 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 381 | #### Disable Image Load from Remote Devices: |
| 382 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 383 | * >= Win10 TH2 |
| 384 | * `ProcessImageLoadPolicy` |
| 385 | * E.g. UNC path to network resource. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 386 | |
| 387 | #### Disable Image Load of "mandatory low" (low integrity level): |
| 388 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 389 | * >= Win10 TH2 |
| 390 | * `ProcessImageLoadPolicy` |
| 391 | * E.g. temporary internet files. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 392 | |
| 393 | #### Extra Disable Child Process Creation: |
| 394 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 395 | * >= Win10 TH2 |
| 396 | * If the Job level <= `JOB_LIMITED_USER`, set |
| 397 | `PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY` to |
| 398 | `PROCESS_CREATION_CHILD_PROCESS_RESTRICTED` via |
| 399 | `UpdateProcThreadAttribute()`. |
| 400 | * This is an extra layer of defense, given that Job levels can be broken out |
| 401 | of. See also: |
| 402 | [ticket](https://bugs.chromium.org/p/project-zero/issues/detail?id=213&redir=1), |
| 403 | [Project Zero blog](http://googleprojectzero.blogspot.co.uk/2015/05/in-console-able.html). |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 404 | |
Will Harris | c7e6edf | 2024-05-22 23:19:48 | [diff] [blame] | 405 | #### Disable Dynamic Code (ACG): |
| 406 | |
| 407 | * >= Windows 10 RS1 |
| 408 | * `ProcessDynamicCodePolicy` - Also known as Arbitrary Code Guard (ACG). |
| 409 | * With ACG enabled, the Windows kernel prevents a process from creating and |
| 410 | modifying code pages in memory by enforcing that all code pages are |
| 411 | immutable and new unsigned code pages cannot be created. This will cause |
| 412 | code that attempts to modify or inject into these processes to fail, such as |
| 413 | certain attempts to corrupt browser memory, and some third party DLLs. |
| 414 | * This is enabled by default for sandboxed service utility processes, and for |
| 415 | sandboxed renderer processes that perform no JIT (just-in-time) compilation, |
| 416 | and can be enabled for the browser process via the |
| 417 | `BrowserDynamicCodeDisabled` feature. |
| 418 | |
Will Harris | 7dba881 | 2021-12-07 16:13:07 | [diff] [blame] | 419 | ### App Container (low box token): |
| 420 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 421 | * In Windows this is implemented at the kernel level by a Low Box token which |
| 422 | is a stripped version of a normal token with limited privilege (normally |
| 423 | just `SeChangeNotifyPrivilege` and `SeIncreaseWorkingSetPrivilege`), running |
| 424 | at Low integrity level and an array of "Capabilities" which can be mapped to |
| 425 | allow/deny what the process is allowed to do (see |
| 426 | [MSDN](https://msdn.microsoft.com/en-us/library/windows/apps/hh464936.aspx) |
| 427 | for a high level description). The capability most interesting from a |
| 428 | sandbox perspective is denying is access to the network, as it turns out |
| 429 | network checks are enforced if the token is a Low Box token and the |
| 430 | `INTERNET_CLIENT` Capability is not present. |
| 431 | * The sandbox therefore takes the existing restricted token and adds the Low |
| 432 | Box attributes, without granting any Capabilities, so as to gain the |
| 433 | additional protection of no network access from the sandboxed process. |
Will Harris | 7dba881 | 2021-12-07 16:13:07 | [diff] [blame] | 434 | |
| 435 | ### Less Privileged App Container (LPAC) |
| 436 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 437 | * An extension of the App Container (see above) available on later versions of |
| 438 | Windows 10 (RS2 and greater), the Less Privileged App Container (LPAC) runs |
| 439 | at a lower privilege level than normal App Container, with access granted by |
| 440 | default to only those kernel, filesystem and registry objects marked with |
| 441 | the `ALL RESTRICTED APPLICATION PACKAGES` or a specific package SID. This is |
| 442 | opposed to App Container which uses `ALL APPLICATION PACKAGES`. |
| 443 | * A key characteristic of the LPAC is that specific named capabilities can be |
| 444 | added such as those based on well known SIDs (defined in |
| 445 | [`base/win/sid.h`](https://cs.chromium.org/chromium/src/base/win/sid.h)) or |
| 446 | via 'named capabilities' resolved through call to |
| 447 | [DeriveCapabilitySidsFromName](https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-derivecapabilitysidsfromname) |
| 448 | which are not really strictly defined anywhere but can be found in various |
| 449 | [places](https://social.technet.microsoft.com/Forums/scriptcenter/en-US/3e7d85e3-d0e1-4e79-8141-0bbf8faf3644/windows-10-anniversary-update-the-case-of-the-mysterious-account-sid-causing-the-flood-of-dcom?forum=win10itprosetup) |
| 450 | and include capabilities such as: |
| 451 | * `lpacCom` |
| 452 | * `registryRead` |
| 453 | * `lpacWebPlatform` |
| 454 | * `lpacClipboard` |
| 455 | * etc... |
| 456 | * Each LPAC process can have a process-specific SID created for it and |
| 457 | this can be used to protect files specific to that particular sandbox, |
| 458 | and there can be multiple different overlapping sets of access rights |
| 459 | depending on the interactions between services running in different |
| 460 | sandboxes. |
Will Harris | 7dba881 | 2021-12-07 16:13:07 | [diff] [blame] | 461 | |
| 462 | #### LPAC File System Permissions |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 463 | |
| 464 | * Importantly, all locations in the filesystem and registry that the LPAC |
| 465 | process will access during its lifetime need to have the right ACLs on them. |
| 466 | `registryRead` is important for registry read access, and Windows system |
| 467 | files have `ALL RESTRICTED APPLICATION PACKAGES` ACE on them already, but |
| 468 | other files that the sandbox process needs access to including the binaries |
| 469 | (e.g. chrome.exe, chrome.dll) and also any data files need ACLs to be laid |
| 470 | down. This is typically done by the installer, and also done automatically |
| 471 | for tests. However, if the LPAC sandbox is to be used in other environments |
| 472 | then these filesystem permissions need to be manually laid down using |
| 473 | `icacls`, the installer, or a similar tool. An example of a ACE that could |
| 474 | be used can be found in |
| 475 | [`testing/scripts/common.py`](https://cs.chromium.org/chromium/src/testing/scripts/common.py) |
| 476 | however in high security environments a more restrictive SID should be used |
| 477 | such as one from the |
| 478 | [installer](https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/setup/install_worker.cc;l=74). |
Will Harris | 7dba881 | 2021-12-07 16:13:07 | [diff] [blame] | 479 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 480 | ### Other caveats |
| 481 | |
| 482 | The operating system might have bugs. Of interest are bugs in the Windows API |
| 483 | that allow the bypass of the regular security checks. If such a bug exists, |
| 484 | malware will be able to bypass the sandbox restrictions and broker policy and |
| 485 | possibly compromise the computer. Under Windows, there is no practical way to |
| 486 | prevent code in the sandbox from calling a system service. |
| 487 | |
| 488 | In addition, third party software, particularly anti-malware solutions, can |
| 489 | create new attack vectors. The most troublesome are applications that inject |
| 490 | dlls in order to enable some (usually unwanted) capability. These dlls will also |
| 491 | get injected in the sandbox process. In the best case they will malfunction, and |
| 492 | in the worst case can create backdoors to other processes or to the file system |
| 493 | itself, enabling specially crafted malware to escape the sandbox. |
| 494 | |
| 495 | ## Sandbox policy |
| 496 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 497 | The actual restrictions applied to a target process are configured by a policy. |
| 498 | The policy is just a programmatic interface that the broker calls to define the |
| 499 | restrictions and allowances. Four functions control the restrictions, roughly |
| 500 | corresponding to the four Windows mechanisms: |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 501 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 502 | * `TargetPolicy::SetTokenLevel()` |
| 503 | * `TargetPolicy::SetJobLevel()` |
| 504 | * `TargetPolicy::SetIntegrityLevel()` |
| 505 | * `TargetPolicy::SetDesktop()` |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 506 | |
| 507 | The first three calls take an integer level parameter that goes from very strict |
| 508 | to very loose; for example, the token level has 7 levels and the job level has 5 |
| 509 | levels. Chromium renderers are typically run with the most strict level in all |
| 510 | four mechanisms. Finally, the last (desktop) policy is binary and can only be |
| 511 | used to indicate if a target is run on an alternate desktop or not. |
| 512 | |
| 513 | The restrictions are by design coarse in that they affect all securable |
| 514 | resources that the target can touch, but sometimes a more finely-grained |
| 515 | resolution is needed. The policy interface allows the broker to specify |
| 516 | exceptions. An exception is a way to take a specific Windows API call issued in |
| 517 | the target and proxy it over to the broker. The broker can inspect the |
| 518 | parameters and re-issue the call as is, re-issue the call with different |
| 519 | parameters, or simply deny the call. To specify exceptions there is a single |
| 520 | call: `AddRule`. The following kinds of rules for different Windows subsystems |
| 521 | are supported at this time: |
| 522 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 523 | * Files |
| 524 | * Named pipes |
| 525 | * Process creation |
| 526 | * Registry |
| 527 | * Synchronization objects |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 528 | |
| 529 | The exact form of the rules for each subsystem varies, but in general rules are |
| 530 | triggered based on a string pattern. For example, a possible file rule is: |
| 531 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 532 | ``` |
| 533 | AddRule(SUBSYS_FILES, FILES_ALLOW_READONLY, L"c:\\temp\\app_log\\d*.dmp") |
| 534 | ``` |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 535 | |
| 536 | This rule specifies that access will be granted if a target wants to open a |
| 537 | file, for read-only access as long as the file matches the pattern expression; |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 538 | for example `c:\temp\app_log\domino.dmp` is a file that satisfies the pattern. |
| 539 | Consult the header files for an up-to-date list of supported objects and |
| 540 | supported actions. |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 541 | |
| 542 | Rules can only be added before each target process is spawned, and cannot be |
| 543 | modified while a target is running, but different targets can have different |
| 544 | rules. |
| 545 | |
Alex Gough | 9e88d86 | 2020-06-05 18:20:39 | [diff] [blame] | 546 | ### Diagnostics |
| 547 | |
| 548 | In Chromium, the policies associated with active processes can be viewed at |
| 549 | chrome://sandbox. Tracing of the `sandbox` category will output the policy used |
| 550 | when a process is launched. Tracing can be enabled using chrome://tracing or by |
| 551 | using the `--trace-startup=-*,disabled-by-default-sandbox` command line flag. |
| 552 | Trace output can be investigated with `//tools/win/trace-sandbox-viewer.py`. |
| 553 | |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 554 | ## Target bootstrapping |
| 555 | |
| 556 | Targets do not start executing with the restrictions specified by policy. They |
| 557 | start executing with a token that is very close to the token the regular user |
| 558 | processes have. The reason is that during process bootstrapping the OS loader |
| 559 | accesses a lot of resources, most of them are actually undocumented and can |
| 560 | change at any time. Also, most applications use the standard CRT provided with |
| 561 | the standard development tools; after the process is bootstrapped the CRT needs |
| 562 | to initialize as well and there again the internals of the CRT initialization |
| 563 | are undocumented. |
| 564 | |
| 565 | Therefore, during the bootstrapping phase the process actually uses two tokens: |
| 566 | the lockdown token which is the process token as is and the initial token which |
| 567 | is set as the impersonation token of the initial thread. In fact the actual |
| 568 | `SetTokenLevel` definition is: |
| 569 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 570 | ``` |
| 571 | SetTokenLevel(TokenLevel initial, TokenLevel lockdown) |
| 572 | ``` |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 573 | |
| 574 | After all the critical initialization is done, execution continues at `main()` |
| 575 | or `WinMain()`, here the two tokens are still active, but only the initial |
| 576 | thread can use the more powerful initial token. It is the target's |
| 577 | responsibility to discard the initial token when ready. This is done with a |
| 578 | single call: |
| 579 | |
Will Harris | 9249617 | 2024-05-22 21:54:13 | [diff] [blame] | 580 | ``` |
| 581 | LowerToken() |
| 582 | ``` |
justincarlson | b4730a0c | 2017-04-20 20:22:13 | [diff] [blame] | 583 | |
| 584 | After this call is issued by the target the only token available is the lockdown |
| 585 | token and the full sandbox restrictions go into effect. The effects of this call |
| 586 | cannot be undone. Note that the initial token is a impersonation token only |
| 587 | valid for the main thread, other threads created in the target process use only |
| 588 | the lockdown token and therefore should not attempt to obtain any system |
| 589 | resources subject to a security check. |
| 590 | |
| 591 | The fact that the target starts with a privileged token simplifies the explicit |
| 592 | policy since anything privileged that needs to be done once, at process startup |
| 593 | can be done before the `LowerToken()` call and does not require to have rules in |
| 594 | the policy. |
| 595 | |
| 596 | **Important** |
| 597 | |
| 598 | Make sure any sensitive OS handles obtained with the initial token are closed |
| 599 | before calling LowerToken(). Any leaked handle can be abused by malware to |
| 600 | escape the sandbox. |