- From: Poul-Henning Kamp <phk@phk.freebsd.dk>
- Date: Thu, 04 Sep 2014 07:50:07 +0000
- To: Brian Smith <brian@briansmith.org>
- cc: "Roy T. Fielding" <fielding@gbiv.com>, HTTP Working Group <ietf-http-wg@w3.org>
-------- In message <CAFewVt5hcXRx66FkxM83cX6v_idQPuXQhj58J7UyHNt_V1JyvA@mail.gmail.com> , Brian Smith writes: >In order for padding to be a useful security feature, it must provide >end-to-end protection. That is, when the origin server sends >data||padding, that data||padding needs to be preserved and processed >as a single unit through all hops (i.e. by any/all proxies). It's not that simple once you start to think about it. We have two padding issues: header-sets and content. For header-sets the standard mandates modifications along the path, Connection: and (X-)Forwarded-For being the primary examples. The effects of HPACK and available compression states also adds to our trouble here. There is simply no way the browser or PHP code can gain any insight into what amount of padding would be needed mask these changes, so padding header-sets seems like it must be hop-by-hop. That doesn't make it easier though. A client proxy has no insight into how large any individual web-apps header-set can be, so the only truly safe algorithm would be: receive(request) strip_padding(request) if size(request) > cur_max: cur_max = size(request) + random(N...M) pad(request, cur_max) send(request) cur_max will eventually be determined by the most silly PHP programmers use of :query arguments and the most ridiculous cookies on the entire web. Or worse: this algorithm is also a trival way to make clients DoS themselves. A clear no-go in my mind. A more robust but less secure algorithm would be to merely randomize the size of the header-set: receive(request) strip_padding(request) // XXX: or not ? pad(request, random(N...M)) send(request) This will only be OK from a security point of view if the browser and application developers understand that masking depends on them always using roughly same-size header-sets. Most web-shops do not do this today: It is utterly trivial to tell browsing wares from adding wares to shopping basket from paying and checking out, simply based on packet-cluster sizes. The most practical way to pad header-sets would be to define a Pad: header. Proxies not actively participating in Padding should treat it as end-to-end, which existing HTTP/1 proxies automatically will do. "Padding-aware" proxies should treat it as hop-by-hop. HPACK would spit out Pad: as the last header in verbatim mode, only then can the necessary length be calculated. All in all, it is not obvious to me that all that complexity would add significant security value over the true and KISS end-to-end solution: Browsers emit a random sized "Junk:" header on all TLS requests, and servers respond in kind. For content proxies are generally hands off, but we are not quite in the clear yet: For instance this is going to happen a lot: A website is implemented across a number of webservers using the well known static/images/database/... pattern. These webservers most likely talk plaintext-HTTP. A proxy or load-balancer wraps all the traffic up, adding HTTP/2 and/or TLS. So the proxy has to add the content padding ? Based on what ? Configured how ? That's not going to happen... And how does the padding survive further HTTP/1.1 <-> HTTP/2.0 conversions ? It seems to me that padding the content can only happen at the application level, not necessarily by the application, it could be done by "middleware", CMS or web-server, but it should happen where the content type is authoritatively known so the content itself can be padded. (ie: adding comments to HTML/CSS/JS etc.) There is whole level of pain in form-submission here, where the web-app should inform the client how much it should pad the returned form-data, but I think that would be W3C territory ? It is not at all obvious to me where the responsibility for padding should be placed, and the unintended interactions of too many players, application, middleware, HTTP/2 and TLS, all having their laddle in the pot worries me, both wrt. security and performance. But nowhere in this picture do I see padding inside the HTTP/2.0 frames being part of the solution. In particular because 50%+ of all HTTP traffic is plain-text with no privacy-concerns which doesn't want and needs neither TLS nor padding. I think we should remove padding from the HTTP/2 frames. On the other hand, I think there is good value in Roys proposal for a hop-to-hop "NO-OP" frame type, if nothing else for debugging. Specific implementations which know they have full and true end-to-end visibility can obviously use that to implement hop-by-hop padding. -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk@FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence.
Received on Thursday, 4 September 2014 07:50:35 UTC