9

The Chrome WebRequests API mentions that specific request headers are not available to the onBeforeSendHeaders event, meaning that extensions cannot read and/or modify these headers. Here is an excerpt from the documentation:

The following headers are currently not provided to the onBeforeSendHeaders event. This list is not guaranteed to be complete nor stable.

  • Authorization
  • Cache-Control
  • Connection
  • Content-Length
  • Host
  • If-Modified-Since
  • If-None-Match
  • If-Range
  • Partial-Data
  • Pragma
  • Proxy-Authorization
  • Proxy-Connection
  • Transfer-Encoding

Is there a security reason to disable extensions from reading or writing these? How could an extension act malicious if it could read/write these values?


Clarification: I am aware why read access to some of these is a bad idea, most prominently any header featuring authentication data. However, other headers such as Host, Connection or Content-Length are a complete enigma to me.

Furthermore, it's unclear to me why some of these headers are completely inaccessible to extensions, instead of allowing setting a value or appending a value, even if read access is not granted.

  • Reading Authorization headers would lead to theft of authorization tokens like JWT tokens.. – Sir Muffington Jan 23 '20 at 12:00
  • 1
    @SirMuffington It still does not explain why an extension is not allowed to set them. –  Jan 23 '20 at 12:01
  • I'm going to guess that it's supposed to limit the damage malicious extensions can do (not sure how much sense that makes). This has been the case [since at least Chrome 41](https://bugs.chromium.org/p/chromium/issues/detail?id=464809&can=1&q=webrequests%20onbeforesendheaders&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified). – Fire Quacker Jan 24 '20 at 02:02
  • May be something related to the ability of uniquely identifying users too. – Overmind Jan 27 '20 at 12:41
  • Btw, can't ModHeader alter these too, did you test ? – Overmind Jan 27 '20 at 12:47
  • @Overmind I tried to modify the `Host` header with ModHeader and I can confirm it does **not** work. –  Jan 27 '20 at 12:51
  • It means indeed they made some sort of protection. It's worth investigating further. – Overmind Jan 27 '20 at 13:13
  • 1
    This question *is* my investigation. I know *that* it exists, I just want to know why. –  Jan 27 '20 at 13:20
  • Why isn't the explanation [given](https://developer.chrome.com/extensions/webRequest#life_cycle_footnote) "the web request API presents an abstraction of the network stack..." sufficient? – nobody Jul 12 '20 at 19:20
  • 3
    https://developer.chrome.com/extensions/webRequest#life_cycle_footnote *[...] For this reason, the API does not provide the final HTTP headers that are sent to the network. **For example**, all headers that are related to caching are invisible to the extension.* – Awaaaaarghhh Jul 14 '20 at 04:36

3 Answers3

1

I agree with the OP that, blocking access to only these headers does not make sense while allowing much broader data in terms of security. A malicious plug-in can do so many damage without them.

From the reading of the API documentation, it sounds like the reason for not allowing access to these headers is not necessarily because of a security concern but more because how current Chrome engine works. It sounds like Chrome's request processing pipeline continues even after the API modifications are done. One aspect of it how Chrome manages network requests and caching. Since those downstream components in the request pipeline can make different decisions and change these headers, I'm guessing that's why it's not even letting you read them b/c it cannot guarantee that they will stay the same.

This is based on how they explained it in the chrome.WebRequest documentation

(*) Note that the web request API presents an abstraction of the network stack to the extension. Internally, one URL request can be split into several HTTP requests (for example to fetch individual byte ranges from a large file) or can be handled by the network stack without communicating with the network. For this reason, the API does not provide the final HTTP headers that are sent to the network. For example, all headers that are related to caching are invisible to the extension.

The following headers are currently not provided to the onBeforeSendHeaders event. This list is not guaranteed to be complete nor stable.

... the header list the OP is questioning ....

If you read further down in the page, it explains the cache issue little more. It sounds to me that Chrome doesn't prefer to expose some parts of the request pipeline (specifically things that affects network communication decisions, including caching) probably for some good technical reasons (maybe it requires a major design change).

Since these hidden part of the pipelines may make different decisions after your plugin modifications are done, Chrome does not let you read them because the downstream pipeline components may still change them. See how it talks about "in-memory cache" being invisible to the API. It sounds like a design challenge on Chrome's part (or a preference not to let a plugin affects its network performance). So I would conclude it's not necessarily because of security.

Caching: Chrome employs two caches — an on-disk cache and a very fast in-memory cache. The lifetime of an in-memory cache is attached to the lifetime of a render process, which roughly corresponds to a tab. Requests that are answered from the in-memory cache are invisible to the web request API. If a request handler changes its behavior (for example, the behavior according to which requests are blocked), a simple page refresh might not respect this changed behavior. To make sure the behavior change goes through, call handlerBehaviorChanged() to flush the in-memory cache. But don't do it often; flushing the cache is a very expensive operation. You don't need to call handlerBehaviorChanged() after registering or unregistering an event listener.

K4M
  • 542
  • 3
  • 8
0

Is there a security reason to disable extensions from reading or writing these?

Yes, the headers are used as a means of protection in some or the other form. So innately protecting these headers from tinkering inherits priority.

How could an extension act malicious if it could read/write these values?it's unclear to me why some of these headers are completely inaccessible to extensions, instead of allowing setting a value or appending a value, even if read access is not granted.

How I have tried to come up with below answer: I have elaborated the extension to give a context of use followed by accumulation of information enough to define the associated risk and attack vectors to the headers and list them. Feel free to edit the answer OR enlighten me if you find any information is outdated or not on point.

Authorization The HTTP Authorization request header contains the credentials to authenticate a user agent with a server, usually, but not necessarily, after the server has responded with a 401 Unauthorized status and the WWW-Authenticate header.

The attacker can write the value of authorization with his session's authorization value to make a victim pay for attacker's check out. Reading this value allows the attacker to steal identity and impersonate the user or make actions on his behalf.

Cache-ControlThe Cache-Control HTTP header holds directives (instructions) for caching in both requests and responses. A given directive in a request does not mean the same directive should be in the response.

If this value can be set, then attacker can allow the cache of sensitive information to be stored on browser and access it at later point in time.

ConnectionThe Connection general header controls whether or not the network connection stays open after the current transaction finishes. If the value sent is keep-alive, the connection is persistent and not closed, allowing for subsequent requests to the same server to be done.

Persistent connections also have drawbacks; even when idling they consume server resources, and under heavy load, DoS attacks can be conducted.

Content-LengthThe Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.

The Content-Length header is used for HTTP 1.1 so that the receiving party knows when the current response* has finished, so the connection can be reused for another request. Again if the connection is hold for long, it consumes resources and may lead to DoS.

HostThe Host request header specifies the host and port number of the server to which the request is being sent.

If host header is changed on the fly then the entire request will land on an evil server hosted by attacker, ending up sharing cookie and other sensitive data.

If-Modified-SinceThe If-Modified-Since request HTTP header makes the request conditional: the server will send back the requested resource, with a 200 status, only if it has been last modified after the given date.

Attacker may target GET and HEAD requests for specific host/hosts and alter this particular header to achieve DoS.

If-None-MatchThe If-None-Match HTTP request header makes the request conditional. For GET and HEAD methods, the server will send back the requested resource, with a 200 status, only if it doesn't have an ETag matching the given ones.

Same as If-Modified-Since, attacker may target GET and HEAD requests for specific host/hosts and alter this particular header to achieve DoS.

If-RangeThe If-Range HTTP request header makes a range request conditional: if the condition is fulfilled, the range request will be issued and the server sends back a 206 Partial Content answer with the appropriate body.

Similar to If-Modified-Since, attacker may target requests for specific host/hosts and alter this particular header to achieve DoS attack.

Partial-DataThe Range HTTP request header indicates the part of a document that the server should return. If the server sends back ranges, it uses the 206 Partial Content for the response.

Since the typical overhead between parts of a multipart/byte-ranges payload is around 80 bytes, depending on the selected representation's media type and the chosen boundary parameter length, it can be less efficient to transfer many small disjoint parts than it is to transfer the entire selected representation. A client that cannot process a multipart/byteranges response MUST NOT generate a request that asks for multiple ranges. When a multipart response payload is generated, the server SHOULD send the parts in the same order that the corresponding byte-range-spec appeared in the received Range header field excluding those ranges that were deemed unjustifiable or that were coalesced into other ranges.

PragmaIt is used for backwards compatibility with HTTP/1.0 caches where the Cache-Control HTTP/1.1 header is not yet present. When the Cache-Control header field is also present and understood in a request, Pragma is ignored.

Pragma: no-cache forces caches to submit the request to the origin server for validation before releasing a cached copy. If this is altered successfully, injection in browser can be executed, especially old ones.

Proxy-AuthorizationThe HTTP Proxy-Authorization request header contains the credentials to authenticate a user agent to a proxy server, usually after the server has responded with a 407 Proxy Authentication Required status and the Proxy-Authenticate header.

Similar to Authorization header. The attacker may read the value of this header and use it for malicious purposes.

Proxy-Connection The Proxy-Connection specifies whether the connection is to be kept open after the request has been sent. If the value indicates that the connection can be kept open, the HTTP 1.1 proxy will accept subsequent requests that can be executed against the server URI.

Similar to Connection header, persistent connections also have drawbacks; even when idling they consume server resources, and under heavy load, DoS attacks can be conducted.

Transfer-EncodingThe Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.

Similar to discussion on Partial-Data header, Transfer-Encoding is a hop-by-hop header, that is applied to a message between two nodes, not to a resource itself.

Transfer-Encoding: chunked
Transfer-Encoding: compress
Transfer-Encoding: deflate
Transfer-Encoding: gzip
Transfer-Encoding: identity

for example, chunked encoding is useful when larger amounts of data are sent to the client and the total size of the response may not be known until the request has been fully processed. If the value of this header is changed, it may cause problem with parsing of the data similar to Partial-Data header.

Now, if an extension of browser is exploited by an attacker. There are chances that that it may be used to alter the values or read the values of these headers based on vulnerability of the server/ application/ browser or mix and match of all of them. There is also a possibility where an attacker makes an extension with hidden feature of proxy to intercept or read the traffic through the browser. One such implementation of JavaScript to intercept/read traffic is described here with example scenario and associated code: https://medium.com/dailyjs/how-to-use-javascript-proxies-for-fun-and-profit-365579d4a9f8

Credits/ References:

Arpit Rohela
  • 573
  • 2
  • 12
-1

I think Browser Extensions have risks associated with them that are documented in other places. From what I understand, the question is specifically about this API that Browser Extensions may use. If I understand the question correctly, it is not that they deny access to these headers, it is a question of why. With those things in mind, let's skip over general Browser Extension security and general Request Header security. Let's focus on intention/requirement.

The intention of the API is present in the documentation that the question linked, and can be treated as the requirement:

Use the chrome.webRequest API to observe and analyze traffic and to intercept, block, or modify requests in-flight.

Thus, the requirement of the API is two fold:

  1. Observe and analyze traffic
  2. Intercept, block, or modify requests

This is a valid intention that privacy minded individuals are indirectly thankful for, as it powers ad-blockers and other privacy focused Browser Extensions.

It is not a question of why specific headers are inaccessible. Rather, it is a matter of least-privilege. The API designer is forced to answer the question, "Of all possible headers in the RFC, which ones are necessary to meet the requirements and which are not?".

The API designer can meet the requirements without any of the headers in the list. Also, I think it explains why the documentation notes that the list is neither guaranteed, nor stable. This reads that most headers, in general, are not necessary to meet the intention/requirement.

iraleigh
  • 326
  • 2
  • 11