Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(822)

Side by Side Diff: chrome/browser/safe_browsing/download_protection_service.cc

Issue 1441243002: Be more lenient about inspecting/pinging on invalid downloaded .zip's (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix expected result in test Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/safe_browsing/download_protection_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/download_protection_service.h" 5 #include "chrome/browser/safe_browsing/download_protection_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 const CheckDownloadCallback& callback, 271 const CheckDownloadCallback& callback,
272 DownloadProtectionService* service, 272 DownloadProtectionService* service,
273 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, 273 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager,
274 BinaryFeatureExtractor* binary_feature_extractor) 274 BinaryFeatureExtractor* binary_feature_extractor)
275 : item_(item), 275 : item_(item),
276 url_chain_(item->GetUrlChain()), 276 url_chain_(item->GetUrlChain()),
277 referrer_url_(item->GetReferrerUrl()), 277 referrer_url_(item->GetReferrerUrl()),
278 tab_url_(item->GetTabUrl()), 278 tab_url_(item->GetTabUrl()),
279 tab_referrer_url_(item->GetTabReferrerUrl()), 279 tab_referrer_url_(item->GetTabReferrerUrl()),
280 archived_executable_(false), 280 archived_executable_(false),
281 archive_is_valid_(ArchiveValid::UNSET),
281 callback_(callback), 282 callback_(callback),
282 service_(service), 283 service_(service),
283 binary_feature_extractor_(binary_feature_extractor), 284 binary_feature_extractor_(binary_feature_extractor),
284 database_manager_(database_manager), 285 database_manager_(database_manager),
285 pingback_enabled_(service_->enabled()), 286 pingback_enabled_(service_->enabled()),
286 finished_(false), 287 finished_(false),
287 type_(ClientDownloadRequest::WIN_EXECUTABLE), 288 type_(ClientDownloadRequest::WIN_EXECUTABLE),
288 start_time_(base::TimeTicks::Now()), 289 start_time_(base::TimeTicks::Now()),
289 weakptr_factory_(this) { 290 weakptr_factory_(this) {
290 DCHECK_CURRENTLY_ON(BrowserThread::UI); 291 DCHECK_CURRENTLY_ON(BrowserThread::UI);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 479
479 private: 480 private:
480 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; 481 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
481 friend class base::DeleteHelper<CheckClientDownloadRequest>; 482 friend class base::DeleteHelper<CheckClientDownloadRequest>;
482 483
483 ~CheckClientDownloadRequest() override { 484 ~CheckClientDownloadRequest() override {
484 DCHECK_CURRENTLY_ON(BrowserThread::UI); 485 DCHECK_CURRENTLY_ON(BrowserThread::UI);
485 DCHECK(item_ == NULL); 486 DCHECK(item_ == NULL);
486 } 487 }
487 488
489 // .zip files that look invalid to Chrome can often be successfully unpacked
490 // by other archive tools, so they may be a real threat. For that reason,
491 // we send pings for them for some users.
492 bool CanReportInvalidArchives() {
493 DCHECK_CURRENTLY_ON(BrowserThread::UI);
494 const bool in_incognito = item_->GetBrowserContext()->IsOffTheRecord();
asanka 2015/11/18 21:37:55 Nit: Maybe return early if in_incognito is true.
Nathan Parker 2015/11/20 06:22:16 We're sending pings here that weren't sent before,
asanka 2015/11/20 15:55:40 It does. I was just curious.
495
496 Profile* profile = Profile::FromBrowserContext(item_->GetBrowserContext());
497 const bool is_extended_reporting =
498 profile &&
499 profile->GetPrefs()->GetBoolean(
500 prefs::kSafeBrowsingExtendedReportingEnabled);
501
502 return !in_incognito && is_extended_reporting;
503 }
504
488 void OnFileFeatureExtractionDone() { 505 void OnFileFeatureExtractionDone() {
489 // This can run in any thread, since it just posts more messages. 506 // This can run in any thread, since it just posts more messages.
490 507
491 // TODO(noelutz): DownloadInfo should also contain the IP address of 508 // TODO(noelutz): DownloadInfo should also contain the IP address of
492 // every URL in the redirect chain. We also should check whether the 509 // every URL in the redirect chain. We also should check whether the
493 // download URL is hosted on the internal network. 510 // download URL is hosted on the internal network.
494 BrowserThread::PostTask( 511 BrowserThread::PostTask(
495 BrowserThread::IO, 512 BrowserThread::IO,
496 FROM_HERE, 513 FROM_HERE,
497 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); 514 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, 574 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished,
558 weakptr_factory_.GetWeakPtr())); 575 weakptr_factory_.GetWeakPtr()));
559 analyzer_->Start(); 576 analyzer_->Start();
560 } 577 }
561 578
562 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { 579 void OnZipAnalysisFinished(const zip_analyzer::Results& results) {
563 DCHECK_CURRENTLY_ON(BrowserThread::UI); 580 DCHECK_CURRENTLY_ON(BrowserThread::UI);
564 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_); 581 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_);
565 if (!service_) 582 if (!service_)
566 return; 583 return;
567 if (results.success) { 584
568 archived_executable_ = results.has_executable; 585 // Even if !results.success, some of the zip may have been parsed.
569 archived_binary_.CopyFrom(results.archived_binary); 586 // Some unzippers will successfully unpack archives that we cannot,
570 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() 587 // so we're lenient here.
571 << ", has_executable=" << results.has_executable 588 archive_is_valid_ =
asanka 2015/11/18 21:37:55 By the way, what happens if our utility process cr
Nathan Parker 2015/11/20 06:22:16 I suspect the download would never complete, since
asanka 2015/11/20 15:55:40 I pointed out one crash bug, though I didn't look
572 << " has_archive=" << results.has_archive; 589 (results.success ? ArchiveValid::VALID : ArchiveValid::INVALID);
573 } else { 590 archived_executable_ = results.has_executable;
574 DVLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value(); 591 archived_binary_.CopyFrom(results.archived_binary);
575 } 592 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value()
593 << ", has_executable=" << results.has_executable
594 << ", has_archive=" << results.has_archive
595 << ", success=" << results.success;
596
576 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileSuccess", results.success); 597 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileSuccess", results.success);
577 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", 598 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable",
578 archived_executable_); 599 archived_executable_);
579 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", 600 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable",
580 results.has_archive && !archived_executable_); 601 results.has_archive && !archived_executable_);
581 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", 602 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime",
582 base::TimeTicks::Now() - zip_analysis_start_time_); 603 base::TimeTicks::Now() - zip_analysis_start_time_);
583 for (const auto& file_name : results.archived_archive_filenames) 604 for (const auto& file_name : results.archived_archive_filenames)
584 RecordArchivedArchiveFileExtensionType(file_name); 605 RecordArchivedArchiveFileExtensionType(file_name);
585 606
586 if (!archived_executable_ && !results.has_archive) { 607 if (!archived_executable_) {
587 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); 608 if (results.has_archive) {
588 return; 609 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE;
610 } else if (!results.success && CanReportInvalidArchives()) {
611 type_ = ClientDownloadRequest::INVALID_ZIP;
612 } else {
613 // Normal zip w/o EXEs, or invalid zip and not extended-reporting.
614 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES);
615 return;
616 }
589 } 617 }
590 618
591 if (!archived_executable_ && results.has_archive)
592 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE;
593 OnFileFeatureExtractionDone(); 619 OnFileFeatureExtractionDone();
594 } 620 }
595 621
596 #if defined(OS_MACOSX) 622 #if defined(OS_MACOSX)
597 void StartExtractDmgFeatures() { 623 void StartExtractDmgFeatures() {
598 DCHECK_CURRENTLY_ON(BrowserThread::UI); 624 DCHECK_CURRENTLY_ON(BrowserThread::UI);
599 DCHECK(item_); 625 DCHECK(item_);
600 dmg_analyzer_ = new SandboxedDMGAnalyzer( 626 dmg_analyzer_ = new SandboxedDMGAnalyzer(
601 item_->GetFullPath(), 627 item_->GetFullPath(),
602 base::Bind(&CheckClientDownloadRequest::OnDmgAnalysisFinished, 628 base::Bind(&CheckClientDownloadRequest::OnDmgAnalysisFinished,
603 weakptr_factory_.GetWeakPtr())); 629 weakptr_factory_.GetWeakPtr()));
604 dmg_analyzer_->Start(); 630 dmg_analyzer_->Start();
605 dmg_analysis_start_time_ = base::TimeTicks::Now(); 631 dmg_analysis_start_time_ = base::TimeTicks::Now();
606 } 632 }
607 633
608 void OnDmgAnalysisFinished(const zip_analyzer::Results& results) { 634 void OnDmgAnalysisFinished(const zip_analyzer::Results& results) {
609 DCHECK_CURRENTLY_ON(BrowserThread::UI); 635 DCHECK_CURRENTLY_ON(BrowserThread::UI);
610 DCHECK_EQ(ClientDownloadRequest::MAC_EXECUTABLE, type_); 636 DCHECK_EQ(ClientDownloadRequest::MAC_EXECUTABLE, type_);
611 if (!service_) 637 if (!service_)
612 return; 638 return;
613 639
614 if (results.success) { 640 // Even if !results.success, some of the DMG may have been parsed.
615 archived_executable_ = results.has_executable; 641 archive_is_valid_ =
616 archived_binary_.CopyFrom(results.archived_binary); 642 (results.success ? ArchiveValid::VALID : ArchiveValid::INVALID);
617 DVLOG(1) << "DMG analysis has finished for " 643 archived_executable_ = results.has_executable;
618 << item_->GetFullPath().value() << ", has_executable=" 644 archived_binary_.CopyFrom(results.archived_binary);
619 << results.has_executable; 645 DVLOG(1) << "DMG analysis has finished for " << item_->GetFullPath().value()
620 } else { 646 << ", has_executable=" << results.has_executable
621 DVLOG(1) << "DMG analysis failed for "<< item_->GetFullPath().value(); 647 << ", success=" << results.success;
622 }
623 648
624 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileSuccess", results.success); 649 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileSuccess", results.success);
625 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileHasExecutable", 650 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileHasExecutable",
626 archived_executable_); 651 archived_executable_);
627 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractDmgFeaturesTime", 652 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractDmgFeaturesTime",
628 base::TimeTicks::Now() - dmg_analysis_start_time_); 653 base::TimeTicks::Now() - dmg_analysis_start_time_);
629 654
630 if (!archived_executable_) { 655 if (!archived_executable_) {
631 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); 656 if (!results.success && CanReportInvalidArchives()) {
632 return; 657 type_ = ClientDownloadRequest::INVALID_MAC_ARCHIVE;
658 } else {
659 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES);
660 return;
661 }
633 } 662 }
634 663
635 OnFileFeatureExtractionDone(); 664 OnFileFeatureExtractionDone();
636 } 665 }
637 #endif // defined(OS_MACOSX) 666 #endif // defined(OS_MACOSX)
638 667
639 static void RecordCountOfSignedOrWhitelistedDownload() { 668 static void RecordCountOfSignedOrWhitelistedDownload() {
640 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); 669 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1);
641 } 670 }
642 671
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 if (tab_referrer_url_.is_valid()) { 834 if (tab_referrer_url_.is_valid()) {
806 resource->set_referrer(SanitizeUrl(tab_referrer_url_)); 835 resource->set_referrer(SanitizeUrl(tab_referrer_url_));
807 DVLOG(2) << "tab referrer " << resource->referrer(); 836 DVLOG(2) << "tab referrer " << resource->referrer();
808 } 837 }
809 } 838 }
810 839
811 request.set_user_initiated(item_->HasUserGesture()); 840 request.set_user_initiated(item_->HasUserGesture());
812 request.set_file_basename( 841 request.set_file_basename(
813 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe()); 842 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe());
814 request.set_download_type(type_); 843 request.set_download_type(type_);
844 if (archive_is_valid_ != ArchiveValid::UNSET)
845 request.set_archive_valid(archive_is_valid_ == ArchiveValid::VALID);
815 request.mutable_signature()->CopyFrom(signature_info_); 846 request.mutable_signature()->CopyFrom(signature_info_);
816 if (image_headers_) 847 if (image_headers_)
817 request.set_allocated_image_headers(image_headers_.release()); 848 request.set_allocated_image_headers(image_headers_.release());
818 if (archived_executable_) 849 if (archived_executable_)
819 request.mutable_archived_binary()->Swap(&archived_binary_); 850 request.mutable_archived_binary()->Swap(&archived_binary_);
820 if (!request.SerializeToString(&client_download_request_data_)) { 851 if (!request.SerializeToString(&client_download_request_data_)) {
821 FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO); 852 FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO);
822 return; 853 return;
823 } 854 }
824 service_->client_download_request_callbacks_.Notify(item_, &request); 855 service_->client_download_request_callbacks_.Notify(item_, &request);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 << cert->subject().GetDisplayName() 960 << cert->subject().GetDisplayName()
930 << " issuer=" << issuer->subject().GetDisplayName(); 961 << " issuer=" << issuer->subject().GetDisplayName();
931 return true; 962 return true;
932 } 963 }
933 } 964 }
934 cert = issuer; 965 cert = issuer;
935 } 966 }
936 return false; 967 return false;
937 } 968 }
938 969
970 enum class ArchiveValid { UNSET, VALID, INVALID };
971
939 // The DownloadItem we are checking. Will be NULL if the request has been 972 // The DownloadItem we are checking. Will be NULL if the request has been
940 // canceled. Must be accessed only on UI thread. 973 // canceled. Must be accessed only on UI thread.
941 content::DownloadItem* item_; 974 content::DownloadItem* item_;
942 // Copies of data from |item_| for access on other threads. 975 // Copies of data from |item_| for access on other threads.
943 std::vector<GURL> url_chain_; 976 std::vector<GURL> url_chain_;
944 GURL referrer_url_; 977 GURL referrer_url_;
945 // URL chain of redirects leading to (but not including) |tab_url|. 978 // URL chain of redirects leading to (but not including) |tab_url|.
946 std::vector<GURL> tab_redirects_; 979 std::vector<GURL> tab_redirects_;
947 // URL and referrer of the window the download was started from. 980 // URL and referrer of the window the download was started from.
948 GURL tab_url_; 981 GURL tab_url_;
949 GURL tab_referrer_url_; 982 GURL tab_referrer_url_;
950 983
951 bool archived_executable_; 984 bool archived_executable_;
985 ArchiveValid archive_is_valid_;
986
952 ClientDownloadRequest_SignatureInfo signature_info_; 987 ClientDownloadRequest_SignatureInfo signature_info_;
953 scoped_ptr<ClientDownloadRequest_ImageHeaders> image_headers_; 988 scoped_ptr<ClientDownloadRequest_ImageHeaders> image_headers_;
954 google::protobuf::RepeatedPtrField<ClientDownloadRequest_ArchivedBinary> 989 google::protobuf::RepeatedPtrField<ClientDownloadRequest_ArchivedBinary>
955 archived_binary_; 990 archived_binary_;
956 CheckDownloadCallback callback_; 991 CheckDownloadCallback callback_;
957 // Will be NULL if the request has been canceled. 992 // Will be NULL if the request has been canceled.
958 DownloadProtectionService* service_; 993 DownloadProtectionService* service_;
959 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_; 994 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
960 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 995 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
961 const bool pingback_enabled_; 996 const bool pingback_enabled_;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 GURL DownloadProtectionService::GetDownloadRequestUrl() { 1238 GURL DownloadProtectionService::GetDownloadRequestUrl() {
1204 GURL url(kDownloadRequestUrl); 1239 GURL url(kDownloadRequestUrl);
1205 std::string api_key = google_apis::GetAPIKey(); 1240 std::string api_key = google_apis::GetAPIKey();
1206 if (!api_key.empty()) 1241 if (!api_key.empty())
1207 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); 1242 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true));
1208 1243
1209 return url; 1244 return url;
1210 } 1245 }
1211 1246
1212 } // namespace safe_browsing 1247 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/safe_browsing/download_protection_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698