Skip to content

Instantly share code, notes, and snippets.

@nv1t
Created November 14, 2019 22:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nv1t/5b1066523d53eea5ccc30f037b8c312a to your computer and use it in GitHub Desktop.
Save nv1t/5b1066523d53eea5ccc30f037b8c312a to your computer and use it in GitHub Desktop.
enumerating local lan IP HTML5 WebRTC and enumerating potentially live hosts
<html>
<head>
<style>
body {
font-family: 'Open Sans', Helvetica, Arial;
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 + ':' + ~~(1024+1024*Math.random()) + '/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:[]});
rtc.createDataChannel('', {reliable:false});
rtc.onicecandidate = function (evt) {
console.log(evt);
if (evt.candidate) grepSDP('a='+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://hacking.ventures/local-ip-discovery-with-html5-webrtc-security-and-privacy-risk/">https://hacking.ventures/local-ip-discovery-with-html5-webrtc-security-and-privacy-risk/</a>] for a discussion on potential security and privacy consequences. Clues: Fingerprinting, Router / Printer exploitation.</p>
<p>Note that reloading the page with F5 or similar tends to cause a lot of false positives. Reset the url instead.</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