Created
January 2, 2014 16:13
-
-
Save sstelfox/8221594 to your computer and use it in GitHub Desktop.
Copy of a localhost enumeration using WebRTC. I can't take credit for writing this though I don't know where I originally got this from.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700"> | |
<style> | |
body { | |
font-family: 'Open Sans', Helvetica, Arial, FreeSans; | |
font-size: 12pt; | |
color: #666; | |
margin-top: 40px; | |
text-align: center; | |
} | |
#container { | |
width: auto; | |
display: inline-block; | |
max-width: 700px; | |
margin: 0 auto; | |
text-align: left; | |
} | |
</style> | |
<script> | |
function TaskController(numConcurrent, onDone) { | |
this.numConcurrent = numConcurrent; | |
this.onDone = onDone || function() {}; | |
this.pending = 0; | |
this.queued = []; | |
this.checkTimer = -1; | |
} | |
TaskController.prototype.deferCheck = function() { | |
if (this.checkTimer != -1) return; | |
this.checkTimer = setTimeout((function() { | |
this.checkTimer = -1; | |
this.check(); | |
}).bind(this), 0); | |
}; | |
TaskController.prototype.check = function() { | |
if (this.pending < 1 && this.queued.length == 0) return this.onDone(); | |
while (this.pending < this.numConcurrent && this.queued.length > 0) { | |
try { | |
this.pending += 1; | |
setTimeout((function(task) { | |
task((function() { | |
this.pending -= 1; | |
this.deferCheck(); | |
}).bind(this)); | |
}).bind(this, this.queued.shift()), 0); | |
} | |
catch (e) { | |
this.pending -= 1; | |
this.deferCheck(); | |
} | |
} | |
}; | |
TaskController.prototype.queue = function(task) { | |
this.queued.push(task); | |
this.deferCheck(); | |
}; | |
function probeIp(ip, timeout, cb) { | |
var start = Date.now(); | |
var done = false; | |
var img = document.createElement('img'); | |
var clean = function() { | |
if (!img) return; | |
document.body.removeChild(img); | |
img = null; | |
}; | |
var onResult = function(success) { | |
if (done) return; | |
done = true; | |
clean(); | |
cb(ip, Date.now() - start < timeout); | |
}; | |
document.body.appendChild(img); | |
img.style.display = 'none'; | |
img.onload = function() { onResult(true); }; | |
img.onerror = function() { onResult(false); }; | |
img.src = 'https://' + ip + ':3389/I_DO_NOT_EXIST?' + Math.random(); | |
setTimeout(function() { if (img) img.src = ''; }, timeout + 500); | |
} | |
function probeNet(net, onHostFound, onDone) { | |
net = net.replace(/(\d+\.\d+\.\d+)\.\d+/, '$1.'); | |
var timeout = 5000; | |
var done = false; | |
var found = []; | |
var q = new TaskController(5, onDone); | |
for (var i = 1; i < 256; ++i) { | |
q.queue((function(i, cb) { | |
probeIp(net + i, timeout, function(ip, success) { | |
if (success) onHostFound(ip); | |
cb(); | |
}); | |
}).bind(this, i)); | |
} | |
} | |
function enumLocalIPs(cb) { | |
var RTCPeerConnection = window.webkitRTCPeerConnection || window.mozRTCPeerConnection; | |
if (!RTCPeerConnection) return false; | |
var addrs = Object.create(null); | |
addrs['0.0.0.0'] = false; | |
function addAddress(newAddr) { | |
if (newAddr in addrs) return; | |
addrs[newAddr] = true; | |
cb(newAddr); | |
} | |
function grepSDP(sdp) { | |
var hosts = []; | |
sdp.split('\r\n').forEach(function (line) { | |
if (~line.indexOf('a=candidate')) { | |
var parts = line.split(' '), | |
addr = parts[4], | |
type = parts[7]; | |
if (type === 'host') addAddress(addr); | |
} else if (~line.indexOf('c=')) { | |
var parts = line.split(' '), | |
addr = parts[2]; | |
addAddress(addr); | |
} | |
}); | |
} | |
var rtc = new RTCPeerConnection({iceServers:[]}); | |
if (window.mozRTCPeerConnection) rtc.createDataChannel('', {reliable:false}); | |
rtc.onicecandidate = function (evt) { | |
if (evt.candidate) grepSDP(evt.candidate.candidate); | |
}; | |
setTimeout(function() { | |
rtc.createOffer(function (offerDesc) { | |
grepSDP(offerDesc.sdp); | |
rtc.setLocalDescription(offerDesc); | |
}, function (e) {}); | |
}, 500); | |
return true; | |
} | |
function go() { | |
var q = new TaskController(1); | |
enumLocalIPs(function(localIp) { | |
document.getElementById('localips').innerHTML += localIp + '<br>'; | |
q.queue(function(cb) { | |
probeNet(localIp, | |
function(ip) { | |
document.getElementById('results').innerHTML += ip + '<br>'; | |
}, | |
cb); | |
}); | |
}) || (document.getElementById('localips').innerHTML = 'WebRTC seems not to be supported'); | |
} | |
</script> | |
</head> | |
<body onload="go()"> | |
<div id="container"> | |
<p>The script on this page will attempt to find your local ip addresses, using HTML5 WebRTC, and then use that info to probe for other live hosts on your lan(s).</p> | |
<p>As provided it should work with Chrome and Firefox on Windows and OS X. Chromium on Linux does not work, Firefox reportedly does.</p> | |
<p>See this post [<a href="https://2x.io/read/security-by-obscurity">https://2x.io/read/security-by-obscurity</a>] for a discussion on potential security and privacy consequences. Clues: Fingerprinting, Router / Printer exploitation.</p> | |
<p>Note that reloading the page tends to cause a lot of false positives.</p> | |
<hr> | |
<p>Your local ips appear to be:</p> | |
<div id="localips"></div> | |
<br/> | |
<p>Other boxes on your LAN possibly include (this will take some time ..):</p> | |
<div id="results"></div> | |
</container> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment