Tuesday, April 2, 2013

Sinkholing, with reporting, using Windows DNS, Netcat, and BLAT on a Zero Dollar Budget

So DNS sinkholes are a pretty good idea to run internally in a company. Doing it for free is better. If you like the idea of using this, don't want to pay for it, and you run Windows, this post is for you.

Currently my solution only handles HTTP connections with logging, it will still sinkhole all connections to the domains but it will log and alert you to HTTP connections only.

I'm sure there's a lot of different ways you can do this. I'm using Windows Server 2K8r2 with DNS already installed in this setup, my actual setup that I will be implementing will be running some flavor of *nix and BIND, it's just more flexible. I saw lots of things that use various *nix setups and BIND but nothing that really works with Windows (for free) so I decided to take the path less traveled.

This power shell script I found from the SANS institute does an AMAZING job of adding entries into Windows DNS. Article with link to zip file with powershell script. Read the whole article, it's worth it.

So since we now have a power shell script that can manipulate DNS entries on our Windows DNS server we need to decide if we're going to sinkhole just one domain or a list of domains. Since making a sinkhole and scripting stuff doens't really make sense for just one entry we'll need a list of bad domains.

I'm getting my list from Malware-Domains.com specifically the "Just Domains" list. I haven't vetted this list for accuracy, speed of update, false positives, or anything really. It just happened to be one of the more commonly mentioned lists I saw floating about the net. I strongly suggest you put some time in and do the research on what list to choose, it could mean the difference between a LOT of angry end users and little to no effective result and a well functioning setup.

Alright, we know where the list we want is, we know what script we're going to use to create the sinkholes, including the switches we want (because you read the article, right). Now lets stitch our server portion together:

I've created a Directory named C:\Sinkhole.
Inside this directory I have my Sinkhole-DNS.ps1 script (from the link above, the one your read the whole way through) and this script:

@echo off
if exist C:\Sinkhole\justdomains.zip del /f /q C:\Sinkhole\justdomains.zip
if exist C:\Sinkhole\justdomains.txt del /f/ q C:\Sinkhole\justdomains.txt
powershell.exe C:\sinkhole\Sinkhole-DNS.ps1 -DeleteSinkHoleDomains
bitsadmin /transfer MalwareDomains /download /priority normal http://www.malware-domains.com/files/justdomains.zip C:\Sinkhole\justdomains.zip
7zip e C:\sinkhole\justdomains.zip -oC:\sinkhole\
ren C:\sinkhole\justdomains justdomains.txt
del /f /q C:\sinkhole\justdomains.zip
powershell.exe C:\sinkhole\Sinkhole-DNS.ps1 -InputFile "C:\sinkhole\justdomains.txt" -SinkholeIP "" -IncludeWildCard
del /f /q C:\sinkhole\justdomains.txt

First two commands are "just in case" house cleaning. Those two files should get nuked at the end of the script, but just in case they don't we check for and remove them before we get started.

Next we use powershell to run our Sinkhole-DNS script to remove all the DNS sinkholes that were created at the last run. It's not likely that a domain that was used to host malware got clean and is now being used for legitimate traffic, but I want it to remove all the old stuff first. Keep things clean. (this can take several actual minutes)

Then we have a bitsadmin command to go out and grab the domains list from malware-domains.com and save it to C:\Sinkhole\

Now we use the built in windows command line utility to extract the files from the zip archive ....
Oh wait, no we can't, because there is no such beast. WHY MICROSOFT WHY!!!!
So we use 7zip's command line application Download Site the Command Line Version runs on x32 and x64.
*Please note I renamed the 7zip executable and placed it in a separate folder and added it to the path variable for ease of access now and in the future. You can place it directly in the C:\sinkhole folder or a folder that is in your path variable.

Then we rename the file justdomains to justdomains.txt. Because since it's windows I want it to have the appropriate file extension, that's why.

Delete the zip file as we don't need it any longer.

Run our powershell script to add all the domains to DNS and point them to our listener and logging station, in this example (this can take several actual minutes).

Delete the txt file with the domain names.

I suggest creating a scheduled task for this script.


