Skip to content

Commit

Permalink
Check subresource filter through the new GMSCore Safe Browsing API
Browse files Browse the repository at this point in the history
The SUBRESOURCE_FILTER threat type is replaced with
ABUSIVE_EXPERIENCE_VIOLATION and BETTER_ADS_VIOLATION in
http://cl/585940542. Update SafeBrowsingJavaThreatType to reflect
this change. Note that the old
SafeBrowsingJavaThreatType::SUBRESOURCE_FILTER was never sent to or
from the new API.

Also start to consume the threat attribute from the API to set the
subresource_filter_match field in ThreatMetadata. This is required
to support subresource filter checks through the new API.

Add a feature flag SafeBrowsingNewGmsApiForSubresourceFilterCheck to
control this feature. The flag is disabled by default.

Bug: 1496508
Change-Id: I08fbcf31d3bbc8abc912553884319854969a4122
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5079692
Reviewed-by: thefrog <[email protected]>
Commit-Queue: Xinghui Lu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1235217}
  • Loading branch information
Xinghui Lu authored and Chromium LUCI CQ committed Dec 8, 2023
1 parent b8ed5b5 commit e2b6d0b
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ SafeBrowsingJavaValidationResult GetJavaValidationResult(
case SafeBrowsingJavaThreatType::SOCIAL_ENGINEERING:
case SafeBrowsingJavaThreatType::UNWANTED_SOFTWARE:
case SafeBrowsingJavaThreatType::POTENTIALLY_HARMFUL_APPLICATION:
case SafeBrowsingJavaThreatType::SUBRESOURCE_FILTER:
case SafeBrowsingJavaThreatType::BILLING:
case SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION:
case SafeBrowsingJavaThreatType::BETTER_ADS_VIOLATION:
is_threat_type_recognized = true;
break;
}
Expand Down Expand Up @@ -325,10 +326,11 @@ SBThreatType SafeBrowsingJavaToSBThreatType(
return SB_THREAT_TYPE_URL_UNWANTED;
case SafeBrowsingJavaThreatType::POTENTIALLY_HARMFUL_APPLICATION:
return SB_THREAT_TYPE_URL_MALWARE;
case SafeBrowsingJavaThreatType::SUBRESOURCE_FILTER:
return SB_THREAT_TYPE_SUBRESOURCE_FILTER;
case SafeBrowsingJavaThreatType::BILLING:
return SB_THREAT_TYPE_BILLING;
case SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION:
case SafeBrowsingJavaThreatType::BETTER_ADS_VIOLATION:
return SB_THREAT_TYPE_SUBRESOURCE_FILTER;
}
}

