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

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: Adjust proto tag number to match server side. Created 5 years 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 if !in_incognito && is_extended_reporting.
492 bool CanReportInvalidArchives() {
493 DCHECK_CURRENTLY_ON(BrowserThread::UI);
494 Profile* profile = Profile::FromBrowserContext(item_->GetBrowserContext());
495 if (!profile ||
496 !profile->GetPrefs()->GetBoolean(
497 prefs::kSafeBrowsingExtendedReportingEnabled))
498 return false;
499
500 return !item_->GetBrowserContext()->IsOffTheRecord();
501 }
502
488 void OnFileFeatureExtractionDone() { 503 void OnFileFeatureExtractionDone() {
489 // This can run in any thread, since it just posts more messages. 504 // This can run in any thread, since it just posts more messages.
490 505
491 // TODO(noelutz): DownloadInfo should also contain the IP address of 506 // TODO(noelutz): DownloadInfo should also contain the IP address of
492 // every URL in the redirect chain. We also should check whether the 507 // every URL in the redirect chain. We also should check whether the
493 // download URL is hosted on the internal network. 508 // download URL is hosted on the internal network.
494 BrowserThread::PostTask( 509 BrowserThread::PostTask(
495 BrowserThread::IO, 510 BrowserThread::IO,
496 FROM_HERE, 511 FROM_HERE,
497 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); 512 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, 572 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished,
558 weakptr_factory_.GetWeakPtr())); 573 weakptr_factory_.GetWeakPtr()));
559 analyzer_->Start(); 574 analyzer_->Start();
560 } 575 }
561 576
562 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { 577 void OnZipAnalysisFinished(const zip_analyzer::Results& results) {
563 DCHECK_CURRENTLY_ON(BrowserThread::UI); 578 DCHECK_CURRENTLY_ON(BrowserThread::UI);
564 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_); 579 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_);
565 if (!service_) 580 if (!service_)
566 return; 581 return;
567 if (results.success) { 582
568 archived_executable_ = results.has_executable; 583 // Even if !results.success, some of the zip may have been parsed.
569 archived_binary_.CopyFrom(results.archived_binary); 584 // Some unzippers will successfully unpack archives that we cannot,
570 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() 585 // so we're lenient here.
571 << ", has_executable=" << results.has_executable 586 archive_is_valid_ =
572 << " has_archive=" << results.has_archive; 587 (results.success ? ArchiveValid::VALID : ArchiveValid::INVALID);
573 } else { 588 archived_executable_ = results.has_executable;
574 DVLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value(); 589 archived_binary_.CopyFrom(results.archived_binary);
575 } 590 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value()
591 << ", has_executable=" << results.has_executable
592 << ", has_archive=" << results.has_archive
593 << ", success=" << results.success;
594
576 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileSuccess", results.success); 595 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileSuccess", results.success);
577 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", 596 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable",
578 archived_executable_); 597 archived_executable_);
579 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", 598 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable",
580 results.has_archive && !archived_executable_); 599 results.has_archive && !archived_executable_);
581 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", 600 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime",
582 base::TimeTicks::Now() - zip_analysis_start_time_); 601 base::TimeTicks::Now() - zip_analysis_start_time_);
583 for (const auto& file_name : results.archived_archive_filenames) 602 for (const auto& file_name : results.archived_archive_filenames)
584 RecordArchivedArchiveFileExtensionType(file_name); 603 RecordArchivedArchiveFileExtensionType(file_name);
585 604
586 if (!archived_executable_ && !results.has_archive) { 605 if (!archived_executable_) {
587 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); 606 if (results.has_archive) {
588 return; 607 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE;
608 } else if (!results.success && CanReportInvalidArchives()) {
609 type_ = ClientDownloadRequest::INVALID_ZIP;
610 } else {
611 // Normal zip w/o EXEs, or invalid zip and not extended-reporting.
612 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES);
613 return;
614 }
589 } 615 }
590 616
591 if (!archived_executable_ && results.has_archive)
592 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE;
593 OnFileFeatureExtractionDone(); 617 OnFileFeatureExtractionDone();
594 } 618 }
595 619
596 #if defined(OS_MACOSX) 620 #if defined(OS_MACOSX)
597 void StartExtractDmgFeatures() { 621 void StartExtractDmgFeatures() {
598 DCHECK_CURRENTLY_ON(BrowserThread::UI); 622 DCHECK_CURRENTLY_ON(BrowserThread::UI);
599 DCHECK(item_); 623 DCHECK(item_);
600 dmg_analyzer_ = new SandboxedDMGAnalyzer( 624 dmg_analyzer_ = new SandboxedDMGAnalyzer(
601 item_->GetFullPath(), 625 item_->GetFullPath(),
602 base::Bind(&CheckClientDownloadRequest::OnDmgAnalysisFinished, 626 base::Bind(&CheckClientDownloadRequest::OnDmgAnalysisFinished,
603 weakptr_factory_.GetWeakPtr())); 627 weakptr_factory_.GetWeakPtr()));
604 dmg_analyzer_->Start(); 628 dmg_analyzer_->Start();
605 dmg_analysis_start_time_ = base::TimeTicks::Now(); 629 dmg_analysis_start_time_ = base::TimeTicks::Now();
606 } 630 }
607 631
608 void OnDmgAnalysisFinished(const zip_analyzer::Results& results) { 632 void OnDmgAnalysisFinished(const zip_analyzer::Results& results) {
609 DCHECK_CURRENTLY_ON(BrowserThread::UI); 633 DCHECK_CURRENTLY_ON(BrowserThread::UI);
610 DCHECK_EQ(ClientDownloadRequest::MAC_EXECUTABLE, type_); 634 DCHECK_EQ(ClientDownloadRequest::MAC_EXECUTABLE, type_);
611 if (!service_) 635 if (!service_)
612 return; 636 return;
613 637
614 if (results.success) { 638 // Even if !results.success, some of the DMG may have been parsed.
615 archived_executable_ = results.has_executable; 639 archive_is_valid_ =
616 archived_binary_.CopyFrom(results.archived_binary); 640 (results.success ? ArchiveValid::VALID : ArchiveValid::INVALID);
617 DVLOG(1) << "DMG analysis has finished for " 641 archived_executable_ = results.has_executable;
618 << item_->GetFullPath().value() << ", has_executable=" 642 archived_binary_.CopyFrom(results.archived_binary);
619 << results.has_executable; 643 DVLOG(1) << "DMG analysis has finished for " << item_->GetFullPath().value()
620 } else { 644 << ", has_executable=" << results.has_executable
621 DVLOG(1) << "DMG analysis failed for "<< item_->GetFullPath().value(); 645 << ", success=" << results.success;
622 }
623 646
624 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileSuccess", results.success); 647 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileSuccess", results.success);
625 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileHasExecutable", 648 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileHasExecutable",
626 archived_executable_); 649 archived_executable_);
627 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractDmgFeaturesTime", 650 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractDmgFeaturesTime",
628 base::TimeTicks::Now() - dmg_analysis_start_time_); 651 base::TimeTicks::Now() - dmg_analysis_start_time_);
629 652
630 if (!archived_executable_) { 653 if (!archived_executable_) {
631 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); 654 if (!results.success && CanReportInvalidArchives()) {
632 return; 655 type_ = ClientDownloadRequest::INVALID_MAC_ARCHIVE;
656 } else {
657 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES);
658 return;
659 }
633 } 660 }
634 661
635 OnFileFeatureExtractionDone(); 662 OnFileFeatureExtractionDone();
636 } 663 }
637 #endif // defined(OS_MACOSX) 664 #endif // defined(OS_MACOSX)
638 665
639 static void RecordCountOfSignedOrWhitelistedDownload() { 666 static void RecordCountOfSignedOrWhitelistedDownload() {
640 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); 667 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1);
641 } 668 }
642 669
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 if (tab_referrer_url_.is_valid()) { 832 if (tab_referrer_url_.is_valid()) {
806 resource->set_referrer(SanitizeUrl(tab_referrer_url_)); 833 resource->set_referrer(SanitizeUrl(tab_referrer_url_));
807 DVLOG(2) << "tab referrer " << resource->referrer(); 834 DVLOG(2) << "tab referrer " << resource->referrer();
808 } 835 }
809 } 836 }
810 837
811 request.set_user_initiated(item_->HasUserGesture()); 838 request.set_user_initiated(item_->HasUserGesture());
812 request.set_file_basename( 839 request.set_file_basename(
813 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe()); 840 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe());
814 request.set_download_type(type_); 841 request.set_download_type(type_);
842 if (archive_is_valid_ != ArchiveValid::UNSET)
843 request.set_archive_valid(archive_is_valid_ == ArchiveValid::VALID);
815 request.mutable_signature()->CopyFrom(signature_info_); 844 request.mutable_signature()->CopyFrom(signature_info_);
816 if (image_headers_) 845 if (image_headers_)
817 request.set_allocated_image_headers(image_headers_.release()); 846 request.set_allocated_image_headers(image_headers_.release());
818 if (archived_executable_) 847 if (archived_executable_)
819 request.mutable_archived_binary()->Swap(&archived_binary_); 848 request.mutable_archived_binary()->Swap(&archived_binary_);
820 if (!request.SerializeToString(&client_download_request_data_)) { 849 if (!request.SerializeToString(&client_download_request_data_)) {
821 FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO); 850 FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO);
822 return; 851 return;
823 } 852 }
824 service_->client_download_request_callbacks_.Notify(item_, &request); 853 service_->client_download_request_callbacks_.Notify(item_, &request);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 << cert->subject().GetDisplayName() 958 << cert->subject().GetDisplayName()
930 << " issuer=" << issuer->subject().GetDisplayName(); 959 << " issuer=" << issuer->subject().GetDisplayName();
931 return true; 960 return true;
932 } 961 }
933 } 962 }
934 cert = issuer; 963 cert = issuer;
935 } 964 }
936 return false; 965 return false;
937 } 966 }
938 967
968 enum class ArchiveValid { UNSET, VALID, INVALID };
969
939 // The DownloadItem we are checking. Will be NULL if the request has been 970 // The DownloadItem we are checking. Will be NULL if the request has been
940 // canceled. Must be accessed only on UI thread. 971 // canceled. Must be accessed only on UI thread.
941 content::DownloadItem* item_; 972 content::DownloadItem* item_;
942 // Copies of data from |item_| for access on other threads. 973 // Copies of data from |item_| for access on other threads.
943 std::vector<GURL> url_chain_; 974 std::vector<GURL> url_chain_;
944 GURL referrer_url_; 975 GURL referrer_url_;
945 // URL chain of redirects leading to (but not including) |tab_url|. 976 // URL chain of redirects leading to (but not including) |tab_url|.
946 std::vector<GURL> tab_redirects_; 977 std::vector<GURL> tab_redirects_;
947 // URL and referrer of the window the download was started from. 978 // URL and referrer of the window the download was started from.
948 GURL tab_url_; 979 GURL tab_url_;
949 GURL tab_referrer_url_; 980 GURL tab_referrer_url_;
950 981
951 bool archived_executable_; 982 bool archived_executable_;
983 ArchiveValid archive_is_valid_;
984
952 ClientDownloadRequest_SignatureInfo signature_info_; 985 ClientDownloadRequest_SignatureInfo signature_info_;
953 scoped_ptr<ClientDownloadRequest_ImageHeaders> image_headers_; 986 scoped_ptr<ClientDownloadRequest_ImageHeaders> image_headers_;
954 google::protobuf::RepeatedPtrField<ClientDownloadRequest_ArchivedBinary> 987 google::protobuf::RepeatedPtrField<ClientDownloadRequest_ArchivedBinary>
955 archived_binary_; 988 archived_binary_;
956 CheckDownloadCallback callback_; 989 CheckDownloadCallback callback_;
957 // Will be NULL if the request has been canceled. 990 // Will be NULL if the request has been canceled.
958 DownloadProtectionService* service_; 991 DownloadProtectionService* service_;
959 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_; 992 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
960 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 993 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
961 const bool pingback_enabled_; 994 const bool pingback_enabled_;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 GURL DownloadProtectionService::GetDownloadRequestUrl() { 1236 GURL DownloadProtectionService::GetDownloadRequestUrl() {
1204 GURL url(kDownloadRequestUrl); 1237 GURL url(kDownloadRequestUrl);
1205 std::string api_key = google_apis::GetAPIKey(); 1238 std::string api_key = google_apis::GetAPIKey();
1206 if (!api_key.empty()) 1239 if (!api_key.empty())
1207 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); 1240 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true));
1208 1241
1209 return url; 1242 return url;
1210 } 1243 }
1211 1244
1212 } // namespace safe_browsing 1245 } // 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