restricted_token_test.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Integration tests for restricted tokens.
  5. #include <stddef.h>
  6. #include <string>
  7. #include "base/strings/stringprintf.h"
  8. #include "base/win/access_token.h"
  9. #include "base/win/scoped_handle.h"
  10. #include "sandbox/win/src/sandbox.h"
  11. #include "sandbox/win/src/sandbox_factory.h"
  12. #include "sandbox/win/src/target_services.h"
  13. #include "sandbox/win/tests/common/controller.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. namespace sandbox {
  17. namespace {
  18. int RunOpenProcessTest(bool unsandboxed,
  19. bool lockdown_dacl,
  20. DWORD access_mask) {
  21. TestRunner runner(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS,
  22. USER_LOCKDOWN);
  23. runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED);
  24. runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
  25. if (lockdown_dacl)
  26. runner.GetPolicy()->SetLockdownDefaultDacl();
  27. runner.SetAsynchronous(true);
  28. // This spins up a renderer level process, we don't care about the result.
  29. runner.RunTest(L"IntegrationTestsTest_args 1");
  30. TestRunner runner2(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS,
  31. USER_LIMITED);
  32. runner2.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
  33. runner2.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
  34. runner2.SetUnsandboxed(unsandboxed);
  35. return runner2.RunTest(
  36. base::StringPrintf(L"RestrictedTokenTest_openprocess %d 0x%08X",
  37. runner.process_id(), access_mask)
  38. .c_str());
  39. }
  40. int RunRestrictedOpenProcessTest(bool unsandboxed,
  41. bool lockdown_dacl,
  42. DWORD access_mask) {
  43. TestRunner runner(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS, USER_LIMITED);
  44. runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
  45. runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
  46. if (lockdown_dacl) {
  47. runner.GetPolicy()->SetLockdownDefaultDacl();
  48. runner.GetPolicy()->AddRestrictingRandomSid();
  49. }
  50. runner.SetAsynchronous(true);
  51. // This spins up a GPU level process, we don't care about the result.
  52. runner.RunTest(L"IntegrationTestsTest_args 1");
  53. TestRunner runner2(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS,
  54. USER_LIMITED);
  55. runner2.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
  56. runner2.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
  57. runner2.SetUnsandboxed(unsandboxed);
  58. return runner2.RunTest(
  59. base::StringPrintf(L"RestrictedTokenTest_openprocess %d 0x%08X",
  60. runner.process_id(), access_mask)
  61. .c_str());
  62. }
  63. int RunRestrictedSelfOpenProcessTest(bool add_random_sid, DWORD access_mask) {
  64. TestRunner runner(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS, USER_LIMITED);
  65. runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
  66. runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
  67. runner.GetPolicy()->SetLockdownDefaultDacl();
  68. if (add_random_sid)
  69. runner.GetPolicy()->AddRestrictingRandomSid();
  70. return runner.RunTest(
  71. base::StringPrintf(L"RestrictedTokenTest_currentprocess_dup 0x%08X",
  72. access_mask)
  73. .c_str());
  74. }
  75. } // namespace
  76. // Opens a process based on a PID and access mask passed on the command line.
  77. // Returns SBOX_TEST_SUCCEEDED if process opened successfully.
  78. SBOX_TESTS_COMMAND int RestrictedTokenTest_openprocess(int argc,
  79. wchar_t** argv) {
  80. if (argc < 2)
  81. return SBOX_TEST_NOT_FOUND;
  82. DWORD pid = _wtoi(argv[0]);
  83. if (pid == 0)
  84. return SBOX_TEST_NOT_FOUND;
  85. DWORD desired_access = wcstoul(argv[1], nullptr, 0);
  86. base::win::ScopedHandle process_handle(
  87. ::OpenProcess(desired_access, false, pid));
  88. if (process_handle.IsValid())
  89. return SBOX_TEST_SUCCEEDED;
  90. return SBOX_TEST_DENIED;
  91. }
  92. // Opens a process through duplication. This is to avoid the OpenProcess hook.
  93. SBOX_TESTS_COMMAND int RestrictedTokenTest_currentprocess_dup(int argc,
  94. wchar_t** argv) {
  95. if (argc < 1)
  96. return SBOX_TEST_NOT_FOUND;
  97. DWORD desired_access = wcstoul(argv[0], nullptr, 0);
  98. HANDLE dup_handle;
  99. if (!::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentProcess(),
  100. ::GetCurrentProcess(), &dup_handle, 0, FALSE, 0)) {
  101. return SBOX_TEST_FIRST_ERROR;
  102. }
  103. base::win::ScopedHandle process_handle(dup_handle);
  104. if (::DuplicateHandle(::GetCurrentProcess(), process_handle.Get(),
  105. ::GetCurrentProcess(), &dup_handle, desired_access,
  106. FALSE, 0)) {
  107. ::CloseHandle(dup_handle);
  108. return SBOX_TEST_SUCCEEDED;
  109. }
  110. if (::GetLastError() != ERROR_ACCESS_DENIED)
  111. return SBOX_TEST_SECOND_ERROR;
  112. return SBOX_TEST_DENIED;
  113. }
  114. // Opens a the process token and checks if it's restricted.
  115. SBOX_TESTS_COMMAND int RestrictedTokenTest_IsRestricted(int argc,
  116. wchar_t** argv) {
  117. absl::optional<base::win::AccessToken> token =
  118. base::win::AccessToken::FromCurrentProcess();
  119. if (!token)
  120. return SBOX_TEST_FIRST_ERROR;
  121. return token->RestrictedSids().size() > 0 ? SBOX_TEST_SUCCEEDED
  122. : SBOX_TEST_FAILED;
  123. }
  124. TEST(RestrictedTokenTest, OpenLowPrivilegedProcess) {
  125. // Test limited privilege to renderer open.
  126. ASSERT_EQ(SBOX_TEST_SUCCEEDED,
  127. RunOpenProcessTest(false, false, GENERIC_READ | GENERIC_WRITE));
  128. // Test limited privilege to renderer open with lockdowned DACL.
  129. ASSERT_EQ(SBOX_TEST_DENIED,
  130. RunOpenProcessTest(false, true, GENERIC_READ | GENERIC_WRITE));
  131. // Ensure we also can't get any access to the process.
  132. ASSERT_EQ(SBOX_TEST_DENIED, RunOpenProcessTest(false, true, MAXIMUM_ALLOWED));
  133. // Also check for explicit owner allowed WRITE_DAC right.
  134. ASSERT_EQ(SBOX_TEST_DENIED, RunOpenProcessTest(false, true, WRITE_DAC));
  135. // Ensure unsandboxed process can still open the renderer for all access.
  136. ASSERT_EQ(SBOX_TEST_SUCCEEDED,
  137. RunOpenProcessTest(true, true, PROCESS_ALL_ACCESS));
  138. }
  139. TEST(RestrictedTokenTest, CheckNonAdminRestricted) {
  140. TestRunner runner(JobLevel::kNone, USER_RESTRICTED_SAME_ACCESS,
  141. USER_RESTRICTED_NON_ADMIN);
  142. EXPECT_EQ(SBOX_TEST_SUCCEEDED,
  143. runner.RunTest(L"RestrictedTokenTest_IsRestricted"));
  144. }
  145. TEST(RestrictedTokenTest, OpenProcessSameSandboxRandomSid) {
  146. // Test process to process open when not using random SID.
  147. ASSERT_EQ(SBOX_TEST_SUCCEEDED,
  148. RunRestrictedOpenProcessTest(false, false, GENERIC_ALL));
  149. // Test process to process open when using random SID.
  150. ASSERT_EQ(SBOX_TEST_DENIED,
  151. RunRestrictedOpenProcessTest(false, true, MAXIMUM_ALLOWED));
  152. // Test process to process open when not using random SID and opening from
  153. // unsandboxed.
  154. ASSERT_EQ(SBOX_TEST_SUCCEEDED,
  155. RunRestrictedOpenProcessTest(true, false, GENERIC_ALL));
  156. // Test process to process open when using random SID and opening from
  157. // unsandboxed.
  158. ASSERT_EQ(SBOX_TEST_SUCCEEDED,
  159. RunRestrictedOpenProcessTest(true, true, GENERIC_ALL));
  160. }
  161. TEST(RestrictedTokenTest, OpenProcessSelfRandomSid) {
  162. // Test process can't open self when not using random SID.
  163. ASSERT_EQ(SBOX_TEST_DENIED,
  164. RunRestrictedSelfOpenProcessTest(false, PROCESS_ALL_ACCESS));
  165. // Test process can open self when using random SID.
  166. ASSERT_EQ(SBOX_TEST_SUCCEEDED,
  167. RunRestrictedSelfOpenProcessTest(true, PROCESS_ALL_ACCESS));
  168. }
  169. } // namespace sandbox