Index: sandbox/win/src/process_mitigations_imageload_unittest.cc |
diff --git a/sandbox/win/src/process_mitigations_imageload_unittest.cc b/sandbox/win/src/process_mitigations_imageload_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..41c652e328052d54ec708203dcd0e9a8505d9909 |
--- /dev/null |
+++ b/sandbox/win/src/process_mitigations_imageload_unittest.cc |
@@ -0,0 +1,248 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "sandbox/win/src/process_mitigations.h" |
+ |
+#include <windows.h> |
+ |
+#include "base/files/file_util.h" |
+#include "base/files/scoped_temp_dir.h" |
+#include "base/path_service.h" |
+#include "base/scoped_native_library.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/test/test_timeouts.h" |
+#include "base/win/windows_version.h" |
+#include "sandbox/win/src/sandbox.h" |
+#include "sandbox/win/src/target_services.h" |
+#include "sandbox/win/tests/common/controller.h" |
+#include "sandbox/win/tests/integration_tests/integration_tests_common.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace { |
+ |
+//------------------------------------------------------------------------------ |
+// Internal Defines & Functions |
+//------------------------------------------------------------------------------ |
+ |
+//------------------------------------------------------------------------------ |
+// ImageLoadRemote test helper function. |
+// |
+// Trigger test child process (with or without mitigation enabled). |
+//------------------------------------------------------------------------------ |
+void TestWin10ImageLoadRemote(bool is_success_test) { |
+ // ***Insert a manual testing share UNC path here! |
+ // E.g.: \\\\hostname\\sharename\\calc.exe |
+ base::string16 unc = L"\"\\\\hostname\\sharename\\calc.exe\""; |
+ |
+ sandbox::TestRunner runner; |
+ sandbox::TargetPolicy* policy = runner.GetPolicy(); |
+ |
+ // Set a policy that would normally allow for process creation. |
+ policy->SetJobLevel(sandbox::JOB_NONE, 0); |
+ policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED); |
+ runner.SetDisableCsrss(false); |
+ |
+ if (!is_success_test) { |
+ // Enable the NoRemote mitigation. |
+ EXPECT_EQ(policy->SetDelayedProcessMitigations( |
+ sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE), |
+ sandbox::SBOX_ALL_OK); |
+ } |
+ |
+ base::string16 test = L"TestChildProcess "; |
+ test += unc.c_str(); |
+ EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED |
+ : sandbox::SBOX_TEST_FAILED), |
+ runner.RunTest(test.c_str())); |
+} |
+ |
+//------------------------------------------------------------------------------ |
+// ImageLoadLow test helper function. |
+// |
+// 1. Set up a copy of calc, using icacls to make it low integrity. |
+// 2. Trigger test child process (with or without mitigation enabled). |
+//------------------------------------------------------------------------------ |
+void TestWin10ImageLoadLowLabel(bool is_success_test) { |
+ // Setup a mandatory low executable for this test (calc.exe). |
+ // If anything fails during setup, ASSERT to end test. |
+ base::FilePath orig_path; |
+ ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &orig_path)); |
+ orig_path = orig_path.Append(L"calc.exe"); |
+ |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ base::FilePath new_path = temp_dir.GetPath(); |
+ new_path = new_path.Append(L"lowIL_calc.exe"); |
+ |
+ // Test file will be cleaned up by the ScopedTempDir. |
+ ASSERT_TRUE(base::CopyFileW(orig_path, new_path)); |
+ |
+ base::string16 cmd_line = L"icacls \""; |
+ cmd_line += new_path.value().c_str(); |
+ cmd_line += L"\" /setintegritylevel Low"; |
+ |
+ base::LaunchOptions options = base::LaunchOptionsForTest(); |
+ base::Process setup_proc = base::LaunchProcess(cmd_line.c_str(), options); |
+ ASSERT_TRUE(setup_proc.IsValid()); |
+ |
+ int exit_code = 1; |
+ if (!setup_proc.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), |
+ &exit_code)) { |
+ // Might have timed out, or might have failed. |
+ // Terminate to make sure we clean up any mess. |
+ setup_proc.Terminate(0, false); |
+ ASSERT_TRUE(false); |
+ } |
+ // Make sure icacls was successful. |
+ ASSERT_EQ(0, exit_code); |
+ |
+ sandbox::TestRunner runner; |
+ sandbox::TargetPolicy* policy = runner.GetPolicy(); |
+ |
+ // Set a policy that would normally allow for process creation. |
+ policy->SetJobLevel(sandbox::JOB_NONE, 0); |
+ policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED); |
+ runner.SetDisableCsrss(false); |
+ |
+ if (!is_success_test) { |
+ // Enable the NoLowLabel mitigation. |
+ EXPECT_EQ(policy->SetDelayedProcessMitigations( |
+ sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL), |
+ sandbox::SBOX_ALL_OK); |
+ } |
+ |
+ base::string16 test = L"TestChildProcess \""; |
+ test += new_path.value().c_str(); |
+ test += L"\" false"; |
+ |
+ EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED |
+ : sandbox::SBOX_TEST_FAILED), |
+ runner.RunTest(test.c_str())); |
+} |
+ |
+} // namespace |
+ |
+namespace sandbox { |
+ |
+//------------------------------------------------------------------------------ |
+// Exported Image Load Tests |
+//------------------------------------------------------------------------------ |
+ |
+//------------------------------------------------------------------------------ |
+// Disable image load from remote devices (MITIGATION_IMAGE_LOAD_NO_REMOTE). |
+// >= Win10_TH2 |
+//------------------------------------------------------------------------------ |
+ |
+// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE |
+// mitigation enables the setting on a process. |
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) { |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
+ return; |
+ |
+ base::string16 test_command = L"CheckPolicy "; |
+ test_command += std::to_wstring(TESTPOLICY_LOADNOREMOTE); |
+ |
+ //--------------------------------- |
+ // 1) Test setting pre-startup. |
+ //--------------------------------- |
+ TestRunner runner; |
+ sandbox::TargetPolicy* policy = runner.GetPolicy(); |
+ |
+ EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), |
+ SBOX_ALL_OK); |
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); |
+ |
+ //--------------------------------- |
+ // 2) Test setting post-startup. |
+ //--------------------------------- |
+ TestRunner runner2; |
+ sandbox::TargetPolicy* policy2 = runner2.GetPolicy(); |
+ |
+ EXPECT_EQ( |
+ policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), |
+ SBOX_ALL_OK); |
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str())); |
+} |
+ |
+// This test validates that we CAN create a new process from |
+// a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE |
+// mitigation is NOT set. |
+// |
+// MANUAL testing only. |
+TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
+ return; |
+ |
+ TestWin10ImageLoadRemote(true); |
+} |
+ |
+// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE |
+// mitigation prevents creating a new process from a remote |
+// UNC device. |
+// |
+// MANUAL testing only. |
+TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
+ return; |
+ |
+ TestWin10ImageLoadRemote(false); |
+} |
+ |
+//------------------------------------------------------------------------------ |
+// Disable image load when "mandatory low label" (integrity level). |
+// (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL) |
+// >= Win10_TH2 |
+//------------------------------------------------------------------------------ |
+ |
+// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
+// mitigation enables the setting on a process. |
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelPolicySuccess) { |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
+ return; |
+ |
+ base::string16 test_command = L"CheckPolicy "; |
+ test_command += std::to_wstring(TESTPOLICY_LOADNOLOW); |
+ |
+ //--------------------------------- |
+ // 1) Test setting pre-startup. |
+ //--------------------------------- |
+ TestRunner runner; |
+ sandbox::TargetPolicy* policy = runner.GetPolicy(); |
+ |
+ EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL), |
+ SBOX_ALL_OK); |
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); |
+ |
+ //--------------------------------- |
+ // 2) Test setting post-startup. |
+ //--------------------------------- |
+ TestRunner runner2; |
+ sandbox::TargetPolicy* policy2 = runner2.GetPolicy(); |
+ |
+ EXPECT_EQ( |
+ policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL), |
+ SBOX_ALL_OK); |
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str())); |
+} |
+ |
+// This test validates that we CAN create a new process with |
+// low mandatory label (IL), if the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
+// mitigation is NOT set. |
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelSuccess) { |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
+ return; |
+ |
+ TestWin10ImageLoadLowLabel(true); |
+} |
+ |
+// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
+// mitigation prevents creating a new process with low mandatory label (IL). |
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelFailure) { |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
+ return; |
+ |
+ TestWin10ImageLoadLowLabel(false); |
+} |
+ |
+} // namespace sandbox |