Okay so we now have a ton of new entries in our DNS server, it makes a mess, you can't find anything, and it's confusing. I would get a separate server from your main internal DNS servers and use this as a forwarder for them, that way you can still navigate your internal DNS stuff without having to look through a jungle. Plus, even through there are safeguards against the script deleting anything that's not in the sinkhole it's always better to be safe than sorry.

We've got through the whirlwind tour of setting up the DNS server. Now we need to setup our listener and reporting station.

You should be able to use any recent version of windows you want for this. I happened to have an old XP machine sitting about collecting dust so I used that. I didn't test it on 7 or 8 or 2003 or 2008 or 2012, it should work without a problem as long as your AV doesn't go all nom nom nom on the netcat / ncat executable.

Okay so lets get our listener setup.

I used netcat for windows, I already had it and it did what I needed. I'm sure you could use ncat and achieve the same results, likely better results with more listening ports capturing more protocols. I've used ncat before but the version I used lacked the portability that I wanted for this. I hear tell that there's now a standalone version now that doesn't require the library files to be bundled with it separately anymore. It has more advanced features and it's worth your time to check it out. Ncat

So netcat serves a dual purpose here.
1. We can use netcat as a primitive web server by directing a file to it while it's listening.
2. Netcat will log the HTTP request then we can send it to ourselves as an email and know what's going on.

We'll also need something to send us an email with the information we've gathered from the listener.
I like BLAT that's what I used, you can use something else if you want. BLAT

This is the listener script I wrote to handle things:

@echo off
echo A Connection has been made to the sinkhole: > temp.txt
echo ------------------------------------------- >> temp.txt
nc -l -vv -p 80 -w 2 -s< index.html >> temp.txt
echo ------------------------------------------- >> temp.txt
echo %date% >> temp.txt
echo %time% >> temp.txt
for /f "tokens=3" %%a in ('netstat -ano ^| find /i "" ^| find /i "time_wait"') do set host=%%a
set host=%host::=#%
for /f "tokens=1 delims=#" %%a in ("%host%") do set host=%%a
for /f "tokens=2" %%a in ('nslookup %host% ^| find /i "Name:"') do set name=%%a
echo From: %name% %host% >> temp.txt
::set date
set dt=%date:~4,2%.%date:~7,2%.%date:~10,4%
::set time
if %time:~0,2% LSS 10 set hr=%time:~1,1%
if %time:~0,2% GEQ 10 set hr=%time:~0,2%
if %time:~3,2% LSS 10 set mn=%time:~4,1%
if %time:~3,2% GEQ 10 set mn=%time:~3,2%
set tm=%hr%.%mn%
::set name
set name=%host%_%dt%-%tm%
::rename file
ren temp.txt %name%.txt
::send the alert
blat.exe %name%.txt -server -subject "HTTP Sinkhole Alert- %host%" -to youremailhere@domain.com -mailfrom sinkhole@domain.com
move %name%.txt old
set name=
set dt=
set tm=
goto beg

Alright so I have this setup as a loop, you could probably use netcat's -L (listen harder) but I was having trouble running the rest of the commands reliably with any solution I could come up with using -L so I just make a big loop.

I write out all the info I get from the listener, plus some other info, and formatting to temp.txt

I start my netcat listener and pipe to it index.html. I do this because on the off chance a user tries to go to a sinkhole domain and it's been unjustly listed as such they know what's going on and to contact me. (index.html will be included below).
-l is listen
-vv is very verbose
-w 2 is wait 2 seconds before closing the connection (timeout). You need this or else it will sit there with an open connection endlessly
-s says to bind and listen on this IP address only
-p 80 is port 80
<index.html will shovel index.html to anything that connects to it
>> temp.txt writes everything that netcat receives to the temp file

Everything else is mostly formatting.
echo %date% and %time% do just what you think they do, echo the date and time.

The one thing that was missing, and I have no idea why, but when netcat first gets a connection it lists who is connecting to what ( connection to port 80) but it does not output that to the log file.
So this is the solution I came up with. It will work as along as only 1 connection happens at a time to the listener. It's not 100% reliable as if multiple IP's hit the sinkhole at once things will get weird.

