Changeset 58402 in vbox
- Timestamp:
- Oct 24, 2015 9:51:55 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
r58385 r58402 31 31 * 32 32 * The VirtualBox VMM requires supervisor (kernel) level access to the CPU. For 33 * both practical and historical reasons , part of the VMM is still implemented34 * in ring-3 and has a rich interface to the kernel part. While the device35 * emulations can be run allin ring-3, we have performance optimizations that33 * both practical and historical reasons part of the VMM is partly realized in 34 * ring-3 with a rich interface to the kernel part. While the device emulations 35 * can be run exclusively in ring-3, we have performance optimizations that 36 36 * loads device emulation code into ring-0 and our special raw-mode execution 37 * context (non-VT-x/AMD-V mode) for handling frequent operations. These share 38 * data between all three context (ring-3, ring-0 and raw-mode). All this poses 39 * a rather broad attack surface, which the hardening protects. 37 * context (non-VT-x/AMD-V mode) for handling frequent operations a lot more 38 * efficiently. These share data between all three context (ring-3, ring-0 and 39 * raw-mode). All this poses a rather broad attack surface, which the hardening 40 * protects. 40 41 * 41 42 * The hardening primarily focuses on restricting access to the support driver, 42 43 * VBoxDrv or vboxdrv depending on the OS, as it is ultimately the link and 43 44 * instigator of the communication between ring-3 and the ring-0 and raw-mode 44 * contexts. A secondary focus is to make sure malicious code cannot be loaded45 * contexts. A secondary focus is to make sure malicious code cannot be loaded 45 46 * and executed in the VM process. Exactly how we go about this depends a lot 46 47 * on the host OS. … … 49 50 * @section sec_hardening_unix Hardening on UNIX-like OSes 50 51 * 51 * On UNIX-like systems (Solaris, Linux, darwin, freebsd, ...) only allow root 52 * to get full unrestricted access to the support driver. The device node 53 * corresponding to unrestricted access is owned by root and has a 0600 access 54 * mode (i.e. only accessible to the owner, root). In addition to this file 55 * system level restriction, the support driver also checks that the effective 56 * user ID (EUID) is root when it is being opened. 52 * On UNIX-like systems (Solaris, Linux, darwin, freebsd, ...) we put our trust 53 * in root and the root knows what he/she/it does. 54 * 55 * We only allow root to get full unrestricted access to the support driver. 56 * The device node corresponding to unrestricted access is own by root and has a 57 * 0600 access mode (i.e. only accessible to the owner, root). In addition to 58 * this file system level restriction, the support driver also checks that the 59 * effective user ID (EUID) is root when it is being opened. 57 60 * 58 61 * The VM processes temporarily assume root privileges using the set-uid-bit on 59 * the executable with root as owner. In fact, all the executable files, shared60 * objects and the other files and directories we install are owned by root and61 * the wheel (or equivalent gid = 0) group.62 * the executable with root as owner. In fact, all the files and directories we 63 * install are owned by root and the wheel (or equivalent gid = 0) group, 64 * including extension pack files. 62 65 * 63 66 * The executable with the set-uid-to-root-bit set is a stub binary that has no 64 * unnecessary library dependencies (only libc) and simply calls 65 * #SUPR3HardenedMain. SUPR3HardenedMain does the following: 66 * 67 * -# Validate installation (supR3HardenedVerifyAll): 67 * unnecessary library dependencies (only libc, pthreads, dynamic linker) and 68 * simply calls #SUPR3HardenedMain. It does the following: 69 * 1. Validate installation (supR3HardenedVerifyAll): 68 70 * - Check that the executable file of the process is one of the known 69 71 * VirtualBox executables. … … 73 75 * anyone except root. 74 76 * - Check that all the parent directories, all the way up to the root 75 * if possible, only permits root (or system admin) to change them - 76 * in order to exclude directory renaming races. 77 * - On systems where it is possible, we may also validate signatures. 78 * 79 * -# Open a file descriptor for the support device driver 77 * if possible, only permits root (or system admin) to change them. 78 * This is that to rule out unintentional rename races. 79 * - On systems where it is possible, we may also valiadate executable 80 * image signatures. 81 * 82 * 2. Open a file descriptor for the support device driver 80 83 * (supR3HardenedMainOpenDevice). 81 84 * 82 * -#Grab ICMP capabilities, if needed (supR3HardenedMainGrabCapabilites).83 * 84 * -#Correctly drop the root privileges (supR3HardenedMainDropPrivileges).85 * 86 * -#Load the VBoxRT dynamic link library and hand over the file85 * 3. Grab ICMP capabilities, if needed (supR3HardenedMainGrabCapabilites). 86 * 87 * 4. Correctly drop the root privileges (supR3HardenedMainDropPrivileges). 88 * 89 * 5. Load the VBoxRT dynamic link library and hand over the file 87 90 * descriptor to the SUPLib code in it (supR3HardenedMainInitRuntime). 88 91 * 89 * -# Load a dynamic library containing the VM frontend code and run it90 * (tail of SUPR3HardenedMain). The set-uid-to-root stub executable is91 * paired with a dynamic link library which exports one TrustedMain92 * entrypoint (see FNSUPTRUSTEDMAIN) that we call.93 * 94 * In case of error reporting, the library may also export a95 * TrustedErrorfunction (FNSUPTRUSTEDERROR).96 * 97 * That a process was started with a set-uid-to-root-bit applied is something98 * that sticks with the process even if after dropping the root privileges and99 * becoming the original user. The dynamic linkers take special care when100 * dealing with processes of this kind to not allow the user to load arbitrary101 * code into a root process and causing a privilege escalation issue. This is102 * of courseexactly the kind of behavior we're looking for.92 * 6. Load a dynamic library containing the actual VM frontend code and run 93 * it (tail of SUPR3HardenedMain). 94 * 95 * The set-uid-to-root stub executable is paired with a dynamic link library 96 * which export one TrustedMain entrypoint (see FNSUPTRUSTEDMAIN) that we call. 97 * In case of error reporting, the library may also export a TrustedError 98 * function (FNSUPTRUSTEDERROR). 99 * 100 * That the set-uid-to-root-bit modifies the dynamic linker behavior on all 101 * relevant systems, even after we've dropped back to the real UI, is something 102 * we take advantage of. The dynamic linkers takes special care to prevent 103 * users from using clever tricks to inject their own code into set-uid 104 * processes and causing privilege escalation issues. This is of course 105 * exactly the kind of behavior we're looking for. 103 106 * 104 107 * In addition to what the dynamic linker does for us, we will not directly 105 108 * call either RTLdrLoad or dlopen to load dynamic link libraries into the 106 109 * process. Instead we will call SUPR3HardenedLdrLoad, 107 * SUPR3HardenedLdrLoadAppPriv or SUPR3HardenedLdrLoadPlugIn to do the loading. 108 * These functions will perform the validations on the file being loaded as 109 * SUPR3HardenedMain did in its validation step. So, anything we load must be 110 * installed owned by root:wheel, the directory we load it from must also be 111 * owned by root:wheel and not allow for renaming the file. Similar ownership 112 * restrictions apply to all the parent directories (except on darwin). 113 * 114 * So, we leave the responsibility of not installing malicious software on the 110 * SUPR3HardenedLdrLoadAppPriv and SUPR3HardenedLdrLoadPlugIn to do the 111 * loading. These functions will perform the validations on the file being 112 * loaded as SUPR3HardenedMain did in its validation step. So, anything we 113 * load must be installed owned by root:wheel, the directory we load it from 114 * must also be owned by root:wheel and now allow for renaming the file. 115 * Similar ownership restricts applies to all the parent directories (except on 116 * darwin). 117 * 118 * So, we place the responsibility of not installing malicious software on the 115 119 * root user on UNIX-like systems. Which is fair enough, in our opinion. 116 120 * … … 118 122 * @section sec_hardening_win Hardening on Windows 119 123 * 120 * On Windows things are a lot more complicated, unfortunately. This is mainly 121 * because on Windows you cannot trust the Administrators users. Some of the 122 * blame for this is that Windows is a descendant/replacement for a set of single 123 * user systems: DOS, Windows 1.0-3.11 Windows 95-ME, and OS/2. Users of NT 124 * 3.51 and later were inclined to want to always run it with full 125 * root/administrator privileges like they had done on the predecessors, which 126 * Microsoft made doing very simple and didn't help with the alternative. 127 * Bad idea, security wise, which is good for the security software industry. 128 * For this reason, using a set-uid-to-root approach is pointless, even if 129 * Windows had one, which it doesn't. 124 * On Windows we cannot put the same level or trust in the Administrator users 125 * (equivalent of root/wheel on unix) as on the UNIX-like systems, which 126 * complicates things greatly. 127 * 128 * Some or the blame for this can be given to Windows being a 129 * descendant/replacement for a set of single user systems: DOS, Windows 130 * 1.0-3.11 Windows 95-ME, and OS/2. Users of NT 3.51 and later was inclined to 131 * want to always run it with full root/administrator privileges like they had 132 * done on the predecessors, while Microsoft made doing this very simple and 133 * didn't help with the alternatives. Bad idea, security wise, which is good 134 * for the security software industry. For this reason using a set-uid-to-root 135 * approach is pointless, even if windows had one, which is doesn't. 130 136 * 131 137 * So, in order to protect access to the support driver and protect the 132 138 * VM process while it's running we have to do a lot more work. A keystone in 133 139 * the defences is code signing. The short version is this: 134 *135 140 * - Minimal stub executable, signed with the same certificate as the 136 141 * kernel driver. … … 148 153 * thoroughly before allowing them protection and in the final case full 149 154 * unrestricted access. 155 * 156 * @subsection sec_hardening_win_protsoft 3rd Party "Protection" Software 150 157 * 151 158 * What makes our life REALLY difficult on Windows is this 3rd party "security" … … 156 163 * common practice to patch a lot of NTDLL, KERNEL32, the executable import 157 164 * table, load extra DLLs into the process, allocate executable memory in the 158 * process and worse. The BIG problem with all this is that it is 159 * indistinguishable from what malicious software would be doing in order to 160 * intercept process activity (network sniffing, maybe password snooping) or 161 * gain a level of kernel access via the support driver. 165 * process (classic code injection) and more. 166 * 167 * The BIG problem with all this is that it is indistiguishable from what 168 * malicious software would be doing in order to intercept process acctivity 169 * (network sniffing, maybe password snooping) or gain a level of kernel access 170 * via the the support driver. 171 * 172 * 173 * @subsection sec_hardening_win_1st_stub The Initial Stub Process 162 174 * 163 175 * We share the stub executable approach with the UNIX-like systems, so there's 164 176 * the SUPR3HardenedMain and a paired DLL with TrustedMain and TrustedError. 165 * However, the stub executable is pushed a bit further here.177 * However, the stub executable is fatter and much more bare metal: 166 178 * - It has no CRT (libc) because we don't need one and we need full 167 179 * control over the code in the stub. … … 180 192 * does a respawn via supR3HardenedWinReSpawn. 181 193 * 182 * The second stub process will be created in suspended state (the thread hasn't 183 * executed a single instruction) and with less generous ACLs associated with it 184 * (skin deep protection only). In order for SUPR3TrustedMain to figure it's 185 * the second stub process, the zero'th command line argument has been replaced 186 * by a known magic string (UUID). Now, before the process starts executing, 187 * the parent will patch the LdrInitializeThunk entrypoint in NTDLL to call 188 * supR3HardenedEarlyProcessInit via supR3HardenedEarlyProcessInitThunk. The 189 * parent will also plant some synchronization stuff via SUPR3WINPROCPARAMS 190 * (NTDLL location, inherited event handles and associated ping-pong equipment). 194 * 195 * @subsection sec_hardening_win_2nd_stub The Second Stub Process 196 * 197 * The second stub process will be created in suspended state, i.e. the main 198 * thread is suspended before it executes a single instruction, and with a less 199 * generous ACLs associated with it (skin deep protection only). In order for 200 * SUPR3TrustedMain to figure that it is the second stub process, the zero'th 201 * command line argument has been replaced by a known magic string (UUID). Now, 202 * before the process starts executing, the parent (initial stub) will patch the 203 * LdrInitializeThunk entrypoint in NTDLL to call supR3HardenedEarlyProcessInit 204 * via supR3HardenedEarlyProcessInitThunk. The parent will also plant some 205 * synchronization stuff via SUPR3WINPROCPARAMS (NTDLL location, inherited event 206 * handles and associated ping-pong equipment). 191 207 * 192 208 * The LdrInitializeThunk entrypoint of NTDLL is where the kernel sets up … … 206 222 * What the parent does during the purification is very similar to what the 207 223 * kernel driver will do later on when verifying the second stub and the VM 208 * processes, except that instead of failing when encountering an issue it will209 * take corrective actions:224 * processes, except that instead of failing when encountering an shortcomming 225 * it will take corrective actions: 210 226 * - Executable memory regions not belonging to a DLL mapping will be 211 227 * attempted freed, and we'll only fail if we can't evict it. … … 264 280 * 265 281 * 282 * @subsection sec_hardening_win_3rd_stub The Final Stub 283 * 284 * Yet to be written... 266 285 * 267 286 */
Note:
See TracChangeset
for help on using the changeset viewer.