Expand All @@ -343,8 +345,6 @@ SafeBrowsingJavaThreatType SBThreatTypeToSafeBrowsingApiJavaThreatType(
return SafeBrowsingJavaThreatType::UNWANTED_SOFTWARE;
case SB_THREAT_TYPE_URL_MALWARE:
return SafeBrowsingJavaThreatType::POTENTIALLY_HARMFUL_APPLICATION;
case SB_THREAT_TYPE_SUBRESOURCE_FILTER:
return SafeBrowsingJavaThreatType::SUBRESOURCE_FILTER;
case SB_THREAT_TYPE_BILLING:
return SafeBrowsingJavaThreatType::BILLING;
default:
Expand All @@ -359,13 +359,24 @@ ScopedJavaLocalRef<jintArray> SBThreatTypeSetToSafeBrowsingJavaArray(
JNIEnv* env,
const SBThreatTypeSet& threat_types) {
DCHECK_LT(0u, threat_types.size());
int int_threat_types[threat_types.size()];
size_t threat_type_size =
base::Contains(threat_types, SB_THREAT_TYPE_SUBRESOURCE_FILTER)
? threat_types.size() + 1
: threat_types.size();
int int_threat_types[threat_type_size];
int* itr = &int_threat_types[0];
for (auto threat_type : threat_types) {
*itr++ = static_cast<int>(
SBThreatTypeToSafeBrowsingApiJavaThreatType(threat_type));
if (threat_type == SB_THREAT_TYPE_SUBRESOURCE_FILTER) {
*itr++ = static_cast<int>(
SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION);
*itr++ =
static_cast<int>(SafeBrowsingJavaThreatType::BETTER_ADS_VIOLATION);
} else {
*itr++ = static_cast<int>(
SBThreatTypeToSafeBrowsingApiJavaThreatType(threat_type));
}
}
return ToJavaIntArray(env, int_threat_types, threat_types.size());
return ToJavaIntArray(env, int_threat_types, threat_type_size);
}

// The map that holds the callback_id used to reference each pending SafetyNet
Expand Down Expand Up @@ -575,15 +586,10 @@ void OnUrlCheckDoneOnSBThreadBySafeBrowsingApi(
return;
}

// The API currently doesn't have required threat types
// (ABUSIVE_EXPERIENCE_VIOLATION, BETTER_ADS_VIOLATION) to work with threat
// attributes, so threat attributes are currently disabled. It should not
// affect browse URL checks (mainframe and subresource URLs). However, this
// must be changed before it is used for subresource filter checks.
// Similarly, threat attributes must be consumed if we decide to use malware
// landing info on Android.
std::move(*(callback->response_callback))
.Run(SafeBrowsingJavaToSBThreatType(threat_type), ThreatMetadata());
.Run(
SafeBrowsingJavaToSBThreatType(threat_type),
GetThreatMetadataFromSafeBrowsingApi(threat_type, threat_attributes));
}

