diff options
author | tsepez@chromium.org <tsepez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-28 05:27:20 +0000 |
---|---|---|
committer | tsepez@chromium.org <tsepez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-28 05:27:20 +0000 |
commit | 7439a2a660cef336fe5e57abc73607fdf1d2e794 (patch) | |
tree | 538884d39d83f5a47ceb6bcf7473ffe2491181e6 /content/browser/loader | |
parent | 892940e15b801be1ab152a5672c2b3236730d790 (diff) | |
download | chromium_src-7439a2a660cef336fe5e57abc73607fdf1d2e794.zip chromium_src-7439a2a660cef336fe5e57abc73607fdf1d2e794.tar.gz chromium_src-7439a2a660cef336fe5e57abc73607fdf1d2e794.tar.bz2 |
Apply cross-origin auth prompt blocking to image resources only.
This CL applies both cross-origin basic auth prompt blocking, and
the stripping of embedded URL identities to image src URLs only.
See the bug for a description of why we think this is acceptable.
The first part of the change is to rename HttpAuthResourceType to
HttpAuthRelationType, to avoid confusion with ResourceType since
both are now used closely together.
Then, BuildLoadFlagsForRequest() is made a method, rather than just
a function, so it can access information needed to compute the relation
type. It blocks the sending of credentials as well as the popping
of popups for images under the right conditions.
BUG=174179
Review URL: https://chromiumcodereview.appspot.com/17738004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209100 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/loader')
-rw-r--r-- | content/browser/loader/resource_dispatcher_host_impl.cc | 136 | ||||
-rw-r--r-- | content/browser/loader/resource_dispatcher_host_impl.h | 19 |
2 files changed, 80 insertions, 75 deletions
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index cc5db10..5613eff 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc @@ -245,49 +245,6 @@ net::Error CallbackAndReturn( return net_error; } -int BuildLoadFlagsForRequest( - const ResourceHostMsg_Request& request_data, - int child_id, - bool is_sync_load) { - int load_flags = request_data.load_flags; - - // Although EV status is irrelevant to sub-frames and sub-resources, we have - // to perform EV certificate verification on all resources because an HTTP - // keep-alive connection created to load a sub-frame or a sub-resource could - // be reused to load a main frame. - load_flags |= net::LOAD_VERIFY_EV_CERT; - if (request_data.resource_type == ResourceType::MAIN_FRAME) { - load_flags |= net::LOAD_MAIN_FRAME; - } else if (request_data.resource_type == ResourceType::SUB_FRAME) { - load_flags |= net::LOAD_SUB_FRAME; - } else if (request_data.resource_type == ResourceType::PREFETCH) { - load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); - } else if (request_data.resource_type == ResourceType::FAVICON) { - load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; - } - - if (is_sync_load) - load_flags |= net::LOAD_IGNORE_LIMITS; - - ChildProcessSecurityPolicyImpl* policy = - ChildProcessSecurityPolicyImpl::GetInstance(); - if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) { - load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA | - net::LOAD_DO_NOT_SAVE_COOKIES); - } - - // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only - // allow requesting them if requester has ReadRawCookies permission. - if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) - && !policy->CanReadRawCookies(child_id)) { - VLOG(1) << "Denied unauthorized request for raw headers"; - load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; - } - - return load_flags; -} - int GetCertID(net::URLRequest* request, int child_id) { if (request->ssl_info().cert.get()) { return CertStore::GetInstance()->StoreCert(request->ssl_info().cert.get(), @@ -654,21 +611,6 @@ bool ResourceDispatcherHostImpl::AcceptAuthRequest( if (delegate_ && !delegate_->AcceptAuthRequest(loader->request(), auth_info)) return false; - // Prevent third-party content from prompting for login, unless it is - // a proxy that is trying to authenticate. This is often the foundation - // of a scam to extract credentials for another domain from the user. - if (!auth_info->is_proxy) { - HttpAuthResourceType resource_type = - HttpAuthResourceTypeOf(loader->request()); - UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthResource", - resource_type, - HTTP_AUTH_RESOURCE_LAST); - - // TODO(tsepez): Return false on HTTP_AUTH_RESOURCE_BLOCKED_CROSS. - // The code once did this, but was changed due to http://crbug.com/174129. - // http://crbug.com/174179 has been filed to track this issue. - } - return true; } @@ -1798,22 +1740,22 @@ void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute( delete loaders; } -ResourceDispatcherHostImpl::HttpAuthResourceType -ResourceDispatcherHostImpl::HttpAuthResourceTypeOf(net::URLRequest* request) { - // Use the same critera as for cookies to determine the sub-resource type - // that is requesting to be authenticated. - if (!request->first_party_for_cookies().is_valid()) - return HTTP_AUTH_RESOURCE_TOP; +ResourceDispatcherHostImpl::HttpAuthRelationType +ResourceDispatcherHostImpl::HttpAuthRelationTypeOf( + const GURL& request_url, + const GURL& first_party) { + if (!first_party.is_valid()) + return HTTP_AUTH_RELATION_TOP; if (net::registry_controlled_domains::SameDomainOrHost( - request->first_party_for_cookies(), request->url(), + first_party, request_url, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)) - return HTTP_AUTH_RESOURCE_SAME_DOMAIN; + return HTTP_AUTH_RELATION_SAME_DOMAIN; if (allow_cross_origin_auth_prompt()) - return HTTP_AUTH_RESOURCE_ALLOWED_CROSS; + return HTTP_AUTH_RELATION_ALLOWED_CROSS; - return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; + return HTTP_AUTH_RELATION_BLOCKED_CROSS; } bool ResourceDispatcherHostImpl::allow_cross_origin_auth_prompt() { @@ -1864,4 +1806,62 @@ void ResourceDispatcherHostImpl::UnregisterResourceMessageDelegate( } } +int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest( + const ResourceHostMsg_Request& request_data, + int child_id, + bool is_sync_load) { + int load_flags = request_data.load_flags; + + // Although EV status is irrelevant to sub-frames and sub-resources, we have + // to perform EV certificate verification on all resources because an HTTP + // keep-alive connection created to load a sub-frame or a sub-resource could + // be reused to load a main frame. + load_flags |= net::LOAD_VERIFY_EV_CERT; + if (request_data.resource_type == ResourceType::MAIN_FRAME) { + load_flags |= net::LOAD_MAIN_FRAME; + } else if (request_data.resource_type == ResourceType::SUB_FRAME) { + load_flags |= net::LOAD_SUB_FRAME; + } else if (request_data.resource_type == ResourceType::PREFETCH) { + load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); + } else if (request_data.resource_type == ResourceType::FAVICON) { + load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN; + } else if (request_data.resource_type == ResourceType::IMAGE) { + // Prevent third-party image content from prompting for login, as this + // is often a scam to extract credentials for another domain from the user. + // Only block image loads, as the attack applies largely to the "src" + // property of the <img> tag. It is common for web properties to allow + // untrusted values for <img src>; this is considered a fair thing for an + // HTML sanitizer to do. Conversely, any HTML sanitizer that didn't + // filter sources for <script>, <link>, <embed>, <object>, <iframe> tags + // would be considered vulnerable in and of itself. + HttpAuthRelationType relation_type = HttpAuthRelationTypeOf( + request_data.url, request_data.first_party_for_cookies); + if (relation_type == HTTP_AUTH_RELATION_BLOCKED_CROSS) { + load_flags |= (net::LOAD_DO_NOT_SEND_AUTH_DATA | + net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); + } + } + + if (is_sync_load) + load_flags |= net::LOAD_IGNORE_LIMITS; + + ChildProcessSecurityPolicyImpl* policy = + ChildProcessSecurityPolicyImpl::GetInstance(); + if (!policy->CanSendCookiesForOrigin(child_id, request_data.url)) { + load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SEND_AUTH_DATA | + net::LOAD_DO_NOT_SAVE_COOKIES); + } + + // Raw headers are sensitive, as they include Cookie/Set-Cookie, so only + // allow requesting them if requester has ReadRawCookies permission. + if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) + && !policy->CanReadRawCookies(child_id)) { + VLOG(1) << "Denied unauthorized request for raw headers"; + load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; + } + + return load_flags; +} + } // namespace content diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index abff21c..3ba2491 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h @@ -379,15 +379,16 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl ResourceContext* context); // Relationship of resource being authenticated with the top level page. - enum HttpAuthResourceType { - HTTP_AUTH_RESOURCE_TOP, // Top-level page itself - HTTP_AUTH_RESOURCE_SAME_DOMAIN, // Sub-content from same domain - HTTP_AUTH_RESOURCE_BLOCKED_CROSS, // Blocked Sub-content from cross domain - HTTP_AUTH_RESOURCE_ALLOWED_CROSS, // Allowed Sub-content per command line - HTTP_AUTH_RESOURCE_LAST + enum HttpAuthRelationType { + HTTP_AUTH_RELATION_TOP, // Top-level page itself + HTTP_AUTH_RELATION_SAME_DOMAIN, // Sub-content from same domain + HTTP_AUTH_RELATION_BLOCKED_CROSS, // Blocked Sub-content from cross domain + HTTP_AUTH_RELATION_ALLOWED_CROSS, // Allowed Sub-content per command line + HTTP_AUTH_RELATION_LAST }; - HttpAuthResourceType HttpAuthResourceTypeOf(net::URLRequest* request); + HttpAuthRelationType HttpAuthRelationTypeOf(const GURL& request_url, + const GURL& first_party); // Returns whether the URLRequest identified by |transferred_request_id| is // currently in the process of being transferred to a different renderer. @@ -406,6 +407,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl void UnregisterResourceMessageDelegate(const GlobalRequestID& id, ResourceMessageDelegate* delegate); + int BuildLoadFlagsForRequest(const ResourceHostMsg_Request& request_data, + int child_id, + bool is_sync_load); + LoaderMap pending_loaders_; // Collection of temp files downloaded for child processes via |