trailofbits/twa

http/2 false positives?

bortels opened this issue · 8 comments

So - it looks like http/2 servers are giving false positives; I am seeing FAIL on headers that I know are sent (via inspection with curl -vvv) and that other tools (I tried https://tools.geekflare.com/tools/x-frame-options-test and it came back ok). Seen with Flask behind an AWS ALB.

Copy of the headers as see from curl -vvv:

< HTTP/2 200
< date: Mon, 17 Sep 2018 22:52:13 GMT
< content-type: text/html; charset=utf-8
< content-length: 2103
< x-frame-options: SAMEORIGIN
< x-content-type-options: nosniff
< x-xss-protection: 1; mode=block
< referrer-policy: no-referrer
< server: Werkzeug/0.12.2 Python/3.6.5
<

... and so on

Thanks for the report @bortels!

Could you give me a website to test against? http2.akamai.com gives me identical results for both explicit HTTP/1.1 and HTTP/2:

$ TWA_CURLOPTS="--http1.1" ./twa http2.akamai.com
PASS(http2.akamai.com): HTTP redirects to HTTPS using a 301
PASS(http2.akamai.com): max-age is at least 6 months
PASS(http2.akamai.com): Strict-Transport-Security specifies includeSubDomains
MEH(http2.akamai.com): Strict-Transport-Security, but no preload
FAIL(http2.akamai.com): X-Frame-Options missing
FAIL(http2.akamai.com): X-Content-Type-Options missing
FAIL(http2.akamai.com): X-XSS-Protection missing
FAIL(http2.akamai.com): Referrer-Policy missing
FAIL(http2.akamai.com): Content-Security-Policy missing
FAIL(http2.akamai.com): Feature-Policy missing
PASS(http2.akamai.com): Site sends 'Server', but probably only a vendor ID: Apache
PASS(http2.akamai.com): Site doesn't send 'X-Powered-By'
PASS(http2.akamai.com): Site doesn't send 'Via'
PASS(http2.akamai.com): Site doesn't send 'X-AspNet-Version'
PASS(http2.akamai.com): Site doesn't send 'X-AspNetMvc-Version'
PASS(http2.akamai.com): No SCM repository at: http://http2.akamai.com/.git/HEAD
PASS(http2.akamai.com): No SCM repository at: http://http2.akamai.com/.hg/store/00manifest.i
PASS(http2.akamai.com): No SCM repository at: http://http2.akamai.com/.svn/entries

$ TWA_CURLOPTS="--http2" ./twa http2.akamai.com
PASS(http2.akamai.com): HTTP redirects to HTTPS using a 301
PASS(http2.akamai.com): max-age is at least 6 months
PASS(http2.akamai.com): Strict-Transport-Security specifies includeSubDomains
MEH(http2.akamai.com): Strict-Transport-Security, but no preload
FAIL(http2.akamai.com): X-Frame-Options missing
FAIL(http2.akamai.com): X-Content-Type-Options missing
FAIL(http2.akamai.com): X-XSS-Protection missing
FAIL(http2.akamai.com): Referrer-Policy missing
FAIL(http2.akamai.com): Content-Security-Policy missing
FAIL(http2.akamai.com): Feature-Policy missing
PASS(http2.akamai.com): Site sends 'Server', but probably only a vendor ID: Apache
PASS(http2.akamai.com): Site doesn't send 'X-Powered-By'
PASS(http2.akamai.com): Site doesn't send 'Via'
PASS(http2.akamai.com): Site doesn't send 'X-AspNet-Version'
PASS(http2.akamai.com): Site doesn't send 'X-AspNetMvc-Version'
PASS(http2.akamai.com): No SCM repository at: http://http2.akamai.com/.git/HEAD
PASS(http2.akamai.com): No SCM repository at: http://http2.akamai.com/.hg/store/00manifest.i
PASS(http2.akamai.com): No SCM repository at: http://http2.akamai.com/.svn/entries

(You'll need the latest master for TWA_CURLOPTS).

I was able to replicate a false negative: it looks like some servers send all of their headers in lowercase in HTTP/2 mode, so the Location: extraction in stage 1 was failing. I'll fix that in a moment.

Edit: Fixed and tagged as 1.3.1.

Do you have someplace private I can drop the URL? I am looking at this because I am mid-harden, and would rather not present a target to people.

ah - We crossed. I will try that...

No joy. Same behavior.

FWIW, I also ran into some problems with nginx that were my own doing: If you enable HTTP/2 on nginx, make sure to only enable it for your HTTPS ports. I was enabling it on my HTTP redirect ports as well, which was causing it to serve the direct HTTP/2 handshake over HTTP/1.1 with no Upgrade field. That was causing false negatives and unknowns though, not positives, so maybe unrelated...

Re: private sharing: I'm yossarian on Keybase if you have that. If not, my PGP key is here: https://keybase.io/yossarian/pgp_keys.asc?fingerprint=46c39716a8f07e98384e28f785ae00c504833b3c

This is indeed a bug: twa was relying on the non-POSIX IGNORECASE variable in awk, which the macOS (BSD?) awk doesn't respect.