goo.gl/pDcpSy
Последние взломы
interface PlatformAPI {
sensitive: never;
getKeys (): Key[];
sign (Data, Key): Signature;
verify (Data, Signature): Key;
}
4. Браузерный плагин
Disclaimer: аудит безопасности не завершен. Не пытайтесь повторить в домашних условиях реальных проектах
<iframe
id="frame"
src="https://secure.app/sign?data=0xDEADBEEF">
<!doctype html>
<script src="/handler.js"
integrity="sha384-..."/>
<script>
window.parent.postMessage(
await handle(location)
)
</script>
</iframe>
async injectIframe(frameUrl, query) => {
const defer = new Deferred()
const frame = createIframe(frameUrl, query)
const mo = new MutationObserver(
mutations => deferred.reject()
)
mo.observe(iframe, {
attributes: true
})
document.body.appendChild(frame)
return defer
}
const key = createKey()
const blobFrameUrl = URL.createObjectURL(new Blob([
`<!doctype html>
<iframe
id="iframe"
src="${iframeUrl}"
sandbox="allow-same-origin allow-scripts">
<script>
iframe.contentWindow.onmessage = ({data}) =>
window.parent.postMessage(
encrypt(data, ${key})
)`
], {
type: 'text/html'
}))
async verifyUrl (frameUrl, integrity) => {
const {ok, headers} = await fetch(frameUrl, {
integrity,
redirect: 'manual',
cache: 'force-cache',
mode: 'cors'
})
assert(
headers.get('Cache-Control') === 'max-age=84600',
headers.has('pragma') === false
)
await injectIframe(frameUrl, query)
}
//iframe.html
<script>
await navigator.storage.persist()
await navigator.serviceWorker.register('sw.js')
//sw.js
self.addEventListener('fetch', event =>
event.respondWith(new Response(`
<!doctype html>
<script src="/handler.js" integrity="sha384-..."/>
<script>
window.parent.postMessage(
await handle(location))
</script>`)))
//iframe.html
<script>
await navigator.storage.persist()
await navigator.serviceWorker.register('sw.js')
//sw.js
self.addEventListener('fetch', event =>
event.respondWith(new Response(`
<script src="/handler.js" integrity="sha384-..."/>
<script>
window.parent.postMessage(
await handle(location))
</script>`)))
handlers.doSomethingImportant = async (...args) => {
await notification('confirm?', {
requireInteraction: true,
data: args,
actions: [
{action: 'res', title: 'yes'},
{action: 'rej', title: 'no'}
]
})
...
}
// sw.js
self.addEventListener(
'notificationclick',
({notification, action}) => {
event.notification.close()
actions.get(notification.data).call(action)
},
false
)
self.addEventListener('fetch', async event =>
event.respondWith(new Response(`
<!doctype html>
<script>
window.parent.postMessage(
${
JSON.stringify(
await handle(event.request.url)
)
})</script>`)))
only allow-same-origin should be required for SW interception within a sandboxed iframe
By the time the request gets to fetch, it doesn't know it came from a sandboxed iframe
self.addEventListener('fetch', async event =>
event.respondWith(Response.redirect(
'data:text/html,' +
encodeURIComponent(`
<!doctype html>
<script>
parent.postMessage(${
JSON.stringify(
await handle(event.request.url)
)
})`))))
как добавлять функционал/обновлять библиотеку по необходимости?
защита от DoS?
защита от публичного доступа?
Всеволод Родионов, JS-шалун
@jabher