// Java->Native call, invoked when a SafeBrowsing check is done. |env| is the
Expand Down Expand Up @@ -635,17 +641,21 @@ void SafeBrowsingApiHandlerBridge::StartHashDatabaseUrlCheck(
std::unique_ptr<ResponseCallback> callback,
const GURL& url,
const SBThreatTypeSet& threat_types) {
// The SafeBrowsing API currently doesn't have required threat types
// (ABUSIVE_EXPERIENCE_VIOLATION, BETTER_ADS_VIOLATION) to perform subresource
// filter checks, so only checking the browse URLs.
if (SBThreatTypeSetIsValidForCheckBrowseUrl(threat_types) &&
base::FeatureList::IsEnabled(
kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck)) {
bool for_browse_url = SBThreatTypeSetIsValidForCheckBrowseUrl(threat_types);
if (for_browse_url && base::FeatureList::IsEnabled(
kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck)) {
StartUrlCheckBySafeBrowsing(std::move(callback), url, threat_types,
SafeBrowsingJavaProtocol::LOCAL_BLOCK_LIST);
} else {
StartUrlCheckBySafetyNet(std::move(callback), url, threat_types);
return;
}
if (!for_browse_url && base::FeatureList::IsEnabled(
kSafeBrowsingNewGmsApiForSubresourceFilterCheck)) {
StartUrlCheckBySafeBrowsing(std::move(callback), url, threat_types,
SafeBrowsingJavaProtocol::LOCAL_BLOCK_LIST);
return;
}

StartUrlCheckBySafetyNet(std::move(callback), url, threat_types);
}

void SafeBrowsingApiHandlerBridge::StartHashRealTimeUrlCheck(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ SBThreatTypeSet GetAllThreatTypes() {
class SafeBrowsingApiHandlerBridgeTest : public testing::Test {
public:
SafeBrowsingApiHandlerBridgeTest() {
feature_list_.InitAndEnableFeature(
safe_browsing::kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck);
feature_list_.InitWithFeatures(
{safe_browsing::kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck,
safe_browsing::kSafeBrowsingNewGmsApiForSubresourceFilterCheck},
{});
}

void SetUp() override {
Expand Down Expand Up @@ -369,21 +371,40 @@ TEST_F(SafeBrowsingApiHandlerBridgeTest,

TEST_F(SafeBrowsingApiHandlerBridgeTest,
HashDatabaseUrlCheck_ThreatMatchWithSubresourceFilter) {
base::HistogramTester histogram_tester;
GURL url("https://example.com");
std::string metadata =
"{\"matches\":[{\"threat_type\":\"13\", "
"\"sf_absv\":\"enforce\"}]}";
AddSafetyNetBlocklistResponse(url, metadata,
{SafetyNetJavaThreatType::SUBRESOURCE_FILTER});
AddSafeBrowsingResponse(
url, SafeBrowsingApiLookupResult::SUCCESS,
SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION,
{SafeBrowsingJavaThreatAttribute::CANARY},
SafeBrowsingJavaResponseStatus::SUCCESS_WITH_LOCAL_BLOCKLIST,
{SafeBrowsingJavaThreatType::SOCIAL_ENGINEERING,
SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION,
SafeBrowsingJavaThreatType::BETTER_ADS_VIOLATION},
SafeBrowsingJavaProtocol::LOCAL_BLOCK_LIST);

RunHashDatabaseUrlCheck(
url, /*threat_types=*/{SB_THREAT_TYPE_SUBRESOURCE_FILTER},
url, /*threat_types=*/
{SB_THREAT_TYPE_URL_PHISHING, SB_THREAT_TYPE_SUBRESOURCE_FILTER},
/*expected_threat_type=*/SB_THREAT_TYPE_SUBRESOURCE_FILTER,
/*expected_subresource_filter_match=*/
{{SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::ENFORCE}});
{{SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::WARN}});

CheckSafetyNetApiHistogramValues(
/*expected_result=*/UmaRemoteCallResult::MATCH);
CheckSafeBrowsingApiHistogramValues(
".LocalBlocklist",
/*expected_is_available=*/true,
/*expected_validation_result=*/SafeBrowsingJavaValidationResult::VALID,
/*expected_lookup_result=*/
static_cast<int>(SafeBrowsingApiLookupResult::SUCCESS),
/*expected_threat_type=*/
static_cast<int>(
SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION),
/*expected_threat_attribute=*/1,
/*expected_threat_attribute_count=*/
static_cast<int>(SafeBrowsingJavaThreatAttribute::CANARY),
/*expected_response_status=*/
static_cast<int>(
SafeBrowsingJavaResponseStatus::SUCCESS_WITH_LOCAL_BLOCKLIST));
}

TEST_F(SafeBrowsingApiHandlerBridgeTest,
Expand Down Expand Up @@ -785,8 +806,9 @@ class SafeBrowsingApiHandlerBridgeNewGmsApiDisabledTest
: public SafeBrowsingApiHandlerBridgeTest {
public:
SafeBrowsingApiHandlerBridgeNewGmsApiDisabledTest() {
feature_list_.InitAndDisableFeature(
safe_browsing::kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck);
feature_list_.InitWithFeatures(
{}, {safe_browsing::kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck,
safe_browsing::kSafeBrowsingNewGmsApiForSubresourceFilterCheck});
}

protected:
Expand Down Expand Up @@ -844,6 +866,25 @@ TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiDisabledTest,
/*expected_result=*/UmaRemoteCallResult::MATCH);
}

TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiDisabledTest,
HashDatabaseUrlCheck_ThreatMatchWithSubresourceFilter) {
GURL url("https://example.com");
std::string metadata =
"{\"matches\":[{\"threat_type\":\"13\", "
"\"sf_absv\":\"enforce\"}]}";
AddSafetyNetBlocklistResponse(url, metadata,
{SafetyNetJavaThreatType::SUBRESOURCE_FILTER});

RunHashDatabaseUrlCheck(
url, /*threat_types=*/{SB_THREAT_TYPE_SUBRESOURCE_FILTER},
/*expected_threat_type=*/SB_THREAT_TYPE_SUBRESOURCE_FILTER,
/*expected_subresource_filter_match=*/
{{SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::ENFORCE}});

CheckSafetyNetApiHistogramValues(
/*expected_result=*/UmaRemoteCallResult::MATCH);
}

TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiDisabledTest,
HashDatabaseUrlCheck_MultipleRequests) {
GURL unsafe_url("https://unsafe.com");
Expand Down Expand Up @@ -933,4 +974,97 @@ TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiDisabledTest,
/*expected_threat_type=*/SB_THREAT_TYPE_SAFE);
}

class SafeBrowsingApiHandlerBridgeNewGmsApiForBrowseUrlDisabledTest
: public SafeBrowsingApiHandlerBridgeTest {
public:
SafeBrowsingApiHandlerBridgeNewGmsApiForBrowseUrlDisabledTest() {
feature_list_.InitWithFeatures(
{safe_browsing::kSafeBrowsingNewGmsApiForSubresourceFilterCheck},
{safe_browsing::kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck});
}

protected:
base::test::ScopedFeatureList feature_list_;
};

TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiForBrowseUrlDisabledTest,
HashDatabaseUrlCheck_SingleThreatMatch) {
GURL url("https://example.com");
// threat_type: 3 is unwanted.
std::string metadata = "{\"matches\":[{\"threat_type\":\"3\"}]}";
AddSafetyNetBlocklistResponse(url, metadata,
GetAllSafetyNetThreatsOfInterest());

RunHashDatabaseUrlCheck(url, /*threat_types=*/GetAllThreatTypes(),
/*expected_threat_type=*/SB_THREAT_TYPE_URL_UNWANTED,
/*expected_subresource_filter_match=*/{});
}

TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiForBrowseUrlDisabledTest,
HashDatabaseUrlCheck_ThreatMatchWithSubresourceFilter) {
GURL url("https://example.com");
// Subresource filter is still checked through the new API.
AddSafeBrowsingResponse(
url, SafeBrowsingApiLookupResult::SUCCESS,
SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION,
{SafeBrowsingJavaThreatAttribute::CANARY},
SafeBrowsingJavaResponseStatus::SUCCESS_WITH_LOCAL_BLOCKLIST,
{SafeBrowsingJavaThreatType::SOCIAL_ENGINEERING,
SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION,
SafeBrowsingJavaThreatType::BETTER_ADS_VIOLATION},
SafeBrowsingJavaProtocol::LOCAL_BLOCK_LIST);

RunHashDatabaseUrlCheck(
url, /*threat_types=*/
{SB_THREAT_TYPE_URL_PHISHING, SB_THREAT_TYPE_SUBRESOURCE_FILTER},
/*expected_threat_type=*/SB_THREAT_TYPE_SUBRESOURCE_FILTER,
/*expected_subresource_filter_match=*/
{{SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::WARN}});
}

