我试图在我的localhost上使用JS从浏览器运行端口扫描。 我已经尝试了各种方法,包括超时检查,建议做很多帖子。
我知道有一种方法可以使用WebRTC扫描主机上的特定端口,但找不到任何相关文档。
有人可以帮忙吗?
感谢。
答案 0 :(得分:2)
没有这样的方法。 WebRTC使用STUN进行同意,以避免允许您构建端口扫描程序。见the security considerations
答案 1 :(得分:0)
有几种方法可以完成基于浏览器的端口扫描。但是通常,它是某种形式的定时攻击,它使浏览器加载一些不存在的资源并测量响应。这里有些例子。一个使用img标签,另一个使用webrtc。
在这里,我们将使用伪造的img标签方法:
/* The scanner needs these global variables for an ugly hack. */
var last_scanobj_index = 0;
var scanobjs = {};
function PortScanner(ip, port) {
this.ip = ip;
this.port = port;
this.on_open_or_closed = null;
this.on_stealthed = null;
this.start_time = null;
this.timed_out = null;
this.total_time = null;
this.run = function () {
/* Check that the client gave us all the callbacks we need. */
if (this.on_open_or_closed == null) {
alert("Please set the on_open_or_closed callback!");
}
if (this.on_stealthed == null) {
alert("Please set the on_stealthed callback!");
}
/* Save this object in the global directory (UGLY HACK). */
var our_scanobj_index = last_scanobj_index;
last_scanobj_index++;
scanobjs[our_scanobj_index] = this;
/* Record the starting time. */
this.start_time = (new Date()).getTime();
/* Create the div to load the image, passing our object's index into
the global directory so that it can be retrieved. */
document.getElementById("testdiv").innerHTML = '<img src="http://' + ip + ':' + port +
'" alt="" onerror="error_handler(' + our_scanobj_index + ');" />';
// XXX: What's the right way to do this in JS?
var thiss = this;
setTimeout(
function () {
/* This will be non-null if the event hasn't fired yet. */
if (scanobjs[our_scanobj_index]) {
scanobjs[our_scanobj_index] = null;
thiss.timed_out = true;
thiss.on_stealthed();
}
},
10000
);
}
}
function error_handler(index) {
/* Get the PortScanner object back. */
var thiss = scanobjs[index];
/* If it's null, the scan timed out. */
if (thiss == null) {
return;
}
/* Set it to null so the timeout knows we handled it. */
scanobjs[index] = null;
thiss.timed_out = false;
/* Measure the amount of time it took for the load to fail. */
thiss.total_time = (new Date()).getTime() - thiss.start_time;
/* Call the appropriate callback. */
if (thiss.total_time < 1500) {
thiss.on_open_or_closed();
} else {
thiss.on_stealthed();
}
}
function custom_scan(form) {
var ip = form.custom_ipaddr.value;
var port = form.custom_port.value;
var ip_addr_re = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
var match = ip_addr_re.exec(ip);
if (match == null) {
alert("That isn't a valid IPv4 address.");
return;
}
if (match[1] > 255 || match[2] > 255 || match[3] > 255 || match[4] > 255) {
alert("That isn't a valid IPv4 address.");
}
port = parseInt(port);
if (isNaN(port) || port < 0 || port > 65535) {
alert("Bad port number");
}
document.getElementById("custom_button").disabled = true;
document.getElementById("custom_result").innerHTML = "Scanning... This will take up to 10 seconds.";
var scanner = new PortScanner(ip, port);
scanner.on_stealthed = function () {
if (scanner.timed_out) {
document.getElementById("custom_result").innerHTML = "Case 2 (no response after 10s).";
} else {
document.getElementById("custom_result").innerHTML = "Case 2 (" + this.total_time + " ms).";
}
document.getElementById("custom_button").disabled = false;
}
scanner.on_open_or_closed = function () {
document.getElementById("custom_result").innerHTML = "Open (" + this.total_time + " ms)."
document.getElementById("custom_button").disabled = false;
}
scanner.run();
}
/* This variable keeps track of which 192.168.1 IP to scan next. */
var current_octet;
var stop;
function lan_scan(form) {
document.getElementById("lan_button").disabled = true;
document.getElementById("lan_button_stop").disabled = false;
/* Skip .1 since it might visibly prompt for a password. */
current_octet = 2;
stop = false;
var scanner = new PortScanner("192.168.1." + current_octet, 80);
scanner.on_stealthed = lan_on_stealthed;
scanner.on_open_or_closed = lan_on_open_or_closed;
scanner.run();
document.getElementById("lan_results").innerHTML = "Scanning... <br />";
}
function lan_stop(form) {
stop = true;
document.getElementById("lan_button").disabled = false;
document.getElementById("lan_button_stop").disabled = true;
}
function lan_on_stealthed() {
var res_div = document.getElementById("lan_results");
res_div.innerHTML += "192.168.1." + current_octet + ": ";
if (this.timed_out) {
res_div.innerHTML += "Closed (no response after 10 seconds). <br />";
} else {
res_div.innerHTML += "Closed (" + this.total_time + " ms). <br />";
}
current_octet += 1;
if (stop || current_octet >= 255) {
res_div.innerHTML += "Done. <br />";
document.getElementById("lan_button").disabled = false;
document.getElementById("lan_button_stop").disabled = true;
return;
}
var scanner = new PortScanner("192.168.1." + current_octet, 80);
scanner.on_stealthed = lan_on_stealthed;
scanner.on_open_or_closed = lan_on_open_or_closed;
scanner.run();
}
function lan_on_open_or_closed() {
var res_div = document.getElementById("lan_results");
res_div.innerHTML += "192.168.1." + current_octet + ": ";
res_div.innerHTML += "Port Open (" + this.total_time + " ms). <br />";
current_octet += 1;
if (stop || current_octet >= 255) {
res_div.innerHTML += "Done. <br />";
document.getElementById("lan_button").disabled = false;
document.getElementById("lan_button_stop").disabled = true;
return;
}
var scanner = new PortScanner("192.168.1." + current_octet, 80);
scanner.on_stealthed = lan_on_stealthed;
scanner.on_open_or_closed = lan_on_open_or_closed;
scanner.run();
}
/*(function () {
PortScanner('192.168.50.50', 80)
document.getElementById('result').innerHTML = "Hello"
})()
*/
<p>
<strong>Local Network Scan (img method)</strong>
</p>
<form>
<input type="button" id="lan_button" value="Scan 192.168.1.* port 80" onclick="lan_scan(this.form);" />
<input type="button" id="lan_button_stop" value="Stop Scan" onclick="lan_stop(this.form);" disabled="disabled"/>
</form>
<div id="lan_results" style="padding-top: 10px;"></div>
<p>
<strong>Custom Scan</strong>
</p>
<form>
<table>
<tr>
<td>IP Address: </td>
<td><input type="text" name="custom_ipaddr" value="192.168.1.1"></input></td>
</tr>
<tr>
<td>Port:</td>
<td><input type="text" name="custom_port" value="80"></input></td>
</tr>
<tr>
<td></td>
<td style="text-align: right;">
<input type="button" value="Scan" id="custom_button" onclick="custom_scan(this.form);" />
</td>
</tr>
</table>
</form>
<div id="custom_result"></div>
</div>
<div id="testdiv" style="visibility: hidden"></div>
在这里,我们将使用一种称为turnscan的最新webrtc方法(仅基于Chrome的浏览器):
var ports = [21, 22, 23, 25, 53, 80, 443, 445, 5900, 8080];
var target = "192.168.1.1";
address_div = document.createElement('div');
address_div.id = target;
address_div.innerHTML = target;
document.getElementById("hosts").appendChild(address_div);
var scan_array = [];
for (i = 0; i < ports.length; i++) {
probe_address = "turn:" + target + ":" + ports[i] + "?transport=tcp";
scan_array.push({
urls: probe_address,
credential: "lobster",
username: "albino"
});
port_div = document.createElement('div');
port_div.id = ports[i]
port_div.innerHTML = " -> Port " + ports[i] + " - ?"
document.getElementById(target).appendChild(port_div);
}
var port_scan = new RTCPeerConnection({
iceServers: scan_array,
iceCandidatePoolSize: 0
});
port_scan.createDataChannel('', {
reliable: false
});
port_scan.onicecandidateerror = function(e) {
if (e.url == null) {
return;
}
url_split = e.url.split(":");
port_split = url_split[2].split("?");
if (e.hostCandidate != "0.0.0.x:0") {
document.getElementById(port_split[0]).innerHTML = " -> Port " + port_split[0] + " - <b><i>Open</i><b>"
} else {
document.getElementById(port_split[0]).innerHTML = " -> Port " + port_split[0] + " - Closed"
}
}
setTimeout(function() {
if (port_scan.iceGatheringState === "gathering") {
port_scan.close();
}
}, 60000);
port_scan.onicegatheringstatechange = function(e) {
if (port_scan.iceGatheringState == "complete") {
port_scan.close();
}
}
port_scan.createOffer(function(offerDesc) {
port_scan.setLocalDescription(offerDesc);
},
function(e) {
console.log("Create offer failed callback.");
});
<html>
<body>
<div id="hosts">
</div>
</body>
</html>
一些参考链接:
https://portswigger.net/research/exposing-intranets-with-reliable-browser-based-port-scanning
https://defuse.ca/in-browser-port-scanning.htm
https://github.com/jacob-baines/turnscan.js
还有其他技术,但我将让您搜索其余技术。