1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
(function () {
let destination = 'https://the.beach/';
let fb_wrap = 'https://facebook.com/l.php?u=' + destination;
let fb_xss = 'https://facebook.com/l.php?u=javascript://bad.site/%250Aalert(1)';
let g_wrap = 'https://www.google.com/url?q=' + destination;
let g_ping = '/url?url=' + destination;
function makeLink(href) {
let element = document.createElement('a');
element.href = href;
element.rel = '';
return element;
}
function stub(elts, selector) {
document.querySelectorAllBefore = document.querySelectorAll;
window.setIntervalBefore = window.setInterval;
chrome.runtime.sendMessageBefore = chrome.runtime.sendMessage;
// Stub querySelectorAll so that any selector that includes `selector` will
// match all the elements in `elts`.
document.querySelectorAll = function (query) {
if (query.includes(selector)) {
return elts;
} else {
return document.querySelectorAllBefore(query);
}
};
// Stub runtime.sendMessage so that it returns `true` in response to the
// `checkEnabled` query.
chrome.runtime.sendMessage = function (message, callback) {
if (message.type == "checkEnabled") {
callback(true);
} else {
chrome.runtime.sendMessageBefore(message, callback);
}
};
window.setInterval = function () {};
}
function unstub() {
document.querySelectorAll = document.querySelectorAllBefore;
window.setInterval = window.setIntervalBefore;
chrome.runtime.sendMessage = chrome.runtime.sendMessageBefore;
}
QUnit.module('First parties');
QUnit.test('facebook script unwraps valid links', (assert) => {
const NUM_CHECKS = 4,
done = assert.async();
assert.expect(NUM_CHECKS);
let fixture = document.getElementById('qunit-fixture');
let good_link = makeLink(fb_wrap);
let bad_link = makeLink(fb_xss);
// create first-party utility script
let util_script = document.createElement('script');
util_script.src = '../js/firstparties/lib/utils.js';
// create the content script
let fb_script = document.createElement('script');
fb_script.src = '../js/firstparties/facebook.js';
fb_script.onload = function() {
assert.equal(good_link.href, destination, 'unwrapped good link');
assert.ok(good_link.rel.includes('noreferrer'),
'added noreferrer to good link');
assert.equal(bad_link.href, fb_xss, 'did not unwrap the XSS link');
assert.notOk(bad_link.rel.includes('noreferrer'),
'did not change rel of XSS link');
unstub();
done();
};
// after the utility script has finished loading, add the content script
util_script.onload = function() {
fixture.append(fb_script);
};
stub([good_link, bad_link], '/l.php?');
fixture.appendChild(good_link);
fixture.appendChild(bad_link);
fixture.appendChild(util_script);
});
QUnit.test('google shim link unwrapping', (assert) => {
const NUM_CHECKS = 2,
done = assert.async();
assert.expect(NUM_CHECKS);
let fixture = document.getElementById('qunit-fixture');
let shim_link = makeLink(g_wrap);
// create first-party utility script
let util_script = document.createElement('script');
util_script.src = '../js/firstparties/lib/utils.js';
// create the content script
let g_script = document.createElement('script');
g_script.src = '../js/firstparties/google-static.js';
g_script.onload = function() {
assert.equal(shim_link.href, destination, 'unwrapped shim link');
assert.ok(shim_link.rel.includes('noreferrer'),
'added noreferrer to shim link');
unstub();
done();
};
// after the utility script has finished loading, add the content script
util_script.onload = function() {
fixture.append(g_script);
};
stub([shim_link], '/url?');
fixture.appendChild(shim_link);
fixture.appendChild(util_script);
});
QUnit.test('google search de-instrumentation', (assert) => {
const NUM_CHECKS = 3,
done = assert.async();
assert.expect(NUM_CHECKS);
let fixture = document.getElementById('qunit-fixture');
let ff_link = makeLink(destination);
ff_link.onmousedown = 'return rwt(this, foobar);';
let chrome_link = makeLink(destination);
chrome_link.ping = g_ping;
// create first-party utility script
let util_script = document.createElement('script');
util_script.src = '../js/firstparties/lib/utils.js';
// create the content script
let g_script = document.createElement('script');
g_script.src = '../js/firstparties/google-search.js';
g_script.onload = function() {
assert.notOk(ff_link.onmousedown, 'removed mouseDown event from ff link');
assert.ok(ff_link.rel.includes('noreferrer'), 'added noreferrer to link');
assert.notOk(chrome_link.ping, 'removed ping attr from chrome link');
unstub();
done();
};
// after the utility script has finished loading, add the content script
util_script.onload = function() {
fixture.append(g_script);
};
stub([ff_link, chrome_link], 'onmousedown^=');
fixture.appendChild(ff_link);
fixture.appendChild(chrome_link);
fixture.appendChild(util_script);
});
}());
|