So you want to build a Javascript based network scanner

OK, first of: the idea is not exactly original, and it has been tried and tested over the years. You’ll find posts/blogs everywhere of people that made JavaScript scanners before. Soon you will learn that most seem to be works in progress or are abandoned entirely. Most of them are also quite limited, mostly scanning default ip addresses of networked devices, or exploiting a single device on a LAN.

There’s a good reason why they all seem to be rudimentary and unfinished: this method of scanning is crude, loud and slow.  And I presume that’s why most of them abandon this project. You might say they are coming to their senses, I’d rather call it lack of vision. :)

So, being the stubborn man that I am, and never taking other peoples opinions for granted, I started weighing the pro’s and con’s. Below you’ll find what I’ve come up with so far. Any feedback on the matter is more then welcome.

How it works: the basics

You send  a link to a specially crafted web page to a user on the target LAN, this page contains a JavaScript that tries to load a set of images. But instead of your average image pre-loading script, this script doesn’t retrieve images from your site in the background, but rather scans certain internal ip addresses for known image file locations.

Image you have a canon network printer that has a web interface, and it runs on http://192.168.0.5/ . On it’s page is the Canon logo, and it is located at http://192.168.0.5/images/canon_logo.png.
If you were to add a script that loads this image on your page, I could (mis)use the images on-load and on-error event handles to check if there is such an image, and therefore such a device on your LAN. All that is left then is smuggle the result back out to you and thus end up with a rudimentary scanner.

Problem1 : It’s slow

Let’s say you wanted to scan an internal network range 192.168.0.0/24, for a list of 100 possible devices (i.e.: 100 known file locations). , you end up with 25400 possible requests. Most approaches I found just loop through the image list for each ip in the range. This takes quite some time and often results in a heavy burden on the browser’s memory usage. So, how can we limit the number of requests?

Speeding things up

One of the first things we could/should do to speed things up is quite obvious: image list optimisation.
There’s no need to scan all ip’s for all images. If you find an image on a certain address there is probably no reason to scan for the other images as well, it’s highly unlikely that a host returning a hit for a specific canon image is also going to yield one for a DLINK device. So, your scanner should stop looping through the list once it gets a hit.
To make the most of this, it would be wise to order your list in order of occurrence. Meaning, that if a device x is more popular (as in: sold and used more often) then device y, it should be placed higher in the list. By optimising your image list this way you might reduce your scanning time drastically.

It doesn’t have to end there though. You could also make your image list dynamic.
Companies often tend to buy material from the same vendor. So, if you find a canon printer, it is likely that there are others. So, it might be beneficial to move the canon printer images  up in your list for other devices as well.
Another consideration you might make is, if you are scanning with the intent of exploiting a certain device type, to remove an image from the scan-list for other hosts if you have found a hit for the image on a certain host (opting to do a more profound scan from the exploited machine).

I also found that most scanners tend to focus on the originality of the file name/location. But why not go for generic images?
Lets say you compiled a list for different router types of the same vendor, and you have done this for 4 router vendors. You could loop through all these images trying to get a hit, but you end up trying possible hundreds of requests per host, with just one possible correct one.
So, in stead of looping through specific, per device, images, why not go through the most generic ones first? Imagine all devices of brand a have the brands logo on their page, and it always has the same name/path. Scanning for this image first will already give you a hit for the brand, eliminating the need to scan for devices of another brand.
You can even go further with this. When scanning through an ip-range, it could first go through a very small list of images first: [welcome.png, pagerror.gif, favicon.ico]
Welcome.png will return hits on IIS7 servers, no need to scan for other networked devices on this ip, seeing very little (I know of none actually) run an IIS7 web-server.
(depending on your scanning reason this might trigger a scan for other exploits in common web app packages?)
pagerror.gif: yields hits for IIS6
favicon.ico is often used. Once you know that this image is there /not there, you can load image lists for devices that share this trait (i.e.: having a favicon or not).
Which brings me to the next point.

Use what you have: most scanners seems to focus on originality of the file-names, but their might be other information equally valuable, especially when you use the scanning for generic images route. The other properties at your disposal in the image object include height/width. If you have 2 different devices that have the same imagepath/name that contains a different image, you can obtain the correct result by checking it’s size. Reducing the amount of http requests to obtain the same result.

Seeing the equation of total amount of requests is ipaddresses*imagelist you should therefor also consider optimising your ip list. This means it might a good idea to first figure out the subnet ranges of your target and configure the scanner accordingly. It’s also advisable to build in a mechanism for reporting dead/non responsive hosts.
I’m currently still trying to figure out the best way to do that (see paragraph below: Playing with onerror event timing)

Problem2: It’s loud

The loudness is for me the biggest downside of this type of scans. When running tests I kept being annoyed by login pop-ups from devices that require basic or ntml authentication. I can’t think of a way to circumvent this and it is dead sure to trigger suspicion on a tech savvy target. There are however some techniques you might employ to minimise this nuisance:

register your image load times: if it takes user interaction to cancel/close those pop-ups, meaning that it takes longer before your image load activity either works or generates an error. you could omit further scans on these hosts/ips if a response time passes a certain limit (i.e. 4 seconds).
choose your target wisely: if they run internet explorer with default settings, ntlm authentication will not trigger a pop-up if the host is identified as being in the same LAN. Pick a target that is not too tech savvy either.

Another thing that bothers me, but isn’t tied to just JavaScript LAN scanners is that the addresses need to be resolved to hardware addresses, this results in a high increase in arp broadcast requests from your targets machine, this is noise that is easily picked up. (Although I’m surprised to say that my AV from a certain well known vendor sees no harm in this at all…)

not very stealthy

arp requests from scan

Playing with onerror event timing

As mentioned before a good scanner should quickly identify dead hosts (not online, or no http server running) and omit these hosts from further scanning. I’m still not sure on the best way to do this, but was thinking about some sort of timing to identify dead ends.

Currently I’m thinking about arp as a  possible candidates for the job:
ARP request retries
: I need to test this on other machines, but on my Ubuntu, several arp requests are tried, always with 1 second in between. The calling routine is always sent  a “no host found” error after 3 tries (although it tries a few more arp requests after that). When calling image.src=”http://non_assigned_ip/idonexist.jpg” I consistently got a trigger of the on-error event after 3 seconds.

This as opposed when I tried to connect to a machine that was enabled,but tried on the wrong port. When trying to load http://ip_that_does_Exist:88/idontexist.jpg, the on-error event was fired within less then a second. Port 88 wasn’t enabled on that host so the TCP connection failed.
From this I can already surmise that if my image loading routing fires an error in less then 3 seconds that the ip address is in use. Please note that assume an ip is not in use with 3 seconds error intervals might be a bit too much as this might be due to server and network load.
Conclusion: is it worth it?

I’m still not sure. Seeing the scanning engine will run on a web page, you will need to take in account how long you can keep the target on your page. In the end, the consideration you will have to make is: What result am I expecting from my scan, how much time will it take this method of scanning to reach objective and how much time do I at my disposal?

One Response to So you want to build a Javascript based network scanner

  1. Pingback: Jenscan: javascript based lan scanner « Allodoxaphobia

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: