Commit 57fd0c0e authored by Daniel Rubery's avatar Daniel Rubery Committed by Commit Bot

Observe and report dangerous download events

For WebProtect real time reporting, we would prefer to report dangerous
downloads when the warning is seen, and when the warning is dismissed,
rather than when the file is opened from within Chrome. This CL adds
real time events for dangerous download warnings seen and bypassed, and
removes the events for dangerous downloads opened.

Bug: 1002976
Change-Id: Ic736390bf8db5fb88bc2b2b68ce824c09d159b63
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1802524
Commit-Queue: Daniel Rubery <drubery@chromium.org>
Reviewed-by: default avatarVarun Khaneja <vakh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#697411}
parent 7d47c04f
...@@ -293,6 +293,44 @@ void SafeBrowsingPrivateEventRouter::OnLargeUnscannedFileEvent( ...@@ -293,6 +293,44 @@ void SafeBrowsingPrivateEventRouter::OnLargeUnscannedFileEvent(
} }
} }
void SafeBrowsingPrivateEventRouter::OnDangerousDownloadWarning(
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& threat_type) {
if (!client_)
return;
// Create a real-time event dictionary and report it.
base::Value event(base::Value::Type::DICTIONARY);
event.SetStringKey(kKeyUrl, url.spec());
event.SetStringKey(kKeyFileName, file_name);
event.SetStringKey(kKeyDownloadDigestSha256, download_digest_sha256);
event.SetStringKey(kKeyProfileUserName, GetProfileUserName());
event.SetStringKey(kKeyThreatType, threat_type);
event.SetBoolKey(kKeyClickedThrough, false);
ReportRealtimeEvent(kKeyDangerousDownloadEvent, std::move(event));
}
void SafeBrowsingPrivateEventRouter::OnDangerousDownloadWarningBypassed(
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& threat_type) {
if (!client_)
return;
// Create a real-time event dictionary and report it.
base::Value event(base::Value::Type::DICTIONARY);
event.SetStringKey(kKeyUrl, url.spec());
event.SetStringKey(kKeyFileName, file_name);
event.SetStringKey(kKeyDownloadDigestSha256, download_digest_sha256);
event.SetStringKey(kKeyProfileUserName, GetProfileUserName());
event.SetStringKey(kKeyThreatType, threat_type);
event.SetBoolKey(kKeyClickedThrough, true);
ReportRealtimeEvent(kKeyDangerousDownloadEvent, std::move(event));
}
void SafeBrowsingPrivateEventRouter::SetCloudPolicyClientForTesting( void SafeBrowsingPrivateEventRouter::SetCloudPolicyClientForTesting(
std::unique_ptr<policy::CloudPolicyClient> client) { std::unique_ptr<policy::CloudPolicyClient> client) {
DCHECK_EQ(nullptr, client_.get()); DCHECK_EQ(nullptr, client_.get());
......
...@@ -112,6 +112,27 @@ class SafeBrowsingPrivateEventRouter : public KeyedService { ...@@ -112,6 +112,27 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
const std::string& file_name, const std::string& file_name,
const std::string& download_digest_sha256); const std::string& download_digest_sha256);
// Notifies listeners that the user saw a download warning.
// - |url| is the download URL
// - |file_name| is the path on disk
// - |download_digest_sha256| is the hex-encoded SHA256
// - |threat_type| is the danger type of the download.
void OnDangerousDownloadWarning(const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& threat_type);
// Notifies listeners that the user bypassed a download warning.
// - |url| is the download URL
// - |file_name| is the path on disk
// - |download_digest_sha256| is the hex-encoded SHA256
// - |threat_type| is the danger type of the download.
void OnDangerousDownloadWarningBypassed(
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& threat_type);
void SetCloudPolicyClientForTesting( void SetCloudPolicyClientForTesting(
std::unique_ptr<policy::CloudPolicyClient> client); std::unique_ptr<policy::CloudPolicyClient> client);
......
...@@ -159,6 +159,8 @@ jumbo_static_library("safe_browsing") { ...@@ -159,6 +159,8 @@ jumbo_static_library("safe_browsing") {
"download_protection/download_protection_service.h", "download_protection/download_protection_service.h",
"download_protection/download_protection_util.cc", "download_protection/download_protection_util.cc",
"download_protection/download_protection_util.h", "download_protection/download_protection_util.h",
"download_protection/download_reporter.cc",
"download_protection/download_reporter.h",
"download_protection/download_url_sb_client.cc", "download_protection/download_url_sb_client.cc",
"download_protection/download_url_sb_client.h", "download_protection/download_url_sb_client.h",
"download_protection/file_analyzer.cc", "download_protection/file_analyzer.cc",
......
...@@ -257,12 +257,13 @@ void CheckClientDownloadRequest::MaybeUploadBinary( ...@@ -257,12 +257,13 @@ void CheckClientDownloadRequest::MaybeUploadBinary(
if (!profile) if (!profile)
return; return;
const std::string& raw_digest_sha256 = item_->GetHash();
auto request = std::make_unique<DownloadItemRequest>( auto request = std::make_unique<DownloadItemRequest>(
item_, item_, base::BindOnce(&MaybeReportDownloadDeepScanningVerdict, profile,
base::BindOnce( item_->GetURL(),
&MaybeReportDownloadDeepScanningVerdict, profile, item_->GetURL(), item_->GetTargetFilePath().AsUTF8Unsafe(),
item_->GetTargetFilePath().AsUTF8Unsafe(), base::HexEncode(raw_digest_sha256.data(),
base::HexEncode(item_->GetHash().data(), item_->GetHash().size()))); raw_digest_sha256.size())));
if (upload_for_dlp) { if (upload_for_dlp) {
DlpDeepScanningClientRequest dlp_request; DlpDeepScanningClientRequest dlp_request;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "chrome/browser/download/download_commands.h" #include "chrome/browser/download/download_commands.h"
#include "chrome/browser/safe_browsing/download_protection/binary_upload_service.h" #include "chrome/browser/safe_browsing/download_protection/binary_upload_service.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h" #include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "chrome/browser/safe_browsing/download_protection/download_reporter.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h"
#include "chrome/browser/safe_browsing/services_delegate.h" #include "chrome/browser/safe_browsing/services_delegate.h"
#include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/browser/safe_browsing/ui_manager.h"
...@@ -305,6 +306,9 @@ class DownloadProtectionService { ...@@ -305,6 +306,9 @@ class DownloadProtectionService {
// Rate of whitelisted downloads we sample to send out download ping. // Rate of whitelisted downloads we sample to send out download ping.
double whitelist_sample_rate_; double whitelist_sample_rate_;
// DownloadReporter to send real time reports for dangerous download events.
DownloadReporter download_reporter_;
DISALLOW_COPY_AND_ASSIGN(DownloadProtectionService); DISALLOW_COPY_AND_ASSIGN(DownloadProtectionService);
}; };
} // namespace safe_browsing } // namespace safe_browsing
......
// 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 "chrome/browser/safe_browsing/download_protection/download_reporter.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/simple_download_manager_coordinator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
namespace safe_browsing {
namespace {
bool DangerTypeIsDangerous(download::DownloadDangerType danger_type) {
return (danger_type == download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
danger_type == download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
danger_type == download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
danger_type == download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
danger_type == download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
danger_type == download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED);
}
std::string DangerTypeToThreatType(download::DownloadDangerType danger_type) {
switch (danger_type) {
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
return "DANGEROUS_FILE_TYPE";
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
return "DANGEROUS_URL";
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
return "DANGEROUS";
case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
return "UNCOMMON";
case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
return "DANGEROUS_HOST";
case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
return "POTENTIALLY_UNWANTED";
default:
// Expects to only be called with the dangerous threat types listed above.
NOTREACHED() << "Unexpected danger type: " << danger_type;
return "UNKNOWN";
}
}
void ReportDangerousDownloadWarning(download::DownloadItem* download) {
content::BrowserContext* browser_context =
content::DownloadItemUtils::GetBrowserContext(download);
Profile* profile = Profile::FromBrowserContext(browser_context);
if (profile) {
std::string raw_digest_sha256 = download->GetHash();
extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
->OnDangerousDownloadWarning(
download->GetURL(), download->GetTargetFilePath().AsUTF8Unsafe(),
base::HexEncode(raw_digest_sha256.data(), raw_digest_sha256.size()),
DangerTypeToThreatType(download->GetDangerType()));
}
}
void ReportDangerousDownloadWarningBypassed(
download::DownloadItem* download,
download::DownloadDangerType original_danger_type) {
content::BrowserContext* browser_context =
content::DownloadItemUtils::GetBrowserContext(download);
Profile* profile = Profile::FromBrowserContext(browser_context);
if (profile) {
std::string raw_digest_sha256 = download->GetHash();
extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
->OnDangerousDownloadWarningBypassed(
download->GetURL(), download->GetTargetFilePath().AsUTF8Unsafe(),
base::HexEncode(raw_digest_sha256.data(), raw_digest_sha256.size()),
DangerTypeToThreatType(original_danger_type));
}
}
} // namespace
DownloadReporter::DownloadReporter() {
profiles_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
profiles_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
content::NotificationService::AllSources());
}
DownloadReporter::~DownloadReporter() {
profiles_registrar_.RemoveAll();
for (download::SimpleDownloadManagerCoordinator* coordinator :
observed_coordinators_) {
coordinator->RemoveObserver(this);
}
for (download::DownloadItem* download_item : observed_downloads_) {
download_item->RemoveObserver(this);
}
}
void DownloadReporter::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_PROFILE_CREATED: {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Profile* profile = content::Source<Profile>(source).ptr();
download::SimpleDownloadManagerCoordinator* coordinator =
SimpleDownloadManagerCoordinatorFactory::GetForKey(
profile->GetProfileKey());
coordinator->AddObserver(this);
observed_coordinators_.insert(coordinator);
break;
}
case chrome::NOTIFICATION_PROFILE_DESTROYED: {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Profile* profile = content::Source<Profile>(source).ptr();
download::SimpleDownloadManagerCoordinator* coordinator =
SimpleDownloadManagerCoordinatorFactory::GetForKey(
profile->GetProfileKey());
coordinator->RemoveObserver(this);
observed_coordinators_.erase(coordinator);
break;
}
default:
NOTREACHED();
}
}
void DownloadReporter::OnDownloadCreated(download::DownloadItem* download) {
danger_types_[download] = download->GetDangerType();
download->AddObserver(this);
observed_downloads_.insert(download);
}
void DownloadReporter::OnDownloadDestroyed(download::DownloadItem* download) {
download->RemoveObserver(this);
danger_types_.erase(download);
observed_downloads_.erase(download);
}
void DownloadReporter::OnDownloadUpdated(download::DownloadItem* download) {
// If the update isn't a change in danger type, we can ignore it.
if (danger_types_[download] == download->GetDangerType())
return;
download::DownloadDangerType old_danger_type = danger_types_[download];
download::DownloadDangerType current_danger_type = download->GetDangerType();
if (!DangerTypeIsDangerous(old_danger_type) &&
DangerTypeIsDangerous(current_danger_type)) {
ReportDangerousDownloadWarning(download);
}
if (DangerTypeIsDangerous(old_danger_type) &&
current_danger_type == download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED) {
ReportDangerousDownloadWarningBypassed(download, old_danger_type);
}
danger_types_[download] = current_danger_type;
}
} // namespace safe_browsing
// 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 CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_REPORTER_H_
#define CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_REPORTER_H_
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/simple_download_manager_coordinator.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
namespace safe_browsing {
// This class is responsible for observing download events and reporting them as
// appropriate.
class DownloadReporter
: public download::DownloadItem::Observer,
public download::SimpleDownloadManagerCoordinator::Observer,
public content::NotificationObserver {
public:
DownloadReporter();
~DownloadReporter() override;
// NotificationObserver implementation:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// SimpleDownloadManagerCoordinator::Observer implementation:
void OnDownloadCreated(download::DownloadItem* download) override;
// DownloadItem::Observer implementation:
void OnDownloadDestroyed(download::DownloadItem* download) override;
void OnDownloadUpdated(download::DownloadItem* download) override;
private:
content::NotificationRegistrar profiles_registrar_;
base::flat_map<download::DownloadItem*, download::DownloadDangerType>
danger_types_;
std::set<download::SimpleDownloadManagerCoordinator*> observed_coordinators_;
std::set<download::DownloadItem*> observed_downloads_;
};
} // namespace safe_browsing
#endif // CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_REPORTER_H_
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