1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/incident_reporting/script_request_detector.h"
7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h"
9 #include "chrome/browser/safe_browsing/incident_reporting/script_request_incident.h"
10 #include "chrome/common/safe_browsing/csd.pb.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/render_frame_host.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/resource_request_info.h"
15 #include "content/public/browser/site_instance.h"
16 #include "crypto/sha2.h"
17 #include "net/url_request/url_request.h"
22 const char* const kHashes
[] = {
23 "\x2b\x45\xc0\xda\x79\x4c\x65\x19\x4d\x78\x98\x85\x6c\xe8\xbd\x95"
24 "\xf5\x9a\x5a\xf4\x4e\xf9\x9f\x4f\x93\x35\x3b\xa8\x52\xc0\x02\xfb",
25 "\x05\xce\x5b\xda\xff\x28\x17\xf9\xc9\x38\x62\x6a\x39\x1b\x76\x56"
26 "\xe3\xef\xed\x48\x1f\xe3\xae\x93\x4f\xd3\xd2\x96\x87\x53\x45\xf0",
27 "\x3a\x65\x3d\x71\x2d\x3a\xc4\x35\x10\xd7\x01\xb6\xbb\xfb\x49\xda"
28 "\x12\xce\x09\xfd\x48\x45\x76\x64\x12\xff\xd4\x7c\x61\x47\x3c\x0b",
29 "\x95\x8e\x4d\x65\xac\xea\x96\xe5\x11\xd9\xfa\xcc\xcc\xb7\xcd\xb3"
30 "\xcb\x8f\x4d\xf0\xf8\x72\xa0\xc5\x87\x02\xad\xe4\x1f\x3d\xfa\xf2",
31 "\x2b\x8f\x58\x38\xeb\x87\x5d\xa0\x14\x90\x95\x89\x04\xd3\xe5\x89"
32 "\xc5\xd7\x7a\xb6\x48\x53\x18\xfe\x71\x3a\x6a\xfd\xf0\xb3\x6e\xa8",
33 "\xa9\x18\x65\x4d\xd3\xf5\xdf\x09\xf6\xe7\xfe\x21\x0f\x11\x35\x9a"
34 "\x53\xbf\xb4\xa8\x5e\x23\xb1\x0c\x3c\x64\x94\xf5\x08\x9b\x29\x15",
35 "\x5a\x2b\x9b\x45\x81\x5c\x4b\xa5\xf5\x9b\x54\x78\x21\x73\x79\x87"
36 "\x37\xdb\x88\x97\xd9\x76\xd9\x21\x80\xfc\x54\x83\x77\xdb\x17\x7f",
37 "\xd5\xab\x93\xdc\x3a\xd2\x40\xee\x77\x82\x12\x5c\xf7\x7f\x91\x5c"
38 "\x56\x62\x17\xbb\x4e\x6a\xb8\x38\x62\x9d\x0a\xbe\xd3\x8f\x50\xdb",
39 "\xdb\x73\x50\xd3\x58\x50\x2e\xfc\x00\xca\xef\x9d\x68\xf4\xb5\x77"
40 "\x2b\x00\xf9\x7d\xf8\x89\x96\x6e\x35\x22\x17\x35\x4d\xb2\x89\xb3",
41 "\xdc\xf1\x0b\xb3\x29\x98\xac\x40\x24\x16\x09\x4b\x50\x3c\xe2\xa7"
42 "\x7f\xde\x5f\xdf\x76\x4a\x29\x54\xbc\x49\xd6\x67\x11\x92\x16\xdf",
43 "\x98\x28\x26\x7a\xa9\xc9\x8b\xab\xd6\x64\xe4\xd6\x89\x70\x67\x97"
44 "\x84\x37\x92\x8b\x1b\xa4\xdf\x4f\x49\xc9\x0a\x12\x15\xff\x6e\x91",
45 "\x30\xa5\x65\x41\xaf\x60\x9d\x2a\x84\x38\x98\xf0\x41\xa9\x4f\x97"
46 "\xbd\x39\x20\xad\x94\x3a\x0b\x3e\x43\xa4\xe1\x91\x90\x9f\xdf\x25",
47 "\x7b\x48\x72\x6d\x40\xc1\x2f\xac\xf7\x9f\x73\x84\xc5\x2a\x7a\x98"
48 "\x6e\x98\x87\xb7\xe0\x65\xbd\x12\xc6\x27\x89\x56\x87\x3d\x36\x47",
49 "\x7b\x57\x48\xde\x08\x7e\x8e\xba\xe9\x61\xa8\xec\xa9\x14\x70\xeb"
50 "\x6f\x70\x3d\xd7\xb7\x73\x4b\x9e\x1c\x01\x80\x39\x64\x6a\x1e\xee",
51 "\x1d\x86\xb8\x5a\x0e\x22\x41\xac\xbf\x7b\x35\x26\x89\x98\x46\x1e"
52 "\x9d\xc2\x59\x6c\x33\xe3\xb7\x63\xed\x29\xf9\x49\x2c\xec\x93\xb5",
53 "\x2e\xf3\x04\xd3\x5d\x4b\x58\xc7\x2f\x8b\xb8\xe9\x77\x01\xa8\x78"
54 "\x1b\x4e\xea\x16\xca\x86\xdb\x76\x04\x8e\xc6\x84\x10\x15\x3c\xe6",
55 "\xec\x06\x16\xaa\xdc\x96\xe4\xbb\xf9\x76\xb4\x4c\x6e\x1c\x7a\x55"
56 "\xc6\x6f\x15\x00\x2e\xc7\x5d\xbe\x81\x6b\x74\x00\xe6\x29\x8e\x4e",
57 "\xba\x4b\xce\xb5\x52\x2b\x0a\xc6\x13\x87\x56\xd2\x2d\x80\x6f\x77"
58 "\x5a\x9d\x7d\x24\x04\xfd\x41\xe4\x3a\x1a\xd3\xcf\x76\xf5\x21\x4b",
59 "\xaa\xab\xfd\x8d\x8a\x43\x9b\x99\x98\xad\x01\xec\xc5\xbb\x40\x80"
60 "\x78\x44\xe4\xec\x44\x94\x5f\xe2\xb2\xc2\xd3\x87\xe1\x21\xd0\x1f",
61 "\x78\x64\x83\x81\xca\x8f\x08\x92\xd2\x95\x36\xab\x77\xff\xcb\xf4"
62 "\xb9\x5c\xc0\xa1\xd7\xfa\xf2\x6e\x6c\xa0\xc5\xfb\xe1\x49\x4a\x7e",
63 "\x91\x1e\x2b\xb9\x6b\x12\x32\xc3\x74\xab\xf1\x6b\xaf\xfa\x40\x1c"
64 "\x25\x50\x3f\x2f\x6e\x25\x95\x09\x5f\x7e\xc4\x91\x56\x56\xbd\x34",
65 "\xa1\xaf\x68\xf8\xdc\x2d\x52\x6a\xe8\xd2\x13\xcd\x73\x05\xf7\x3e"
66 "\xb1\x8b\x52\xb1\x69\xea\x64\x24\x2c\x79\x76\x81\x11\x9d\xa0\x71",
67 "\x8e\x3c\xe6\x2f\xcb\xea\x7a\x1a\x31\x11\xa7\x52\xfd\x3f\x68\xca"
68 "\x7b\xf0\x22\xd9\x6f\xd7\x21\x62\xe4\xb9\x05\x85\x93\xd0\xea\xfb",
69 "\xab\x13\xfc\x28\x67\x26\xb0\x35\x93\x82\xba\x70\xda\x2d\xcc\xa9"
70 "\x8e\x0b\xee\xd8\xd1\x93\x89\x9b\x53\x9f\xf8\x12\x83\x13\x95\x7d",
71 "\xe9\x7a\x20\xc8\x98\x04\x34\xe9\x36\x9b\x9b\x3c\x19\x2b\xe0\xf5"
72 "\xdf\xc7\x7f\x4e\x94\x1b\x8a\x0a\xf6\x35\xba\xef\xbc\x18\x79\x26",
73 "\x24\x15\x42\x76\x4d\x29\xae\x4e\x1b\x2b\xd5\x8a\xdb\x85\x77\xea"
74 "\xe6\xc4\x21\x26\x83\x17\x3e\x7f\xe1\xf4\xdc\xe8\xd1\xee\x38\xac",
75 "\xbb\x44\xfe\x76\xeb\x37\x4f\x4e\xd2\x99\x70\x9e\x20\x7f\x08\x30"
76 "\xec\x7b\xe9\x3a\x59\x81\x82\x3e\x45\x01\x41\x8d\xe5\x32\x74\x68",
77 "\x5a\x18\x08\xb9\xb8\xc3\x16\x5f\x4b\x96\x6a\x81\x4f\xeb\xc1\xe0"
78 "\x44\x05\xf5\xea\xa9\x34\xeb\xaa\x7e\x97\xd1\xf1\xd4\xd3\x9c\x30",
79 "\xac\x93\xea\x0d\xd5\xdb\xa4\xe9\x2f\xa2\xdd\x1a\x49\x4b\xdb\x54"
80 "\x8a\xb0\x93\x2f\x6d\x48\x54\x39\x30\xf1\x8c\x89\x87\xf2\x4b\x97",
81 "\x90\x55\x4d\xe7\xcc\x8f\x6f\x3a\xa5\xf9\x90\xb7\x22\xf8\xe6\xf9"
82 "\x33\x9e\xb6\x2d\x47\x97\x42\x3c\xd7\x5f\x89\x1e\x32\xb9\xcc\x59",
83 "\xdf\xb0\xe0\x83\xfd\xd1\x3f\x0b\xad\xd6\x08\x9d\x47\x91\x10\xba"
84 "\x59\xdc\x87\xd3\x68\xf1\x5c\xdc\x64\xf9\xdd\xf0\xe8\xd5\xdd\x02",
85 "\x3a\xa0\x93\x8c\x7c\x7f\x9b\x9a\x2a\x87\x60\x6d\xd5\x73\x6d\xa4"
86 "\xc6\xac\x84\x07\x68\xba\x43\x94\x24\x1f\x9c\x5f\x1b\x87\x54\x82",
87 "\x76\x5f\xad\xc9\xb6\x00\xf0\x28\x37\x3e\xbe\xfb\x35\x2b\x95\xac"
88 "\xc3\x54\x09\x2b\x04\x72\x92\xbb\x3a\x6e\x5c\x78\xb4\xa8\x87\x58",
89 "\xec\x33\xf1\x38\x85\xf0\x1c\x1e\xee\xca\x05\x2d\x9b\xd3\x4f\x8a"
90 "\x54\x6b\x91\x36\x10\x64\xf6\x64\xbe\x1d\xf4\xa5\xa1\x22\x8e\x97",
91 "\x75\xa3\xd3\x53\xb0\x57\xbe\x92\x9c\xf5\xf9\xc1\x30\x95\x10\xee"
92 "\x93\xc0\x4e\x48\x9d\x4a\xa1\x8d\x40\xe5\xa2\x42\xd7\xf2\xc2\x77",
93 "\x21\x66\x33\xff\xc3\xfa\xe1\x7a\xa1\x06\xf2\x9e\x2f\xc6\xcc\x93"
94 "\x1e\x62\x17\xf1\xcc\x02\x2f\x39\x80\xee\x34\x4a\x85\xc8\x99\xed",
95 "\x9b\x62\xc6\x2b\xc9\xb0\xf9\xbd\x93\x1a\xfd\xed\xfb\x68\xa0\xc2"
96 "\x15\xfe\x34\xea\xc4\x89\x73\x9e\x70\x93\xe1\x1f\x4a\x75\xbe\x09",
97 "\xb9\xe4\x66\x44\xea\x77\xe1\x74\x3d\x92\xcf\x6c\x20\x7e\xbf\x46"
98 "\xfd\x4f\x4e\x82\x17\xa8\x7d\x3d\x19\xd4\xda\xde\x75\x74\xf1\x13",
99 "\x8b\x2e\x30\xfa\x2e\xe1\xa1\x8e\xb6\x00\xb9\xe3\xc2\xc9\xa4\xad"
100 "\x70\x03\x72\xea\xa8\x68\xdc\x95\x43\x6d\xdf\x40\x26\x58\xde\xe6",
103 Profile
* GetProfileForRenderProcessId(int render_process_id
) {
104 // How to get a profile from a RenderProcess id:
105 // 1) Get the RenderProcessHost
106 // 2) From 1) Get the BrowserContext
107 // 3) From 2) Get the Profile.
108 Profile
* profile
= nullptr;
109 content::RenderProcessHost
* render_process_host
=
110 content::RenderProcessHost::FromID(render_process_id
);
111 if (render_process_host
) {
112 content::BrowserContext
* browser_context
=
113 render_process_host
->GetBrowserContext();
115 profile
= Profile::FromBrowserContext(browser_context
);
120 GURL
GetUrlForRenderFrameId(int render_process_id
, int render_frame_id
) {
121 content::RenderFrameHost
* render_frame_host
=
122 content::RenderFrameHost::FromID(render_process_id
, render_frame_id
);
123 if (render_frame_host
)
124 return render_frame_host
->GetLastCommittedURL();
130 namespace safe_browsing
{
132 ScriptRequestDetector::ScriptRequestDetector(
133 scoped_ptr
<IncidentReceiver
> incident_receiver
)
134 : incident_receiver_(incident_receiver
.Pass()),
135 allow_null_profile_for_testing_(false),
136 weak_ptr_factory_(this) {
137 InitializeScriptSet();
140 ScriptRequestDetector::~ScriptRequestDetector() {
143 void ScriptRequestDetector::OnResourceRequest(const net::URLRequest
* request
) {
144 // Only look at actual net requests (e.g., not chrome-extensions://id/foo.js).
145 if (!request
->url().SchemeIsHTTPOrHTTPS())
148 const content::ResourceRequestInfo
* request_info
=
149 content::ResourceRequestInfo::ForRequest(request
);
151 if (request_info
->GetResourceType() != content::RESOURCE_TYPE_SCRIPT
)
154 DVLOG(1) << "Script request: " << request
->url().spec();
156 std::string
url(request
->url().host() + request
->url().path());
157 std::string
script_digest(crypto::kSHA256Length
, '\0');
158 crypto::SHA256HashString(url
.c_str(), &script_digest
[0],
159 crypto::kSHA256Length
);
161 if (script_set_
.count(script_digest
)) {
162 DVLOG(1) << "Script detector match found.";
164 scoped_ptr
<ClientIncidentReport_IncidentData_ScriptRequestIncident
>
166 new ClientIncidentReport_IncidentData_ScriptRequestIncident());
167 incident_data
->set_script_digest(script_digest
);
169 // This next bit of work needs a profile, so has to happen on the UI
171 int render_process_id
= 0;
172 int render_frame_id
= 0;
173 content::ResourceRequestInfo::GetRenderFrameForRequest(
174 request
, &render_process_id
, &render_frame_id
);
176 content::BrowserThread::PostTask(
177 content::BrowserThread::UI
, FROM_HERE
,
178 base::Bind(&ScriptRequestDetector::ReportIncidentOnUIThread
,
179 weak_ptr_factory_
.GetWeakPtr(), render_process_id
,
180 render_frame_id
, base::Passed(&incident_data
)));
184 void ScriptRequestDetector::set_allow_null_profile_for_testing(
185 bool allow_null_profile_for_testing
) {
186 allow_null_profile_for_testing_
= allow_null_profile_for_testing
;
189 void ScriptRequestDetector::InitializeScriptSet() {
190 // Store a hashed set of decoded string hashes. Probably slower than a linear
191 // search for this size list, but this is only temporary.
192 for (const char* encoded_hash
: kHashes
)
193 script_set_
.insert(std::string(encoded_hash
, crypto::kSHA256Length
));
196 void ScriptRequestDetector::ReportIncidentOnUIThread(
197 int render_process_id
,
199 scoped_ptr
<ClientIncidentReport_IncidentData_ScriptRequestIncident
>
201 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
203 Profile
* profile
= GetProfileForRenderProcessId(render_process_id
);
204 if (profile
|| allow_null_profile_for_testing_
) {
205 // Add the URL obtained from the RenderFrameHost, if available.
206 GURL host_url
= GetUrlForRenderFrameId(render_process_id
, render_frame_id
);
207 if (host_url
.is_valid())
208 incident_data
->set_inclusion_origin(host_url
.GetOrigin().spec());
210 incident_receiver_
->AddIncidentForProfile(
212 make_scoped_ptr(new ScriptRequestIncident(incident_data
.Pass())));
216 } // namespace safe_browsing