class SafeBrowsingApiHandlerBridgeNewGmsApiForSubresourceFilterDisabledTest
: public SafeBrowsingApiHandlerBridgeTest {
public:
SafeBrowsingApiHandlerBridgeNewGmsApiForSubresourceFilterDisabledTest() {
feature_list_.InitWithFeatures(
{safe_browsing::kSafeBrowsingNewGmsApiForBrowseUrlDatabaseCheck},
{safe_browsing::kSafeBrowsingNewGmsApiForSubresourceFilterCheck});
}

protected:
base::test::ScopedFeatureList feature_list_;
};

TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiForSubresourceFilterDisabledTest,
HashDatabaseUrlCheck_SingleThreatMatch) {
GURL url("https://example.com");
// Browse URL is still checked through the new API.
AddSafeBrowsingResponse(
url, SafeBrowsingApiLookupResult::SUCCESS,
SafeBrowsingJavaThreatType::UNWANTED_SOFTWARE, {},
SafeBrowsingJavaResponseStatus::SUCCESS_WITH_LOCAL_BLOCKLIST,
GetAllSafeBrowsingThreatTypes(),
SafeBrowsingJavaProtocol::LOCAL_BLOCK_LIST);

RunHashDatabaseUrlCheck(url, /*threat_types=*/GetAllThreatTypes(),
/*expected_threat_type=*/SB_THREAT_TYPE_URL_UNWANTED,
/*expected_subresource_filter_match=*/{});
}