for /f "tokens=3" %%a in ('netstat -ano ^| find /i "" ^| find /i "time_wait"') do set host=%%a

This does a netstat, finds the connection in time_wait (not established as the -w 2 disconnects before this part gets ran) to the listening server on port 80, parses out to find the IP and port that connected to it and sets it to the variable %host%.
Then with this
set host=%host::=#%
we change the ipaddress:port to ipaddress#port.
We can't delimit a : on a for loop, but we can delimit a #, that way we can run a for loop and grab just the IP address that connected.
for /f "tokens=1 delims=#" %%a in ("%host%") do set host=%%a
Now %host% is just the IP address.
Now we do another for loop with an nslookup to get the hostname, since the connection is internal we should be able to get the hostname from this:
for /f "tokens=2" %%a in ('nslookup %host% ^| find /i "Name:"') do set name=%%a

Next we do some date / time tomfoolery to timestamp our log file:
::set date
set dt=%date:~4,2%.%date:~7,2%.%date:~10,4%
*for my international readers: This part probably isn't going to work for you. Everyone does their date representation differently, this variable is based on the american method of displaying the date MM/DD/YYYY. You will need to adjust accordingly.

::set time
if %time:~0,2% LSS 10 set hr=%time:~1,1%
if %time:~0,2% GEQ 10 set hr=%time:~0,2%
if %time:~3,2% LSS 10 set mn=%time:~4,1%
if %time:~3,2% GEQ 10 set mn=%time:~3,2%
set tm=%hr%.%mn%
Time gets a bit squirrely also. we have to have the less than and greater than statements to handle hours and minutes less than 10. For example if it's 08:24.49 am and you try to set a variable to 08 it's going to just end up being " 8" and it's going to mess things up since there will be a space before the 8. Same thing for the minutes.

Next big thing we have is the BLAT command.
You'll need the BLAT executable and the blat.dll file in the folder with the script or in a folder that's in the PATH variable.
blat.exe %name%.txt -server -subject "HTTP Sinkhole Alert- %host%" -to youremailhere@domain.com -mailfrom sinkhole@domain.com

%name%.txt is the temp.txt file renamed, it's contents are used as the body of the email.
The rest is self explanatory use blat -h to see the help file. You will either want to create an internal relay connector in exchange to allow you to send the email or you can use authentication in BLAT.

Then we move the now named file to the OLD directory as a log repository. That part is optional and actually you can cut out a bunch of the script if you don't want it, like the time and date tomfoolery.

And that's that, we wait and see what connects to our listener.

Here's some action shots:

I've setup a wildcard sinkhole for blakhal0.com (not an actual domain as far as I know) on the DNS server.

Here we see the wildcard matching in action:

Here's a shot of the webpage the clients will get if they open a bad site in their browser (this is probably not going to happen often as most malware doesn't do things visibly in the browser)

And here is the email alert you get when something has connected to the sinkhole

I like it because you get the host they attempted to connect to (Host:virus.blakhal0.com) what URI they tried to go to, in this instance nothing, the date, time and what host the connection initiated from.
It will work for any URI on any domain you have sinkholed, so if they try and get /whatever/%20%20/evil.exe it'll log it. Then if you're feeling adventurous you can go get the exe and start examining it to see what would have happened, after you've put the kibosh on whatever is trying to connect in the first place.

From the 3 minutes I've spent looking at it it looks like you can use ncat for ssl connections so there's that to look forward to.

So for zero dollars you can have a reporting sinkhole for HTTP setup with Windows DNS. Enjoy.

<body bgcolor="red">
<h1>Welcome to the IT Sinkhole</h1>
You've arived here because the domain you are attempting to reach is currently listed as hosting malware.
An alert has been sent to the IT department.
Please send any additional information about how you got here to the IT department (it@domain.com)
Click here to send an email:<a href="mailto:it@domain.com?Subject=Sinkhole">Email IT</a>

No comments:

Post a Comment

All comments moderated.
Comments like "sweet dude" or "this is awesome" or "thanks" will be denied,
if you've got something genuinely interesting to say, say it. Other than that just sit back and bask in the glory.