-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTTPS Upgrades Test Page #15
Changes from all commits
a3a2915
fcf54e5
78e45c3
dd5666d
105c5ee
a061324
c30bc84
7142bf3
410b754
57afb29
bc775b8
dbac404
ed2b17c
a48abe6
3834ee1
0516cfd
8c0ed4d
3e744f7
4fa7baa
e170507
5c0452e
298d135
1132ac3
293c32e
aaf55ba
31b8382
2d780c4
8feb2e9
1530a02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,14 +12,15 @@ | |
<link href='./style.css' rel='stylesheet'></link> | ||
</head> | ||
<body> | ||
<p><a href="../../">[Home]</a> ↣ <a href="../">[Privacy Protections Tests]</a></p> | ||
<p><a href="../../">[Home]</a> ↣ <a href="../">[Privacy Protections Tests]</a> ↣ <strong>[Fingerprinting Test Page]</strong></p> | ||
|
||
<p>This page collects various datapoints from your browser that can be used for fingerprinting.</p> | ||
<p>⚠️ Please note that: </p> | ||
<ul> | ||
<li>not all of the properties listed here have to be modified to succesfully prevent fingerprining,</li> | ||
<li>some properties may change randomly, depending on the brower, on every page reload or test run,</li> | ||
<li>some data is duplicated, but it's retrieved using different methods.</li> | ||
<li>depending on the brower some properties may change randomly on every page reload or test run,</li> | ||
<li>some data is duplicated, but it's retrieved using different methods,</li> | ||
<li>this page has to be loaded over https for all tests to work correctly (some APIs are not available over http).</li> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since glitch is supporting both http and https I added a note that fingerprinting page should be loaded over https. |
||
</ul> | ||
|
||
<p><button id='start'>Start the test</button></p> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>iframe HTTPS Upgrade Test</title> | ||
</head> | ||
<body> | ||
<script> | ||
const onMessage = msg => { | ||
if (msg.data.action && msg.data.action === 'url') { | ||
if (window.opener) { | ||
window.opener.postMessage({url: document.location.href, type: msg.data.type}, '*'); | ||
} else if (window.parent) { | ||
window.parent.postMessage({url: document.location.href, type: msg.data.type}, '*'); | ||
} | ||
} | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this page returns current url to either parent url (iframe scenario) or opener (window.open scenario). |
||
|
||
window.addEventListener('message', onMessage); | ||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>HTTPS upgrades test page</title> | ||
|
||
<script src='./main.js' defer></script> | ||
<link href='./style.css' rel='stylesheet'></link> | ||
</head> | ||
<body> | ||
<p><a href="../../">[Home]</a> ↣ <a href="../">[Privacy Protections Tests]</a> ↣ <strong>[HTTPS Upgrades Test Page]</strong></p> | ||
|
||
<p>This page will test if requests and navigations to http pages get upgraded to https.</p> | ||
<p>To test your https upgrading solution please add <storng>good.third-party.site</storng> domain to your upgrade list.</p> | ||
<p>⚠️ Those tests will only work if this page is loaded over <strong>http</strong> (otherwise mixed content will be blocked).</p> | ||
|
||
<p><button id='start'>Start test</button></p> | ||
|
||
<details id='tests' hidden> | ||
<summary id='tests-summary'></summary> | ||
<ul id='tests-details'> | ||
</ul> | ||
</details> | ||
|
||
<p><button id='download' disabled>Download the result</button></p> | ||
|
||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
const startButton = document.querySelector('#start'); | ||
const downloadButton = document.querySelector('#download'); | ||
|
||
const testsDiv = document.querySelector('#tests'); | ||
const testsSummaryDiv = document.querySelector('#tests-summary'); | ||
const testsDetailsDiv = document.querySelector('#tests-details'); | ||
|
||
const TEST_DOMAIN = 'good.third-party.site'; | ||
|
||
const tests = [ | ||
{ | ||
id: 'upgrade-navigation', | ||
run: () => { | ||
let resolve, reject; | ||
const promise = new Promise((res, rej) => {resolve = res; reject = rej}); | ||
const otherWindow = window.open(`http://${TEST_DOMAIN}/privacy-protections/https-upgrades/frame.html`); | ||
|
||
const interval = setInterval(() => { | ||
otherWindow.postMessage({action: 'url', type: 'navigation'}, `http://${TEST_DOMAIN}/`); | ||
otherWindow.postMessage({action: 'url', type: 'navigation'}, `https://${TEST_DOMAIN}/`); | ||
}, 500); | ||
|
||
function onMessage(m) { | ||
if (m.data && m.data.type === 'navigation') { | ||
clearInterval(interval); | ||
otherWindow.close(); | ||
window.removeEventListener('message', onMessage); | ||
resolve(m.data.url); | ||
} | ||
} | ||
|
||
window.addEventListener('message', onMessage); | ||
|
||
return promise; | ||
} | ||
}, | ||
{ | ||
id: 'upgrade-iframe', | ||
run: () => { | ||
let resolve, reject; | ||
const promise = new Promise((res, rej) => {resolve = res; reject = rej}); | ||
|
||
const iframe = document.createElement('iframe'); | ||
|
||
iframe.addEventListener('load', i => { | ||
iframe.contentWindow.postMessage({action: 'url', type: 'frame'}, `http://${TEST_DOMAIN}/`); | ||
iframe.contentWindow.postMessage({action: 'url', type: 'frame'}, `https://${TEST_DOMAIN}/`); | ||
}); | ||
|
||
iframe.src = `http://${TEST_DOMAIN}/privacy-protections/https-upgrades/frame.html`; | ||
|
||
document.body.appendChild(iframe); | ||
|
||
function onMessage(m) { | ||
if (m.data && m.data.type === 'frame') { | ||
window.removeEventListener('message', onMessage); | ||
document.body.removeChild(iframe); | ||
resolve(m.data.url); | ||
} | ||
} | ||
|
||
window.addEventListener('message', onMessage); | ||
|
||
return promise; | ||
} | ||
}, | ||
{ | ||
id: 'upgrade-subrequest', | ||
run: () => { | ||
return fetch(`http://${TEST_DOMAIN}/reflect-headers`) | ||
.then(r => r.json()) | ||
.then(data => data.url); | ||
} | ||
}, | ||
{ | ||
id: 'upgrade-websocket', | ||
run: () => { | ||
let resolve, reject; | ||
const promise = new Promise((res, rej) => {resolve = res; reject = rej}); | ||
|
||
const websocketUrl = `ws://${TEST_DOMAIN}/block-me/web-socket`; | ||
const socket = new WebSocket(websocketUrl); | ||
socket.addEventListener('message', () => { | ||
resolve(socket.url); | ||
}); | ||
|
||
return promise; | ||
} | ||
} | ||
]; | ||
|
||
// object that contains results of all tests | ||
const results = { | ||
page: 'https-upgrades', | ||
date: null, | ||
results: [] | ||
}; | ||
|
||
function resultToHTML(data) { | ||
if (Array.isArray(data)) { | ||
return `<ul>${data.map(r => `<li>${r.test} - ${r.result}</li>`).join('')}</ul>`; | ||
} else if (data) { | ||
return JSON.stringify(data, null, 2); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* Test runner | ||
*/ | ||
function runTests() { | ||
startButton.setAttribute('disabled', 'disabled'); | ||
downloadButton.removeAttribute('disabled'); | ||
testsDiv.removeAttribute('hidden'); | ||
|
||
results.results.length = 0; | ||
results.date = (new Date()).toUTCString(); | ||
let all = 0; | ||
let failed = 0; | ||
|
||
testsDetailsDiv.innerHTML = ''; | ||
|
||
function updateSummary() { | ||
testsSummaryDiv.innerText = `Performed ${all} tests${failed > 0 ? ` (${failed} failed)` : ''}. Click for details.`; | ||
} | ||
|
||
for (const test of tests) { | ||
const resultObj = { | ||
id: test.id, | ||
value: null | ||
}; | ||
results.results.push(resultObj); | ||
|
||
const li = document.createElement('li'); | ||
li.id = `test-${test.id.replace(' ', '-')}`; | ||
li.innerHTML = `${test.id} - <span class='value'>…</span>`; | ||
const valueSpan = li.querySelector('.value'); | ||
|
||
testsDetailsDiv.appendChild(li); | ||
|
||
try { | ||
const result = test.run(); | ||
|
||
if (result instanceof Promise) { | ||
result | ||
.then(data => { | ||
valueSpan.innerHTML = resultToHTML(data); | ||
resultObj.value = data || null; | ||
}) | ||
.catch(e => { | ||
failed++; | ||
valueSpan.innerHTML = `❌ error thrown ("${e.message ? e.message : e}")`; | ||
updateSummary(); | ||
}); | ||
} else { | ||
valueSpan.innerHTML = resultToHTML(data);; | ||
resultObj.value = result || null; | ||
} | ||
} catch(e) { | ||
failed++; | ||
valueSpan.innerHTML = `❌ error thrown ("${e.message ? e.message : e}")`; | ||
} | ||
|
||
all++; | ||
} | ||
|
||
updateSummary(); | ||
|
||
startButton.removeAttribute('disabled'); | ||
} | ||
|
||
function downloadTheResults() { | ||
const data = JSON.stringify(results, null, 2); | ||
const a = document.createElement('a'); | ||
const url = window.URL.createObjectURL(new Blob([data], {type: 'application/json'})); | ||
a.href = url; | ||
a.download = 'fingerprinting-results.json'; | ||
|
||
document.body.appendChild(a); | ||
a.click(); | ||
|
||
window.URL.revokeObjectURL(url); | ||
a.remove(); | ||
} | ||
|
||
downloadButton.addEventListener('click', () => downloadTheResults()); | ||
|
||
// run tests if button was clicked or… | ||
startButton.addEventListener('click', () => runTests()); | ||
|
||
// if url query is '?run' | ||
if (document.location.search === '?run') { | ||
runTests(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
* { | ||
box-sizing: border-box; | ||
} | ||
|
||
.value { | ||
color: gray; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,16 @@ | |
<title>Privacy Protections Tests</title> | ||
</head> | ||
<body> | ||
<p><a href="../">[Home]</a></p> | ||
<p><a href="../">[Home]</a> ↣ <strong>[Privacy Protections Tests]</strong></p> | ||
|
||
<h1>Privacy Protections Tests</h1> | ||
|
||
<ul> | ||
<li><a href='./request-blocking/'>Request blocking</a></li> | ||
<li><a href='./fingerprinting/'>Fingerprinting</a></li> | ||
<li><a href='./storage-blocking/'>Storage blocking</a></li> | ||
<li><a href='./referrer-trimming/'>Referrer trimming</a></li> | ||
<li><a href='https://privacy-test-pages.glitch.me/privacy-protections/request-blocking/'>Request blocking</a></li> | ||
<li><a href='https://privacy-test-pages.glitch.me/privacy-protections/fingerprinting/'>Fingerprinting</a></li> | ||
<li><a href='https://privacy-test-pages.glitch.me/privacy-protections/storage-blocking/'>Storage blocking</a></li> | ||
<li><a href='https://privacy-test-pages.glitch.me/privacy-protections/referrer-trimming/'>Referrer trimming</a></li> | ||
<li><a href='http://privacy-test-pages.glitch.me/privacy-protections/https-upgrades/'>HTTPS upgrades</a></li> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto - hardcoded urls |
||
</ul> | ||
|
||
</body> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ function generateNavigationTest(url) { | |
|
||
if (localStorage[key]) {// test already finished before | ||
return JSON.parse(localStorage[key]); | ||
} else if(currentURL.searchParams.get('js')) {// test finished now | ||
} else if(currentURL.searchParams.get('js') !== null) {// test finished now | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated fix for referrer trimming - we have to test for null specifically because Brave, in certain scenarios trims referrer to an empty string. |
||
const result = [ | ||
{ | ||
test: 'js', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,15 @@ const express = require('express'); | |
const ws = require('ws'); | ||
const app = express(); | ||
const port = process.env.PORT || 3000; | ||
const url = require('url'); | ||
|
||
function fullUrl(req) { | ||
return url.format({ | ||
protocol: req.protocol, | ||
host: req.get('host'), | ||
pathname: req.originalUrl | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this returns full url that was requested (we need that to see if the protocol was http or https) |
||
} | ||
|
||
// start server | ||
const listener = app.listen(port, () => { | ||
|
@@ -66,13 +75,13 @@ app.post('/block-me/csp', (req, res) => { | |
return res.sendStatus(200); | ||
}); | ||
|
||
// reflects request headers back | ||
// reflects request headers and request url back | ||
app.get('/reflect-headers', (req, res) => { | ||
res.set('Access-Control-Allow-Origin', req.headers.origin || '*'); | ||
res.set('Access-Control-Allow-Credentials', 'true'); | ||
res.set('Timing-Allow-Origin', '*'); | ||
|
||
return res.json({headers: req.headers}); | ||
return res.json({url: fullUrl(req), headers: req.headers}); | ||
}); | ||
|
||
// sets a cookie with provided value | ||
|
@@ -108,9 +117,9 @@ app.get('/come-back', (req, res) => { | |
<body> | ||
<script> | ||
const jsReferrer = document.referrer; | ||
document.body.innerHTML += '<p>header: <strong>${req.headers.referer}</strong></p><p>js: <strong>' + jsReferrer + '</strong></p>'; | ||
document.body.innerHTML += '<p>header: <strong>${req.headers.referer || ''}</strong></p><p>js: <strong>' + jsReferrer + '</strong></p>'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated referrer clean up - for Brave referrer is sometimes undefined in which scenarios we want to return |
||
setTimeout(() => { | ||
location.href = 'https://privacy-test-pages.glitch.me/privacy-protections/referrer-trimming/?run&header=${req.headers.referer}&js=' + jsReferrer; | ||
location.href = 'https://privacy-test-pages.glitch.me/privacy-protections/referrer-trimming/?run&header=${req.headers.referer || ''}&js=' + jsReferrer; | ||
}, 1000); | ||
</script> | ||
</body> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of those pages don't really work on github pages, which might be confusing, so I hardcoded full glitch urls.