summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIstiaque Ahmed <lazyboy@chromium.org>2020-01-14 18:26:09 +0100
committerMichael BrĂ¼ning <michael.bruning@qt.io>2020-01-16 13:13:45 +0000
commit9f87a1ede7cd8824425c182c2ac77eebf4f7d14d (patch)
tree7afeca77a32cf9fd91061eca64c3f25160e9c527
parent5fc987f210cb555c53e4d1696fb2205d6d70f3e9 (diff)
downloadqtwebengine-chromium-9f87a1ede7cd8824425c182c2ac77eebf4f7d14d.tar.gz
[Backport] CVE-2019-13755: Insufficient policy enforcement in extensions.
Manual backport of patch: Content Verification: Make computed hashes aware of dot/space suffix treatment. On windows, filename with (.| )+ suffix is ignored, i.e. "foo.html." and "foo.html" are treated the same. VerifiedContents is already aware of this and it stores a canonicalized version of filename for filenames containing (.| )+ suffix. This CL makes ComputedHashes aware of the change too, so that searching for hashes will consider canonicalized version of the filename as candidate. This makes ComputedHashes::Reader and VerifiedContents treat this suffix behavior consistently. This CL also adds unittest and browsertest for the fix. Bug: 696208 Test: See bug for test repro. Change-Id: I98e3f851b2f4cf3cb9cdb4a49f5414c476e2d5bd Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--chromium/extensions/browser/BUILD.gn2
-rw-r--r--chromium/extensions/browser/computed_hashes.cc51
-rw-r--r--chromium/extensions/browser/content_verifier/content_verifier_utils.cc24
-rw-r--r--chromium/extensions/browser/content_verifier/content_verifier_utils.h23
-rw-r--r--chromium/extensions/browser/verified_contents.cc26
5 files changed, 93 insertions, 33 deletions
diff --git a/chromium/extensions/browser/BUILD.gn b/chromium/extensions/browser/BUILD.gn
index 6ec2a9925e0..a440fa6c741 100644
--- a/chromium/extensions/browser/BUILD.gn
+++ b/chromium/extensions/browser/BUILD.gn
@@ -86,6 +86,8 @@ jumbo_source_set("browser_sources") {
"content_verifier/content_hash.cc",
"content_verifier/content_hash.h",
"content_verifier/content_verifier_key.h",
+ "content_verifier/content_verifier_utils.cc",
+ "content_verifier/content_verifier_utils.h",
"content_verifier_delegate.h",
"content_verifier_io_data.cc",
"content_verifier_io_data.h",
diff --git a/chromium/extensions/browser/computed_hashes.cc b/chromium/extensions/browser/computed_hashes.cc
index c99e990f179..b159e1df796 100644
--- a/chromium/extensions/browser/computed_hashes.cc
+++ b/chromium/extensions/browser/computed_hashes.cc
@@ -16,8 +16,10 @@
#include "base/stl_util.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
+#include "build/build_config.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
+#include "extensions/browser/content_verifier/content_verifier_utils.h"
namespace extensions {
@@ -148,24 +150,43 @@ bool ComputedHashes::Reader::GetHashes(const base::FilePath& relative_path,
int* block_size,
std::vector<std::string>* hashes) const {
base::FilePath path = relative_path.NormalizePathSeparatorsTo('/');
- auto i = data_.find(path);
+ auto find_data = [&](const base::FilePath& normalized_path) {
+ auto i = data_.find(normalized_path);
+ if (i == data_.end()) {
+ // If we didn't find the entry using exact match, it's possible the
+ // developer is using a path with some letters in the incorrect case,
+ // which happens to work on windows/osx. So try doing a linear scan to
+ // look for a case-insensitive match. In practice most extensions don't
+ // have that big a list of files so the performance penalty is probably
+ // not too big here. Also for crbug.com/29941 we plan to start warning
+ // developers when they are making this mistake, since their extension
+ // will be broken on linux/chromeos.
+ for (i = data_.begin(); i != data_.end(); ++i) {
+ const base::FilePath& entry = i->first;
+ if (base::FilePath::CompareEqualIgnoreCase(entry.value(),
+ normalized_path.value())) {
+ break;
+ }
+ }
+ }
+ return i;
+ };
+ auto i = find_data(path);
+#if defined(OS_WIN)
if (i == data_.end()) {
- // If we didn't find the entry using exact match, it's possible the
- // developer is using a path with some letters in the incorrect case, which
- // happens to work on windows/osx. So try doing a linear scan to look for a
- // case-insensitive match. In practice most extensions don't have that big
- // a list of files so the performance penalty is probably not too big
- // here. Also for crbug.com/29941 we plan to start warning developers when
- // they are making this mistake, since their extension will be broken on
- // linux/chromeos.
- for (i = data_.begin(); i != data_.end(); ++i) {
- const base::FilePath& entry = i->first;
- if (base::FilePath::CompareEqualIgnoreCase(entry.value(), path.value()))
- break;
+ base::FilePath::StringType trimmed_path_value;
+ // Also search for path with (.| )+ suffix trimmed as they are ignored in
+ // windows. This matches the canonicalization behavior of
+ // VerifiedContents::Create.
+ if (content_verifier_utils::TrimDotSpaceSuffix(path.value(),
+ &trimmed_path_value)) {
+ i = find_data(base::FilePath(trimmed_path_value));
}
- if (i == data_.end())
- return false;
}
+#endif // defined(OS_WIN)
+ if (i == data_.end())
+ return false;
+
const HashInfo& info = i->second;
*block_size = info.first;
*hashes = info.second;
diff --git a/chromium/extensions/browser/content_verifier/content_verifier_utils.cc b/chromium/extensions/browser/content_verifier/content_verifier_utils.cc
new file mode 100644
index 00000000000..a9c3797aa28
--- /dev/null
+++ b/chromium/extensions/browser/content_verifier/content_verifier_utils.cc
@@ -0,0 +1,24 @@
+// Copyright 2019 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 "extensions/browser/content_verifier/content_verifier_utils.h"
+
+namespace extensions {
+namespace content_verifier_utils {
+
+#if defined(OS_WIN)
+bool TrimDotSpaceSuffix(const base::FilePath::StringType& path,
+ base::FilePath::StringType* out_path) {
+ base::FilePath::StringType::size_type trim_pos =
+ path.find_last_not_of(FILE_PATH_LITERAL(". "));
+ if (trim_pos == base::FilePath::StringType::npos)
+ return false;
+
+ *out_path = path.substr(0, trim_pos + 1);
+ return true;
+}
+#endif // defined(OS_WIN)
+
+} // namespace content_verifier_utils
+} // namespace extensions
diff --git a/chromium/extensions/browser/content_verifier/content_verifier_utils.h b/chromium/extensions/browser/content_verifier/content_verifier_utils.h
new file mode 100644
index 00000000000..bcfaebf8e29
--- /dev/null
+++ b/chromium/extensions/browser/content_verifier/content_verifier_utils.h
@@ -0,0 +1,23 @@
+// Copyright 2019 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.
+#ifndef EXTENSIONS_BROWSER_CONTENT_VERIFIER_CONTENT_VERIFIER_UTILS_H_
+#define EXTENSIONS_BROWSER_CONTENT_VERIFIER_CONTENT_VERIFIER_UTILS_H_
+
+#include "base/files/file_path.h"
+#include "build/build_config.h"
+
+namespace extensions {
+namespace content_verifier_utils {
+
+#if defined(OS_WIN)
+// Returns true if |path| ends with (.| )+.
+// |out_path| will contain "." and/or " " suffix removed from |path|.
+bool TrimDotSpaceSuffix(const base::FilePath::StringType& path,
+ base::FilePath::StringType* out_path);
+#endif // defined(OS_WIN)
+
+} // namespace content_verifier_utils
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_CONTENT_VERIFIER_CONTENT_VERIFIER_UTILS_H_
diff --git a/chromium/extensions/browser/verified_contents.cc b/chromium/extensions/browser/verified_contents.cc
index 8beeb151be5..cef5277bb25 100644
--- a/chromium/extensions/browser/verified_contents.cc
+++ b/chromium/extensions/browser/verified_contents.cc
@@ -18,6 +18,7 @@
#include "build/build_config.h"
#include "components/crx_file/id_util.h"
#include "crypto/signature_verifier.h"
+#include "extensions/browser/content_verifier/content_verifier_utils.h"
#include "extensions/common/extension.h"
namespace {
@@ -94,21 +95,6 @@ class ScopedUMARecorder {
DISALLOW_COPY_AND_ASSIGN(ScopedUMARecorder);
};
-#if defined(OS_WIN)
-// Returns true if |path| ends with (.| )+.
-// |out_path| will contain "." and/or " " suffix removed from |path|.
-bool TrimDotSpaceSuffix(const base::FilePath::StringType& path,
- base::FilePath::StringType* out_path) {
- base::FilePath::StringType::size_type trim_pos =
- path.find_last_not_of(FILE_PATH_LITERAL(". "));
- if (trim_pos == base::FilePath::StringType::npos)
- return false;
-
- *out_path = path.substr(0, trim_pos + 1);
- return true;
-}
-#endif // defined(OS_WIN)
-
} // namespace
namespace extensions {
@@ -225,9 +211,11 @@ std::unique_ptr<VerifiedContents> VerifiedContents::Create(
// that any filename with (.| )+ suffix can be matched later, see
// HasTreeHashRoot() and TreeHashRootEquals().
base::FilePath::StringType trimmed_path;
- if (TrimDotSpaceSuffix(lowercase_file_path, &trimmed_path))
+ if (content_verifier_utils::TrimDotSpaceSuffix(lowercase_file_path,
+ &trimmed_path)) {
verified_contents->root_hashes_.insert(
std::make_pair(trimmed_path, i->second));
+ }
#endif // defined(OS_WIN)
}
@@ -246,7 +234,7 @@ bool VerifiedContents::HasTreeHashRoot(
#if defined(OS_WIN)
base::FilePath::StringType trimmed_path;
- if (TrimDotSpaceSuffix(path, &trimmed_path))
+ if (content_verifier_utils::TrimDotSpaceSuffix(path, &trimmed_path))
return base::Contains(root_hashes_, trimmed_path);
#endif // defined(OS_WIN)
return false;
@@ -261,8 +249,10 @@ bool VerifiedContents::TreeHashRootEquals(const base::FilePath& relative_path,
#if defined(OS_WIN)
base::FilePath::StringType trimmed_relative_path;
- if (TrimDotSpaceSuffix(normalized_relative_path, &trimmed_relative_path))
+ if (content_verifier_utils::TrimDotSpaceSuffix(normalized_relative_path,
+ &trimmed_relative_path)) {
return TreeHashRootEqualsImpl(trimmed_relative_path, expected);
+ }
#endif // defined(OS_WIN)
return false;
}