TEST_F(SafeBrowsingApiHandlerBridgeNewGmsApiForSubresourceFilterDisabledTest,
HashDatabaseUrlCheck_ThreatMatchWithSubresourceFilter) {
GURL url("https://example.com");
std::string metadata =
"{\"matches\":[{\"threat_type\":\"13\", "
"\"sf_absv\":\"enforce\"}]}";
AddSafetyNetBlocklistResponse(url, metadata,
{SafetyNetJavaThreatType::SUBRESOURCE_FILTER});

RunHashDatabaseUrlCheck(
url, /*threat_types=*/{SB_THREAT_TYPE_SUBRESOURCE_FILTER},
/*expected_threat_type=*/SB_THREAT_TYPE_SUBRESOURCE_FILTER,
/*expected_subresource_filter_match=*/
{{SubresourceFilterType::ABUSIVE, SubresourceFilterLevel::ENFORCE}});
}

} // namespace safe_browsing
41 changes: 41 additions & 0 deletions components/safe_browsing/android/safe_browsing_api_handler_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,45 @@ UmaRemoteCallResult ParseJsonFromGMSCore(const std::string& metadata_str,
return UmaRemoteCallResult::MATCH; // success
}

ThreatMetadata GetThreatMetadataFromSafeBrowsingApi(
SafeBrowsingJavaThreatType threat_type,
const std::vector<int>& threat_attributes) {
bool is_relevant_threat_type = false;
SubresourceFilterType type;
switch (threat_type) {
case SafeBrowsingJavaThreatType::ABUSIVE_EXPERIENCE_VIOLATION:
is_relevant_threat_type = true;
type = SubresourceFilterType::ABUSIVE;
break;
case SafeBrowsingJavaThreatType::BETTER_ADS_VIOLATION:
is_relevant_threat_type = true;
type = SubresourceFilterType::BETTER_ADS;
break;
case SafeBrowsingJavaThreatType::NO_THREAT:
case SafeBrowsingJavaThreatType::SOCIAL_ENGINEERING:
case SafeBrowsingJavaThreatType::UNWANTED_SOFTWARE:
case SafeBrowsingJavaThreatType::POTENTIALLY_HARMFUL_APPLICATION:
case SafeBrowsingJavaThreatType::BILLING:
break;
}
if (!is_relevant_threat_type) {
return ThreatMetadata();
}
// Filter level is default to ENFORCE.
SubresourceFilterLevel level = SubresourceFilterLevel::ENFORCE;
for (int threat_attribute : threat_attributes) {
if (threat_attribute ==
static_cast<int>(SafeBrowsingJavaThreatAttribute::CANARY)) {
level = SubresourceFilterLevel::WARN;
break;
}
}

SubresourceFilterMatch subresource_filter_match;
subresource_filter_match[type] = level;
ThreatMetadata threat_metadata;
threat_metadata.subresource_filter_match = subresource_filter_match;
return threat_metadata;
}

} // namespace safe_browsing
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ enum class SafeBrowsingJavaThreatType {
SOCIAL_ENGINEERING = 2,
UNWANTED_SOFTWARE = 3,
POTENTIALLY_HARMFUL_APPLICATION = 4,
SUBRESOURCE_FILTER = 13,
BILLING = 15
BILLING = 15,
ABUSIVE_EXPERIENCE_VIOLATION = 20,
BETTER_ADS_VIOLATION = 21
};

// Must match the definition in SafeBrowsing::ThreatAttribute in SafeBrowsing
Expand Down Expand Up @@ -134,6 +135,12 @@ UmaRemoteCallResult ParseJsonFromGMSCore(const std::string& metadata_str,
SBThreatType* worst_threat,
ThreatMetadata* metadata);

// Translates |threat_type| and |threat_attributes| from the Safe Browsing API
// into ThreatMetadata.
ThreatMetadata GetThreatMetadataFromSafeBrowsingApi(
SafeBrowsingJavaThreatType threat_type,
const std::vector<int>& threat_attributes);

} // namespace safe_browsing

#endif // COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_UTIL_H_
Loading

0 comments on commit e2b6d0b

Please sign in to comment.