很早就有使用浏览器扫描LAN这种操作了。也有许多使用XHR请求、WebSocket或纯HTML来发现和识别LAN设备的工具。但是在这篇文章中,我将介绍一种使用WebRTC ICE服务器的新扫描技术。它速度很快,并且与其他方法不同的是:它绕过了阻止的端口列表。唯一的缺点是:它仅在受害者使用Chrome时有效。
首先给大家看一个概念简介的视频。视频中我正在扫描的是192.168.88.0/24网络。
https://www.youtube.com/watch?v=M6lBVhkzUmM&feature=emb_title
(因为“网络”选项卡可见,所以您看不到任何被记录的请求。)
什么是ICE服务器?
正如我所说,扫描时要用到WebRTC ICE服务器。ICE服务器是WebRTC RTCPeerConnection用于自发现、NAT遍历或中继的STUN或TURN服务器。服务器列表可以传递到RTCPeerConnection的构造函数中。下图是提供给一台Google公共STUN服务器的构造函数示例:
var rtc = new RTCPeerConnection({ iceServers:[{“urls”:”stun:stun.l.google.com:19302”}] });
当上述RTCPeerConnection进入ICE gathering state时,它将尝试连接到提供的服务器。
协议事项
ICE服务器可以绑定到UDP或TCP端口。但是除非另有指示,否则Chrome会仅尝试通过UDP进行通信。下图是Wireshark的屏幕截图,图中显示的是Chrome发送到不存在的TURN服务器的数据包。内容都是UDP。
如果您了解ICE服务器URLs,就可以强制Chrome通过TCP进行访问。但是传递给RTCPeerConnection构造函数的URL必须符合RFC 7064(STUN)或RFC 7065(TURN)。 TURN URI方案如下:
详情见https://tools.ietf.org/html/rfc7065#section-3.1
对于扫描而言,最重要的是可选的“?transport =”字段。通过使用以“?transport = tcp”结尾的TURN URI,我们可以强制Chrome使用基于TCP的ICE。
现在我们掌握了一种可以使用我们选择的任何IP和端口来启动TCP连接的方法。但是我们扫描的所有主机大都不是TURN服务器,那我们该如何确定主机是否还存在呢?
确定主机是否存在
下图是JSFiddle生成的256 TURN URI,用于查找192.168.[0–255].1范围内仍存在的主机地址。
var brute_array = []; for (i = 0; i < 256; i++) { brute_address = "turn:192.168." + i + ".1:445?transport=tcp"; brute_array.push({ urls: brute_address, credential: "lobster", username: "albino" }); } var rtc_brute = new RTCPeerConnection({ iceServers: brute_array, iceCandidatePoolSize: 0 }); rtc_brute.createDataChannel('', { reliable: false }); rtc_brute.onicecandidateerror = function(e) { if (e.url == null) { return; } url_split = e.url.split(":"); host_div = document.createElement('div'); host_div.id = url_split[1]; host_div.innerHTML = url_split[1]; document.getElementById('hosts').appendChild(host_div); } // trigger the gathering of ICE candidates rtc_brute.createOffer(function(offerDesc) { rtc_brute.setLocalDescription(offerDesc); }, function(e) { console.log("Create offer failed callback.");
<html> <body> <div id="hosts"> </div> </body> </html>
192.168.10.1 192.168.13.1 192.168.15.1 192.168.16.1 192.168.32.1 192.168.33.1 192.168.35.1 192.168.50.1 192.168.65.1 192.168.69.1 192.168.132.1 192.168.67.1 192.168.68.1 192.168.133.1 192.168.134.1 192.168.135.1 192.168.136.1 192.168.137.1 192.168.138.1 192.168.139.1 192.168.140.1 192.168.141.1 192.168.142.1 192.168.143.1 192.168.144.1 192.168.145.1 192.168.146.1 192.168.147.1 192.168.148.1 192.168.149.1 192.168.150.1 192.168.151.1 192.168.152.1 192.168.153.1 192.168.154.1 192.168.155.1 192.168.156.1 192.168.157.1 192.168.158.1 192.168.159.1 192.168.160.1 192.168.161.1 192.168.162.1 192.168.163.1 192.168.164.1 192.168.165.1 192.168.166.1 192.168.167.1 192.168.168.1 192.168.169.1 192.168.170.1 192.168.171.1 192.168.172.1 192.168.173.1 192.168.174.1 192.168.175.1 192.168.176.1 192.168.177.1 192.168.178.1 192.168.179.1 192.168.180.1 192.168.181.1 192.168.182.1 192.168.73.1 192.168.30.1 192.168.76.1 192.168.72.1 192.168.74.1 192.168.75.1 192.168.96.1 192.168.97.1 192.168.99.1 192.168.98.1 192.168.94.1 192.168.70.1 192.168.183.1 192.168.201.1 192.168.199.1 192.168.200.1 192.168.195.1 192.168.196.1 192.168.202.1 192.168.203.1 192.168.204.1 192.168.205.1 192.168.206.1 192.168.207.1 192.168.208.1 192.168.209.1 192.168.210.1 192.168.211.1 192.168.212.1 192.168.213.1 192.168.214.1 192.168.215.1 192.168.216.1 192.168.217.1 192.168.218.1 192.168.219.1 192.168.220.1 192.168.221.1 192.168.222.1 192.168.223.1 192.168.224.1 192.168.225.1 192.168.226.1 192.168.227.1 192.168.228.1 192.168.229.1 192.168.230.1 192.168.231.1 192.168.232.1 192.168.233.1 192.168.234.1 192.168.235.1 192.168.236.1 192.168.237.1 192.168.238.1 192.168.239.1 192.168.240.1 192.168.241.1 192.168.242.1 192.168.243.1 192.168.244.1 192.168.245.1 192.168.246.1 192.168.247.1 192.168.248.1 192.168.249.1 192.168.250.1 192.168.251.1 192.168.252.1 192.168.253.1 192.168.254.1 192.168.255.1 192.168.0.1 192.168.1.1 192.168.2.1 192.168.3.1 192.168.4.1 192.168.5.1 192.168.6.1 192.168.7.1 192.168.8.1 192.168.9.1 192.168.11.1 192.168.12.1 192.168.14.1 192.168.17.1 192.168.18.1 192.168.19.1 192.168.20.1 192.168.21.1 192.168.22.1 192.168.23.1 192.168.24.1 192.168.25.1 192.168.26.1 192.168.27.1 192.168.28.1 192.168.29.1 192.168.31.1 192.168.34.1 192.168.36.1 192.168.37.1 192.168.38.1 192.168.39.1 192.168.40.1 192.168.41.1 192.168.42.1 192.168.43.1 192.168.44.1 192.168.45.1 192.168.46.1 192.168.47.1 192.168.48.1 192.168.49.1 192.168.51.1 192.168.52.1 192.168.53.1 192.168.54.1 192.168.55.1 192.168.56.1 192.168.57.1 192.168.58.1 192.168.59.1 192.168.60.1 192.168.61.1 192.168.62.1 192.168.63.1 192.168.64.1 192.168.66.1 192.168.71.1 192.168.77.1 192.168.78.1 192.168.79.1 192.168.80.1 192.168.81.1 192.168.82.1 192.168.83.1 192.168.84.1 192.168.85.1 192.168.86.1 192.168.87.1 192.168.88.1 192.168.89.1 192.168.90.1 192.168.91.1 192.168.92.1 192.168.93.1 192.168.95.1 192.168.100.1 192.168.101.1 192.168.102.1 192.168.103.1 192.168.104.1 192.168.105.1 192.168.106.1 192.168.107.1 192.168.108.1 192.168.109.1 192.168.110.1 192.168.111.1 192.168.112.1 192.168.113.1 192.168.114.1 192.168.115.1 192.168.116.1 192.168.117.1 192.168.118.1 192.168.119.1 192.168.120.1 192.168.121.1 192.168.122.1 192.168.123.1 192.168.124.1 192.168.125.1 192.168.126.1 192.168.127.1 192.168.128.1 192.168.129.1 192.168.130.1 192.168.131.1 192.168.184.1 192.168.185.1 192.168.186.1 192.168.187.1 192.168.188.1 192.168.189.1 192.168.190.1 192.168.191.1 192.168.192.1 192.168.193.1 192.168.194.1 192.168.197.1 192.168.198.1
若icecandidateerror事件生成,则确定该主机地址“存在(active)”。如果主机以某种形式拒绝连接,Chrome将生成错误事件。理想情况是:在Chrome发送初始消息后,主机通过RST或快速地拒绝了连接。尽管服务器保持连接打开,但错误事件仍需要30秒钟才能生成。
这就是为什么JSFiddle要使用端口445进行扫描。我曾遇到过SMB完成了TCP握手,然后在Chrome的非SMB流量之后关闭了连接。实际上445也是一种不切实际的选择,因为它更有可能会安装Windows盒子。
如果Chrome没有响应,则不会生成该事件。这可能是由于防火墙忽略了不常见的入站请求。或者实际上没有可用的主机。
我遇到过的唯一一个极端情况是:发送ICMP响应作为回复。这会导致Chrome生成icecandidateerror,它与处于active状态的主机没有区别。
文章作者:Jacob Baines