Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Great XSS challenge @ Belluminar 2018

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →
Avatar for Jinmo Jinmo
November 15, 2018

The Great XSS challenge @ Belluminar 2018

Just a simple reversing + web challenge

Avatar for Jinmo

Jinmo

November 15, 2018

Other Decks in Technology

Transcript

  1. Challenge description Add following host entry for SSL. The server

    does, too. 192.168.1.73 0e1.kr Submit your URL to http://0e1.kr:8080 to get flag on https://0e1.kr:8000/flag. h2proxy: HTTP/2.0 <-> HTTP/1.1 proxy running on 8000. I wrote it.
  2. Server architecture • Attacker submit a link --> chrome launches,

    visits the link • Flag is on https://0e1.kr:8000 http://0e1.kr:8080 puppeteer (Latest chrome)
  3. Server architecture (cont.) • Flag is on 0e1.kr:8000/flag (HTTP/2), only

    gives flag to 127.0.0.1 • 0e1.kr:8000 (HTTP/2) <- h2proxy -> localhost:8888 (HTTP/1.1) h2 https://0e1.kr:8000 (flag storage) localhost:8888 (express.js)
  4. Challenge description (cont.) • :8000 (h2proxy) • :8080 (static page

    + bot), :8888 (express.js) • All source code is given except flag in secrets.js • Throw a link to :8080, and get :8000/flag! • (or :8888, which is impossible)
  5. :8888 a.k.a 8000 / /echo/.. • No reflective XSS, but

    /echo/ handler: app.get('/echo/:param', (req, res) => { // X-Frame-Options, No XSS auditor res.header('x-echo', req.params.param); res.end(JSON.stringify({"echo": req.params.param})); }) (Obviously no XSS here)
  6. h2proxy bug / off-by-one on HPACK encoder • HTTP/1.1 ->

    HTTP/2 side max_number = (1 << prefix_bits) must be max_number = (1 << prefix_bits) - 1
  7. Discovery • I made this bug unintentionally, but the exploitation

    was fun • Make server to give a large header, then…
  8. Bug • If a header(e.g. X-echo)’s length is 0x80, it

    must be 0x7F 0x01 • But the server encodes 0x80 • X-echo’s length becomes 0 with Huffman encoding (0x80)
  9. Bug (cont.) • You can insert arbitrary header after X-echo

    • It’s achievable by using ASCII codes within 0x20 <= c <= 0x7F
  10. Exploitation • Header encoding • 0x80: Known key & value

    – (0x80 + index) (e.g. method: GET) • 0x40: Known key – (0x40 + index | (length) | value) • 0x00: Unknown key & value – ((length) | key | (length) | value)
  11. Exploitation • “Known headers” • (RFC 7541: Header Compression for

    HTTP/2) • e.g. Let’s use Content-Type header! • 0x40 + 0x1F = 0x5F
  12. !!!

  13. Remaining steps • Upload a HTML to your server that

    sets name • it’s passed to eval(name) • Get /flag and send to your server by using XHR
  14. Summary • There’s vulnerability in h2proxy, which is just a

    HPACK • Use Content-Type to make echo-backed content a HTML document • Get /flag! h2 https://0e1.kr:8000 (flag storage) localhost:8888 (express.js)
  15. Q&A