Re: h2 padding

--------
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