From 3154e97dcf02a131efcf2237f8acee375ec2cca8 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Fri, 16 Oct 2015 22:23:17 -0400 Subject: [PATCH 1/9] added IP subnet calculator --- sonar.js | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/sonar.js b/sonar.js index d39d042..9bde970 100644 --- a/sonar.js +++ b/sonar.js @@ -111,16 +111,54 @@ var sonar = { sonar.fingerprints = fingerprints; }, - 'ip_to_range': function( ip ) { + 'ip_to_range': function(ip, range) { var ip_parts = ip.split( '.' ); if( ip_parts.length !== 4 ) { return false; } - for( var i = 1; i < 255; i++ ) { - var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + i; - sonar.ip_queue.push( tmp_ip ); + var ip_min = [0, 0, 0, 0]; + var ip_max = [0, 0, 0, 0]; + var r = 0; + + for( var tmp = 0; tmp < 4; tmp++ ) { + + // Calculate the number of bits of each part + if ( range > 8 + 8 * tmp){ + r = 0; + } else { + r = 8 - (range - tmp * 8); + if ( r < 0 ){ + r = 8; + } + } + + // Calculate minimum and maximum of IP range for the current part + ip_min[tmp] = ip_parts[tmp] & (255 << r); + ip_max[tmp] = ip_parts[tmp] | (255 & ~(255 << r)); } + + if( sonar.debug ) { + alert( '[DEBUG][The samallest IP adress to be scaned is:]' + ip_min[0] + '.' + ip_min[1] + '.' + ip_min[2] + '.' + ip_min[3]); + alert( '[DEBUG][The largest IP adress to be scaned is:]' + ip_max[0] + '.' + ip_max[1] + '.' + ip_max[2] + '.' + ip_max[3]); + } + + // Queue IP address range + var ip_parts = ip_min.slice(); + for( var a = ip_min[0]; a <= ip_max[0]; a++ ) { + ip_parts[0] = a; + for( var b = ip_min[1]; b <= ip_max[1]; b++ ) { + ip_parts[1] = b; + for( var c = ip_min[2]; c <= ip_max[2]; c++ ) { + ip_parts[2] = c; + for( var d = ip_min[3]; d <= ip_max[3]; d++ ) { + ip_parts[3] = d; + var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + ip_parts[3]; + sonar.ip_queue.push( tmp_ip ); + } + } + } + } }, /* @@ -183,7 +221,7 @@ var sonar = { function addAddress(newAddr) { if (newAddr in addrs) return; addrs[newAddr] = true; - sonar.ip_to_range(newAddr); + sonar.ip_to_range(newAddr, 24); // We assume that we are on a /24 } function grepSDP(sdp) { var hosts = []; From 79db80b35815aa6e9b0c2ed54dc9cd61e6110d13 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Sat, 24 Oct 2015 14:21:13 -0400 Subject: [PATCH 2/9] Added option to define target subnet or size of subnet --- example.htm | 6 +++++- sonar.js | 21 ++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/example.htm b/example.htm index e774324..33444e9 100644 --- a/example.htm +++ b/example.htm @@ -8,8 +8,12 @@ diff --git a/sonar.js b/sonar.js index 9bde970..d1d0b48 100644 --- a/sonar.js +++ b/sonar.js @@ -8,7 +8,7 @@ var sonar = { /* * Start the exploit */ - 'start': function(debug, interval_scan) { + 'start': function(debug, interval_scan, target) { if( debug !== undefined ) { sonar.debug = true; } @@ -17,16 +17,27 @@ var sonar = { interval_scan = 1000; } + if( target === undefined ) { + target = "/24"; + } + if( sonar.fingerprints.length == 0 ) { return false; } + // Separate IP and range, target[0] is the IP and target[1] is the range + target = target.split( '/' ); + // This calls sonar.process_queue() every setInterval( function() { sonar.process_queue(); }, interval_scan ); - sonar.enumerate_local_ips(); + if( target[0] == "" ) { + sonar.enumerate_local_ips( target[1] ); + } else{ + sonar.ip_to_range( target[0], target[1] ); + } }, /* @@ -123,7 +134,7 @@ var sonar = { for( var tmp = 0; tmp < 4; tmp++ ) { - // Calculate the number of bits of each part + // Calculate the number of bits that change of each part if ( range > 8 + 8 * tmp){ r = 0; } else { @@ -213,7 +224,7 @@ var sonar = { //console.log( 'Dead IP', ip ); }, - 'enumerate_local_ips': function() { + 'enumerate_local_ips': function(range) { var RTCPeerConnection = window.webkitRTCPeerConnection || window.mozRTCPeerConnection; if (!RTCPeerConnection) return false; var addrs = Object.create(null); @@ -221,7 +232,7 @@ var sonar = { function addAddress(newAddr) { if (newAddr in addrs) return; addrs[newAddr] = true; - sonar.ip_to_range(newAddr, 24); // We assume that we are on a /24 + sonar.ip_to_range(newAddr, range); } function grepSDP(sdp) { var hosts = []; From 58ca962c2aa23cc65102085d0c2cea6138698c74 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Mon, 26 Oct 2015 19:49:54 -0400 Subject: [PATCH 3/9] fixed queuing of reserved address --- example.htm | 4 ++-- sonar.js | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/example.htm b/example.htm index 33444e9..da93e90 100644 --- a/example.htm +++ b/example.htm @@ -12,8 +12,8 @@ sonar.start(true, 2000 ); // It's also possible to specify a target or subnet size - //sonar.start(true, 2000, 192.168.0.1/24); - //sonar.start(true, 2000, /24); + //sonar.start(true, 2000, "192.168.0.1/24"); + //sonar.start(true, 2000, "/24"); diff --git a/sonar.js b/sonar.js index d1d0b48..b445177 100644 --- a/sonar.js +++ b/sonar.js @@ -134,7 +134,7 @@ var sonar = { for( var tmp = 0; tmp < 4; tmp++ ) { - // Calculate the number of bits that change of each part + // Calculate the number of bits that change of the current part if ( range > 8 + 8 * tmp){ r = 0; } else { @@ -150,23 +150,26 @@ var sonar = { } if( sonar.debug ) { - alert( '[DEBUG][The samallest IP adress to be scaned is:]' + ip_min[0] + '.' + ip_min[1] + '.' + ip_min[2] + '.' + ip_min[3]); + alert( '[DEBUG][The samallest IP adress to be scaned is:]' + ip_min[0] + '.' + ip_min[1] + '.' + ip_min[2] + '.' + (ip_min[3] + 1)); alert( '[DEBUG][The largest IP adress to be scaned is:]' + ip_max[0] + '.' + ip_max[1] + '.' + ip_max[2] + '.' + ip_max[3]); } // Queue IP address range var ip_parts = ip_min.slice(); + var d = ip_min[3] + 1; for( var a = ip_min[0]; a <= ip_max[0]; a++ ) { ip_parts[0] = a; for( var b = ip_min[1]; b <= ip_max[1]; b++ ) { ip_parts[1] = b; for( var c = ip_min[2]; c <= ip_max[2]; c++ ) { ip_parts[2] = c; - for( var d = ip_min[3]; d <= ip_max[3]; d++ ) { + while( d <= ip_max[3] ) { ip_parts[3] = d; var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + ip_parts[3]; sonar.ip_queue.push( tmp_ip ); + d++; } + d = ip_min[3] } } } From fd85c2d8b8d1631c1795b4e50b20ef8590999c30 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Mon, 26 Oct 2015 20:13:01 -0400 Subject: [PATCH 4/9] fixed queuing of broadcast address --- sonar.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sonar.js b/sonar.js index b445177..c266f11 100644 --- a/sonar.js +++ b/sonar.js @@ -151,18 +151,26 @@ var sonar = { if( sonar.debug ) { alert( '[DEBUG][The samallest IP adress to be scaned is:]' + ip_min[0] + '.' + ip_min[1] + '.' + ip_min[2] + '.' + (ip_min[3] + 1)); - alert( '[DEBUG][The largest IP adress to be scaned is:]' + ip_max[0] + '.' + ip_max[1] + '.' + ip_max[2] + '.' + ip_max[3]); + alert( '[DEBUG][The largest IP adress to be scaned is:]' + ip_max[0] + '.' + ip_max[1] + '.' + ip_max[2] + '.' + (ip_max[3] - 1)); } // Queue IP address range - var ip_parts = ip_min.slice(); var d = ip_min[3] + 1; for( var a = ip_min[0]; a <= ip_max[0]; a++ ) { ip_parts[0] = a; + if ( a == ip_max[0] ){ // Check if we are approaching the end of the subnet + var ae = 1; + } for( var b = ip_min[1]; b <= ip_max[1]; b++ ) { ip_parts[1] = b; + if ( ae == 1 && b == ip_max[1] ){ + var be = 1; + } for( var c = ip_min[2]; c <= ip_max[2]; c++ ) { ip_parts[2] = c; + if ( be == 1 && c == ip_max[2] ){ + ip_max[3]--; // Prevent the broadcast address from getting queued + } while( d <= ip_max[3] ) { ip_parts[3] = d; var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + ip_parts[3]; From 2e29d89b1914c5b0068cf9ead8aba9f33295d2a0 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Mon, 26 Oct 2015 20:24:39 -0400 Subject: [PATCH 5/9] removed unnecessary variables --- sonar.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/sonar.js b/sonar.js index c266f11..cee724f 100644 --- a/sonar.js +++ b/sonar.js @@ -155,29 +155,25 @@ var sonar = { } // Queue IP address range - var d = ip_min[3] + 1; - for( var a = ip_min[0]; a <= ip_max[0]; a++ ) { - ip_parts[0] = a; - if ( a == ip_max[0] ){ // Check if we are approaching the end of the subnet + ip_parts[3] = ip_min[3] + 1; + for( ip_parts[0] = ip_min[0]; ip_parts[0] <= ip_max[0]; ip_parts[0]++ ) { + if ( ip_parts[0] == ip_max[0] ){ // Check if we are approaching the end of the subnet var ae = 1; } - for( var b = ip_min[1]; b <= ip_max[1]; b++ ) { - ip_parts[1] = b; - if ( ae == 1 && b == ip_max[1] ){ + for( ip_parts[1] = ip_min[1]; ip_parts[1] <= ip_max[1]; ip_parts[1]++ ) { + if ( ae == 1 && ip_parts[1] == ip_max[1] ){ var be = 1; } - for( var c = ip_min[2]; c <= ip_max[2]; c++ ) { - ip_parts[2] = c; - if ( be == 1 && c == ip_max[2] ){ + for( ip_parts[2] = ip_min[2]; ip_parts[2] <= ip_max[2]; ip_parts[2]++ ) { + if ( be == 1 && ip_parts[2] == ip_max[2] ){ ip_max[3]--; // Prevent the broadcast address from getting queued } - while( d <= ip_max[3] ) { - ip_parts[3] = d; + while( ip_parts[3] <= ip_max[3] ) { var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + ip_parts[3]; sonar.ip_queue.push( tmp_ip ); - d++; + ip_parts[3]++; } - d = ip_min[3] + ip_parts[3] = ip_min[3]; } } } From 3cd6af53170118ca2d32bd9a3a261af21c8f368d Mon Sep 17 00:00:00 2001 From: flex-lm Date: Tue, 27 Oct 2015 11:00:57 -0400 Subject: [PATCH 6/9] updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6992c64..1a2ca8e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A framework for identifying and launching exploits against internal network host ## How does it work? Upon loading the sonar.js payload in a modern web browser the following will happen: -* sonar.js will use WebRTC to enumerate what internal IPs the user loading the payload has. +* sonar.js will use WebRTC to enumerate what internal IPs the user loading the payload has, assuming a /24 subnet size unless a target subnet or subnet size has been specified. * sonar.js then attempts to find live hosts on the internal network via WebSockets. * If a live host is found, sonar.js begins to attempt to fingerprint the host by linking to it via `````` and `````` and hooking the ```onload``` event. If the expected resources load successfully it will trigger the pre-set JavaScript callback to start the user-supplied exploit. From 85a4b2febb9b55a1125490e93d07b917bdfe50a3 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Sat, 31 Oct 2015 13:22:54 -0400 Subject: [PATCH 7/9] removed redundant if --- sonar.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/sonar.js b/sonar.js index cee724f..a010573 100644 --- a/sonar.js +++ b/sonar.js @@ -139,9 +139,6 @@ var sonar = { r = 0; } else { r = 8 - (range - tmp * 8); - if ( r < 0 ){ - r = 8; - } } // Calculate minimum and maximum of IP range for the current part From b6ef2dcb263543c7c040b604791480b179603d91 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Fri, 6 Nov 2015 15:25:57 -0500 Subject: [PATCH 8/9] added capability of scanning only one IP --- example.htm | 4 ++++ sonar.js | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/example.htm b/example.htm index da93e90..b07c57f 100644 --- a/example.htm +++ b/example.htm @@ -14,6 +14,10 @@ // It's also possible to specify a target or subnet size //sonar.start(true, 2000, "192.168.0.1/24"); //sonar.start(true, 2000, "/24"); + + // Or just one IP + //sonar.start(true, 2000, "192.168.0.1/32"); + //sonar.start(true, 2000, "192.168.0.1"); diff --git a/sonar.js b/sonar.js index a010573..5c0cde7 100644 --- a/sonar.js +++ b/sonar.js @@ -26,7 +26,16 @@ var sonar = { } // Separate IP and range, target[0] is the IP and target[1] is the range + // If the range is not specified, we assume that only one IP should be scaned target = target.split( '/' ); + if( target[1] === undefined ) { + target[1] = 32; + } + + // Check the specified IP range, /31 subnets are excluded because those only have reserved and broadcast addresses + if( target[1] < 0 || target[1] > 32 || target[1] == 31 ) { + return false; + } // This calls sonar.process_queue() every setInterval( function() { @@ -36,7 +45,7 @@ var sonar = { if( target[0] == "" ) { sonar.enumerate_local_ips( target[1] ); } else{ - sonar.ip_to_range( target[0], target[1] ); + sonar.ip_to_range( target[0], target[1] ); } }, @@ -128,6 +137,12 @@ var sonar = { return false; } + // If we're only going to scan one IP, queue it without calculating the range + if ( range == 32 ){ + sonar.ip_queue.push( ip ); + return; + } + var ip_min = [0, 0, 0, 0]; var ip_max = [0, 0, 0, 0]; var r = 0; From 417709b17d989e645b3db5a34d0d928a7dd32323 Mon Sep 17 00:00:00 2001 From: flex-lm Date: Fri, 6 Nov 2015 16:19:46 -0500 Subject: [PATCH 9/9] replaced tabs with spaces --- sonar.js | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/sonar.js b/sonar.js index 5c0cde7..64044a5 100644 --- a/sonar.js +++ b/sonar.js @@ -149,12 +149,12 @@ var sonar = { for( var tmp = 0; tmp < 4; tmp++ ) { - // Calculate the number of bits that change of the current part - if ( range > 8 + 8 * tmp){ - r = 0; - } else { - r = 8 - (range - tmp * 8); - } + // Calculate the number of bits that change of the current part + if ( range > 8 + 8 * tmp){ + r = 0; + } else { + r = 8 - (range - tmp * 8); + } // Calculate minimum and maximum of IP range for the current part ip_min[tmp] = ip_parts[tmp] & (255 << r); @@ -169,26 +169,26 @@ var sonar = { // Queue IP address range ip_parts[3] = ip_min[3] + 1; for( ip_parts[0] = ip_min[0]; ip_parts[0] <= ip_max[0]; ip_parts[0]++ ) { - if ( ip_parts[0] == ip_max[0] ){ // Check if we are approaching the end of the subnet - var ae = 1; - } - for( ip_parts[1] = ip_min[1]; ip_parts[1] <= ip_max[1]; ip_parts[1]++ ) { - if ( ae == 1 && ip_parts[1] == ip_max[1] ){ - var be = 1; - } - for( ip_parts[2] = ip_min[2]; ip_parts[2] <= ip_max[2]; ip_parts[2]++ ) { - if ( be == 1 && ip_parts[2] == ip_max[2] ){ - ip_max[3]--; // Prevent the broadcast address from getting queued - } - while( ip_parts[3] <= ip_max[3] ) { - var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + ip_parts[3]; - sonar.ip_queue.push( tmp_ip ); - ip_parts[3]++; - } - ip_parts[3] = ip_min[3]; - } - } - } + if ( ip_parts[0] == ip_max[0] ){ // Check if we are approaching the end of the subnet + var ae = 1; + } + for( ip_parts[1] = ip_min[1]; ip_parts[1] <= ip_max[1]; ip_parts[1]++ ) { + if ( ae == 1 && ip_parts[1] == ip_max[1] ){ + var be = 1; + } + for( ip_parts[2] = ip_min[2]; ip_parts[2] <= ip_max[2]; ip_parts[2]++ ) { + if ( be == 1 && ip_parts[2] == ip_max[2] ){ + ip_max[3]--; // Prevent the broadcast address from getting queued + } + while( ip_parts[3] <= ip_max[3] ) { + var tmp_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + ip_parts[3]; + sonar.ip_queue.push( tmp_ip ); + ip_parts[3]++; + } + ip_parts[3] = ip_min[3]; + } + } + } }, /*