Commit 329c8277 authored by Vasilii Sukhanov's avatar Vasilii Sukhanov Committed by Commit Bot

Strengthen renderer autherization in ContentPasswordManagerDriver.

- The code is refactored. CheckChildProcessSecurityPolicy is to be used for
autofill::mojom::PasswordManagerClient too.
- PasswordForm::signon_realm is now checked together with origin.

Bug: 467150
Change-Id: I8e696c4c904c72621a3410a8ec8f4d00cb4d6236
Reviewed-on: https://chromium-review.googlesource.com/1109966
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569331}
parent b4a9e51e
...@@ -6,11 +6,19 @@ ...@@ -6,11 +6,19 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/syslog_logging.h"
#include "components/autofill/core/common/password_form.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
namespace password_manager { namespace password_manager {
namespace bad_message { namespace bad_message {
namespace {
// Called when the browser receives a bad IPC message from a renderer process on
// the UI thread. Logs the event, records a histogram metric for the |reason|,
// and terminates the process for |host|.
void ReceivedBadMessage(content::RenderProcessHost* host, void ReceivedBadMessage(content::RenderProcessHost* host,
BadMessageReason reason) { BadMessageReason reason) {
LOG(ERROR) LOG(ERROR)
...@@ -22,5 +30,53 @@ void ReceivedBadMessage(content::RenderProcessHost* host, ...@@ -22,5 +30,53 @@ void ReceivedBadMessage(content::RenderProcessHost* host,
content::RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP); content::RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP);
} }
bool CheckChildProcessSecurityPolicyForURL(content::RenderFrameHost* frame,
const GURL& url,
BadMessageReason reason) {
// Renderer-side logic should prevent any password manager usage for
// about:blank frames as well as data URLs. If that's not the case, kill the
// renderer, as it might be exploited.
if (url.SchemeIs(url::kAboutScheme) || url.SchemeIs(url::kDataScheme)) {
SYSLOG(WARNING) << "Killing renderer: illegal password access from about: "
<< "or data: URL. Reason: " << static_cast<int>(reason);
bad_message::ReceivedBadMessage(frame->GetProcess(), reason);
return false;
}
content::ChildProcessSecurityPolicy* policy =
content::ChildProcessSecurityPolicy::GetInstance();
if (!policy->CanAccessDataForOrigin(frame->GetProcess()->GetID(), url)) {
SYSLOG(WARNING) << "Killing renderer: illegal password access. Reason: "
<< static_cast<int>(reason);
bad_message::ReceivedBadMessage(frame->GetProcess(), reason);
return false;
}
return true;
}
} // namespace
bool CheckChildProcessSecurityPolicy(
content::RenderFrameHost* frame,
const autofill::PasswordForm& password_form,
BadMessageReason reason) {
return CheckChildProcessSecurityPolicyForURL(frame, password_form.origin,
reason) &&
CheckChildProcessSecurityPolicyForURL(
frame, GURL(password_form.signon_realm), reason);
}
bool CheckChildProcessSecurityPolicy(
content::RenderFrameHost* frame,
const std::vector<autofill::PasswordForm>& forms,
BadMessageReason reason) {
for (const auto& form : forms) {
if (!bad_message::CheckChildProcessSecurityPolicy(frame, form, reason))
return false;
}
return true;
}
} // namespace bad_message } // namespace bad_message
} // namespace password_manager } // namespace password_manager
...@@ -5,8 +5,14 @@ ...@@ -5,8 +5,14 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_BAD_MESSAGE_H_ #ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_BAD_MESSAGE_H_
#define COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_BAD_MESSAGE_H_ #define COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_BAD_MESSAGE_H_
#include <vector>
namespace autofill {
struct PasswordForm;
}
namespace content { namespace content {
class RenderProcessHost; class RenderFrameHost;
} }
namespace password_manager { namespace password_manager {
...@@ -38,11 +44,19 @@ enum class BadMessageReason { ...@@ -38,11 +44,19 @@ enum class BadMessageReason {
}; };
namespace bad_message { namespace bad_message {
// Called when the browser receives a bad IPC message from a renderer process on // Returns true if the renderer for |frame| is allowed to perform an operation
// the UI thread. Logs the event, records a histogram metric for the |reason|, // on |password_form|. If the origin mismatches, the process for |frame| is
// and terminates the process for |host|. // terminated and the function returns false.
void ReceivedBadMessage(content::RenderProcessHost* host, bool CheckChildProcessSecurityPolicy(
BadMessageReason reason); content::RenderFrameHost* frame,
const autofill::PasswordForm& password_form,
BadMessageReason reason);
// Same as above but checks every form in |forms|.
bool CheckChildProcessSecurityPolicy(
content::RenderFrameHost* frame,
const std::vector<autofill::PasswordForm>& forms,
BadMessageReason reason);
} // namespace bad_message } // namespace bad_message
} // namespace password_manager } // namespace password_manager
......
...@@ -72,22 +72,22 @@ class ContentPasswordManagerDriver ...@@ -72,22 +72,22 @@ class ContentPasswordManagerDriver
const autofill::PasswordFormFillData& form_data) override; const autofill::PasswordFormFillData& form_data) override;
void ClearPreviewedForm() override; void ClearPreviewedForm() override;
void ForceSavePassword() override; void ForceSavePassword() override;
void ShowManualFallbackForSaving(const autofill::PasswordForm& form) override;
void HideManualFallbackForSaving() override;
void GeneratePassword() override; void GeneratePassword() override;
PasswordGenerationManager* GetPasswordGenerationManager() override;
PasswordManager* GetPasswordManager() override;
PasswordAutofillManager* GetPasswordAutofillManager() override;
void SendLoggingAvailability() override; void SendLoggingAvailability() override;
void AllowToRunFormClassifier() override; void AllowToRunFormClassifier() override;
autofill::AutofillDriver* GetAutofillDriver() override; autofill::AutofillDriver* GetAutofillDriver() override;
bool IsMainFrame() const override; bool IsMainFrame() const override;
void MatchingBlacklistedFormFound() override; void MatchingBlacklistedFormFound() override;
PasswordGenerationManager* GetPasswordGenerationManager() override;
PasswordManager* GetPasswordManager() override;
PasswordAutofillManager* GetPasswordAutofillManager() override;
void DidNavigateFrame(content::NavigationHandle* navigation_handle); void DidNavigateFrame(content::NavigationHandle* navigation_handle);
// autofill::mojom::PasswordManagerDriver: // autofill::mojom::PasswordManagerDriver:
// Note that these messages received from a potentially compromised renderer.
// For that reason, any access to form data should be validated via
// bad_message::CheckChildProcessSecurityPolicy.
void PasswordFormsParsed( void PasswordFormsParsed(
const std::vector<autofill::PasswordForm>& forms) override; const std::vector<autofill::PasswordForm>& forms) override;
void PasswordFormsRendered( void PasswordFormsRendered(
...@@ -95,6 +95,8 @@ class ContentPasswordManagerDriver ...@@ -95,6 +95,8 @@ class ContentPasswordManagerDriver
bool did_stop_loading) override; bool did_stop_loading) override;
void PasswordFormSubmitted( void PasswordFormSubmitted(
const autofill::PasswordForm& password_form) override; const autofill::PasswordForm& password_form) override;
void ShowManualFallbackForSaving(const autofill::PasswordForm& form) override;
void HideManualFallbackForSaving() override;
void SameDocumentNavigation( void SameDocumentNavigation(
const autofill::PasswordForm& password_form) override; const autofill::PasswordForm& password_form) override;
void ShowPasswordSuggestions(int key, void ShowPasswordSuggestions(int key,
...@@ -112,13 +114,8 @@ class ContentPasswordManagerDriver ...@@ -112,13 +114,8 @@ class ContentPasswordManagerDriver
void CheckSafeBrowsingReputation(const GURL& form_action, void CheckSafeBrowsingReputation(const GURL& form_action,
const GURL& frame_url) override; const GURL& frame_url) override;
void OnPasswordFormsParsedNoRenderCheck(
const std::vector<autofill::PasswordForm>& forms);
void OnFocusedPasswordFormFound(const autofill::PasswordForm& password_form);
private: private:
bool CheckChildProcessSecurityPolicy(const GURL& url, void OnFocusedPasswordFormFound(const autofill::PasswordForm& password_form);
BadMessageReason reason);
const autofill::mojom::AutofillAgentPtr& GetAutofillAgent(); const autofill::mojom::AutofillAgentPtr& GetAutofillAgent();
......
...@@ -86,14 +86,6 @@ class PasswordManagerDriver ...@@ -86,14 +86,6 @@ class PasswordManagerDriver
// the corresponding password form, so that it can be saved. // the corresponding password form, so that it can be saved.
virtual void ForceSavePassword() {} virtual void ForceSavePassword() {}
// Tells the driver to show the manual fallback for password saving, i.e. to
// show the omnibox icon with anchored hidden save prompt.
virtual void ShowManualFallbackForSaving(const autofill::PasswordForm& form) {
}
// Tells the driver to hide the manual fallback for saving.
virtual void HideManualFallbackForSaving() {}
// Tells the driver to find the focused password field and to show generation // Tells the driver to find the focused password field and to show generation
// popup at it. // popup at it.
virtual void GeneratePassword() {} virtual void GeneratePassword() {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment