-
Notifications
You must be signed in to change notification settings - Fork 664
/
index.html
269 lines (226 loc) · 12.6 KB
/
index.html
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
<html>
<head>
<link rel="stylesheet" href="css/master.css" type="text/css">
<script type="text/javascript" src="js/swfobject-2.2.min.js"></script>
<script type="text/javascript" src="http://www.java.com/js/dtjava.js"></script>
<script type="text/javascript" src="js/evercookie.js"></script>
<title>evercookie - virtually irrevocable persistent cookies</title>
</head>
<body>
<div id="pagebox1" align="center">
<div id="pagebox2">
<table width="728" border="0" align="center" cellpadding="0" cellspacing="0" class="topnavtable"><tr><td></td></tr></table>
<div id="pagecontent" align="left" style="margin-top:5px">
<a href="http://samy.pl">samy's home page</a> || <a href="http://twitter.com/samykamkar">follow my twitter</a> || <a href="http://namb.la">blog</a> || <a href="mailto:code@samy.pl">email me</a> || samy kamkar<hr>
<h1>evercookie <small>-- never forget.</small></h1>
10/10/2010: Reported on by the <a target=_new href="http://www.nytimes.com/2010/10/11/business/media/11privacy.html?hp">New York Times</a>
<PRE>
</PRE>
<H2>DESCRIPTION</H2><PRE>
<i>evercookie</i> is a javascript API available that produces
extremely persistent cookies in a browser. Its goal
is to identify a client even after they've removed standard
cookies, Flash cookies (Local Shared Objects or LSOs), and
others.
evercookie accomplishes this by storing the cookie data in
several types of storage mechanisms that are available on
the local browser. Additionally, if evercookie has found the
user has removed any of the types of cookies in question, it
recreates them using each mechanism available.
Specifically, when creating a new cookie, it uses the
following storage mechanisms when available:<b>
- Standard <A href="http://en.wikipedia.org/wiki/HTTP_cookie">HTTP Cookies</a>
- <a href="http://en.wikipedia.org/wiki/Local_Shared_Object">Local Shared Objects</a> (Flash Cookies)
- Silverlight <a href="http://www.silverlight.net/learn/quickstarts/isolatedstorage/">Isolated Storage</a>
- Storing cookies in RGB values of auto-generated, force-cached
PNGs using HTML5 Canvas tag to read pixels (cookies) back out
- Storing cookies in and reading out <a href="http://samy.pl/csshack/">Web History</a>
- Storing cookies in HTTP <a href="http://en.wikipedia.org/wiki/HTTP_ETag">ETags</a>
- Storing cookies in <a href="http://en.wikipedia.org/wiki/Web_cache">Web cache</a>
- <a href="http://en.wikipedia.org/wiki/HTTP_cookie#window.name">window.name</a> caching
- Internet Explorer <a href="http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx">userData</a> storage
- HTML5 <a href="http://dev.w3.org/html5/webstorage/#the-sessionstorage-attribute">Session Storage</a>
- HTML5 <a href="http://dev.w3.org/html5/webstorage/#dom-localstorage">Local Storage</a>
- HTML5 <a href="https://developer.mozilla.org/en/dom/storage#globalStorage">Global Storage</a>
- HTML5 <a href="http://dev.w3.org/html5/webdatabase/">Database Storage</a> via SQLite
TODO:</b> adding support for:
- Caching in <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Authentication</a>
- Using Java to produce a unique key based off of NIC info
Got a crazy idea to improve this? <a href="mailto:code@samy.pl">Email me!</a>
</PRE>
<H2>EXAMPLE</H2><PRE>
<script>
var val = '' + Math.floor(Math.random()*1000);
var ec = new evercookie({
/* Options */
});
getC(0);
//setTimeout(getC, 500, 1);
function getC(dont)
{
ec.get("uid", function(best, all) {
document.getElementById('idtag').innerHTML = best;
var txt = document.getElementById('cookies');
txt.innerHTML = '';
for (var item in all)
txt.innerHTML += item + ' mechanism: ' + (val == all[item] ? '<b>' + all[item] + '</b>' : all[item]) + '<br>';
if (!dont)
getC(1);
}, dont);
}
</script>
<b>Cookie found:</b> <i>uid</i> = <span id='idtag'>currently not set</span>
Click to create an evercookie. Don't worry, the cookie is a
random number between 1 and 1000, not enough for me to track
you, just enough to test evercookies.
<input type=button value="Click to create an evercookie" onClick="document.getElementById('idtag').innerHTML = '*creating*'; document.getElementById('cookies').innerHTML = ''; ec.set('uid', val); setTimeout(getC, 1000, 1); ">
<div id='cookies'></div>
Now, try deleting this "uid" cookie anywhere possible, then
<input type=button value="Click to rediscover cookies" onClick="document.getElementById('idtag').innerHTML = '*checking*'; document.getElementById('cookies').innerHTML = ''; setTimeout(getC, 300);">
or
<input type=button value="Click to rediscover cookies WITHOUT reactivating deleted cookies" onClick="document.getElementById('idtag').innerHTML = '*checking*'; document.getElementById('cookies').innerHTML = ''; setTimeout(getC, 300, 1);">
</PRE>
<H2><a href="evercookie-0.4.tgz">DOWNLOAD</a></H2><PRE>
<I>evercookie</I> is written in JavaScript and additionally
uses a SWF (Flash) object for the Local Shared Objects and
PHPs for the server-side generation of cached PNGs and ETags.
<B>v0.4 BETA</B>, released 10/13/2010
download source <a href="evercookie-0.4.tgz">here</a>
Or get it from github: <a href="http://github.com/samyk/evercookie">http://github.com/samyk/evercookie</a>
</PRE>
<H2>FAQ</H2><PRE>
<b>What is the point of evercookie?</b>
Evercookie is designed to make persistent data just that, persistent. By
storing the same data in several locations that a client can access, if
any of the data is ever lost (for example, by clearing cookies), the data
can be recovered and then reset and reused.
Simply think of it as cookies that just won't go away.
<b>PRIVACY CONCERN! How do I stop websites from doing this?</b>
Great question. So far, I've found that using <a href="http://www.apple.com/pro/tips/privacy_safari.html">Private Browsing</a>
in <a href="http://www.apple.com/safari/">Safari</a> will stop ALL evercookie methods after a browser restart.
<b>What if the user deletes their cookies?</b>
That's the great thing about evercookie. With all the methods available,
currently thirteen, it only takes one cookie to remain for most, if not all,
of them to be reset again.
For example, if the user deletes their standard HTTP cookies, LSO data,
and all HTML5 storage, the PNG cookie and history cookies will still
exist. Once either of those are discovered, all of the others will
come back (assuming the browser supports them).
<b>Why not use EFF's <a href="https://panopticlick.eff.org/">Panopticlick</a>?</b>
Panopticlick is an awesome idea, however the uniqueness really only
helps in consumer machines and typically not systems running in a
business or corporation. Typically those systems are virtually
identical and provide no difference in information where a home
user's laptop would. Evercookie is meant to be able to store the
same unique data a normal cookie would.
<b>Does this work cross-browser?</b>
If a user gets cookied on one browser and switches to another browser,
as long as they still have the Local Shared Object cookie, the cookie
will reproduce in both browsers.
<b>Does the client have to install anything?</b>
No, the client simply uses the website without even knowing about the
persistent data being set, just as they would use a website with standard
HTTP cookies.
<b>Does the server have to install anything?</b>
The server must at least have access to the JavaScript evercookie file.
Additionally, to use Local Shared Object (Flash Cookies) storage, the
evercookie.swf file must be present, and to use the auto-generated PNG
caching, standard caching and ETag storage mechanisms, PHP must be
installed and evercookie_(png|etag|cache).php must be on the server.
All of these are available in the download.
<b>Is evercookie open source?</b>
Yes, evercookie is open source. The code is in readable format without
any obfuscation. Additionally, the PHP files are open source as is the
FLA (Flash) code used to generate the SWF Flash object. You can compile
the Flash object yourself or use the pre-compiled version (evercookie.swf).
<b>How does the PNG caching work?</b>
When evercookie sets a cookie, it accesses evercookie_png.php with a special
HTTP cookie, different than the one used for standard session data. This
special cookie is read by the PHP file, and if found, generates a PNG file
where all the RGB values are set to the equivalent of the session data to
be stored. Additionally, the PNG is sent back to the client browser with
the request to cache the file for 20 years.
When evercookie retrieves this data, it deletes the special HTTP cookie,
then makes the same request to the same file without any user information.
When the PHP script sees it has no information to generate a PNG with, it
returns a forged HTTP response of "304 Not Modified" which forces the web
browser to access its local cache. The browser then produces the cached
image and then applies it to an HTML5 Canvas tag. Once applied, evercookie
reads each pixel of the Canvas tag, extracting the RGB values, and thus
producing the initial cookie data that was stored.
<b>How does the Web History storage work?</b>
When evercookie sets a cookie, assuming the Web History caching is enabled,
it Base64 encodes the data to be stored. Let's assume this data is "bcde"
in Base64. Evercookie then accesses the following URLs in the background:
google.com/evercookie/cache/b
google.com/evercookie/cache/bc
google.com/evercookie/cache/bcd
google.com/evercookie/cache/bcde
google.com/evercookie/cache/bcde-
These URLs are now stored in history.
When checking for a cookie, evercookie loops through all the possible Base64
characters on google.com/evercookie/cache/, starting with "a" and moving up,
but only for a single character. Once it sees a URL that was accessed, it
attempts to brute force the next letter. This is actually extremely fast
because <b>no requests</b> are made to theserver. The history lookups are simply
locally in JavaScript using the <a href="http://samy.pl/csshack/">CSS History Knocker</a>. Evercookie knows it has
reached the end of the string as soon as it finds a URL that ends in "-".
</PRE>
<H2>USAGE</H2><PRE>
<b><script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="swfobject-2.2.min.js"></script>
<script type="text/javascript" src="evercookie.js"></script>
<script>
var ec = new evercookie({
baseurl: '/test', </b><i>http://localhost/test</i><b>
asseturi: '/assets', </b><i>http://localhost/test/assets</i><b>
phpuri: '/php' </b><i>http://localhost/test/php</i><b>
});</b>
// set a cookie "id" to "12345"
// usage: ec.set(key, value)
<b>ec.set("id", "12345");</b>
// retrieve a cookie called "id" (simply)
<b>ec.get("id", function(value) { alert("Cookie value is " + value) });</b>
// or use a more advanced callback function for getting our cookie
// the cookie value is the first param
// an object containing the different storage methods
// and returned cookie values is the second parameter
<b>function getCookie(best_candidate, all_candidates)
{
alert("The retrieved cookie is: " + best_candidate + "\n" +
"You can see what each storage mechanism returned " +
"by looping through the all_candidates object.");
for (var item in all_candidates)
document.write("Storage mechanism " + item +
" returned: " + all_candidates[item] + "<br>");
}
ec.get("id", getCookie);</b>
// we look for "candidates" based off the number of "cookies" that
// come back matching since it's possible for mismatching cookies.
// the best candidate is most likely the correct one
<b></script></b>
</PRE>
<H2>SEE ALSO</H2><PRE>
<B><a href="http://samy.pl/csshack/">csshack</a>, <a href="http://samy.pl">best website ever</a></B>
</PRE>
<H2>BUGS</H2><PRE>
See <b>CONTACT</b>.
</PRE>
<H2>CONTACT</H2><PRE>
Questions or comments, email me: <B><a href="mailto:code@samy.pl">code@samy.pl</a></B>.
Visit <a href="http://samy.pl">http://samy.pl</a> for more awesome stuff.
</PRE>
<H2>evercookie, by <a href="mailto:code@samy.pl">Samy Kamkar</a>, 09/20/2010</h2>
</div>
</div></div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-6127617-2");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>