3

Password cracking revisited

Sunday, March 7, 2010

About a year and a half ago my organization was looking at implementing a new password standard. At the time our password rules only required that user's password needed to be at least six characters long. Passwords were good for almost a year and there were no rules against re-using the password. The proposed standard would impose new hardships on our users but would also hopefully make our passwords more resistent to guessing and hacking. We had decided on a standard that required passwords to be at least eight characters long and required some combination of mix case, numbers, and symbols.

To test the new standard out, I took a sample of our passwords and analyzed the resistence of the sample when faced with a simple dictionary attack, an attack with some mutation, and a rainbow table attack. I covered my results here and here.

Well the months have gone by since we implemented the standard in January of 2009 and I decided that it was time to take another sample of our user's passwords and see if our new standard has created a noticable difference in our password strength. I had hoped to do this monthly and chart the trendline, but life got in the way of plans. I followed the same procedure that I outlined in the blog posts above to get a statistically significant sample that would give me a 3% margin of error and a 95% confidence interval.

I started with a simple wordlist attack using basic mutation. I used Cain & Abel to perform the attack and I used a John the Ripper word list called "all." For the mutation, I used the default settings in Cain & Abel. I was able to analyze the sample in about 15 minutes with this approach. In 2008 this technique revealed 313 of the 1027 hashes in the password sample, or about 30% (714). Now only 139 of the 1027 samples passwords were broken with this technique. We can report this as a 24% improvement in password strength or a 55% reduction in badness. Obviously I am pretty happy about this, and I think this really demonstrates that our new standard has resulted in higher-quality passwords.

Now I decided to run my anonymized sample through Ophcrack. With Ophcrack the complexity of your password matters less than it does in a dictionary attack. It only took ophcrack 2 mins and 23 seconds to crack as many passwords in the sample as Cain & Abel did. At the 30 minute mark 59% of the passwords in the sample had been broken. At the 60 minute mark 68% had fallen. When it was all said and done, 712 of the 1027 passwords had been cracked, or just over 69%. In 2008 when we did this analysis over 80% of the passwords fell to this kind of attack. If you remember, each of our samples has a margin of error of 3% so it is possible that there wasn't much of a change in the effectiveness of rainbow tables on our password database.

Still, for an outside attacker trying to gain access to user accounts, a password attacking tool might be the weapon of choice. So I feel good having improved things a bit. Now I can enjoy my weekend.

2

The Google Suckage Ratio

Monday, February 22, 2010

Sometimes we security people find ourselves in the uncomfortable position of having to buy software, services, or hardware to enhance our security. And in many cases we really don't know a whole lot about the vendors that we have to purchase from. Let's say, for example, that we need to purchase some vulnerability management software. There are some big names out there, like Nessus, Qualys, and nCircle but how do you choose which one to purchase.

I'm not going to go through the whole purchasing decision process. I would hope that part of your selection process involves developing a matrix of qualifications, assigning a weight to those qualifications, and assigning a score to each vendor. You should also put in some guidelines for each qualification so that multiple reviewers will give come up with roughly the same answers for the same product (inter-rater reliability).

One of the things that you might want to consider when you're making the decision is how favorably the company is viewed by others. After all, if the general consensus is that a company sucks, then you probably don't want to invest a big hunk of money with them. But how do you go about doing that? You can talk to a few friends of yours, but you're taking an awfully small sample to base your opinion on. You can also talk to references provided by the company, but there is going to be a high degree of selection bias in that approach. The approach I would like to consider is the Google Suckage Ratio.

It's dead simple the calculate the Google Suckage Ratio. Simply go to Google and type in a company name, like nCircle and look at how many results you get back. Now type the company name followed by "sucks." Take the total number of company sucks results and divide by the total number of company results and you get a Suckage ratio. You may be tempted to put the whole thing in double quotes, but I have found that you can get a staggeringly low number of hits. Instead we're going to look for the company name surrounded by a negative adjective.


CompanyCompany SucksCompany mentionsSuckage
nCirlce26,700189,00014%
Nessus156,00092100017%
Qualys20,100226,0009%
There are a couple more considerations we should make so that our measurement is more reliable. When we do these searches, we should exclude the names of the other vendors that we're considering. After all, it may be a discussion board where people agree that nCircle is awesome and that Nessus sucks. So I ran the searches again with exclusion. Here is a sample search string: Nessus -Qualys -nCircle. I have also found that if you reverse the order of the excluded terms you can get a different number of hits.

One question that was brought up when I was discussing this with some co-workers was whether or not we need to consider every negative adjective out there. Do I also need to search for 'Nessus Blows' and 'Nessus really sucks'? I decided that the answer is no because I'm really trying to compare these companies to each other using the same measurement tool. In other words, I'm not saying that 9% of Qualys users are unhappy, I'm saying that the ratio of bad press to total press is higher for Nessus, about 50% higher (9 divided by 17). In theory, if we added in company name blows then we would still see about the same ratio between Qualys and Nessus.

Now I'm not saying that I endorse this method yet, only that I am intrigued by the idea. I would love to know if this is pure crap that I am suggesting here. I would also like to point out that I am not the first person to suggest doing this, but I don't know who is. One of the things that gives it credibility is the fact that Google has indexed so much of the Internet. When you dip into Google you're taking a very wide sample of the Internet.

0

*nix command of the day

Wednesday, February 3, 2010

I'm going to do a series of blog posts on some basic security tools and how to use them in your environment. The school that I work for is going to be fielding a team in the Collegiate Cyber Defense Competition and I am very excited to be acting as an advisor to the team. So I thought I would put together a few tutorials, today is going to be the *nix command of the day, lsof. I also decided to put this on my blog because I don't believe in witholding information (even if it means that other CCDC teams might read this).

OK, so why do I think that any linux admin should know about lsof? Well the fact is you can't deter things that you can't detect, and lsof is an excellent tool for trying to detect weird network traffic, and possibly any malware that might be on your machine. This is also a valuable part of profiling your machine so you can write rules on your firewall to block unwanted traffic.

lsof stands for "List open files." Remember, on *nix, everything is a file, including network ports. Let's just dive in by opening up a command prompt and typing lsof. You might need to run this as root or use sudo to get some results. For this first run, let's pipe the output into head so we can see the begining.
OK, so in this photo you can see that the columns list the command and the process ID that has each file open. If you didn't pipe the output into head, you would see pages and pages of output listing everything that was open on your machine. Let's process that a bit with grep to find network connections. Don't forget the sudo or you wont see all of the output! sudo lsof | grep TCP
So looking at this output you can see that there is a process called dropbox that is listening on port 17500. That same process has some connections that are in a CLOSE_WAIT state. We wont get into what that means right now, except to say that it shows that at one time my machine had a connection to those IP addresses. You can also see that I have one connection that is established, which means that it is going on right now. There is also a process called cups that is listening for connections on the ipp port.

The listening port is what we're interested in. We want to know everything that is listening on the network, so that we can write appropriate Access Control Lists and possibly hunt down any rogue listeners. So let's run lsof again and grep for LISTEN.


As you can see, there are only two services listening for connections. Now to demonstrate, let's create a rogue listener and see the difference. I'm going to run this command in another terminal window: nc -l 9000. Then I'll run my lsof again. I'm going to spice up this command a bit so you can see the headers too.


Based on the information that you've got here, you should be able to figure out what services are running each of the connections. If there are any that you can't identify, then it may be an indication of malware that you need to investigate further.

0

How to identify Exchange 2010 Outlook Web Access logins from IIS logs

Sunday, January 17, 2010

Summary:

  • look for POST events in the IIS logs going to /owa/auth.owa

  • Make sure you've configured your web server and firewall to log to a logging server. Incident response begins long before the incident.

  • Even denied traffic on your firewall's external interface can be interesting.

I had an interesting bit of detective work a while back that I thought I would share with you. I had to sanitize the crap out of this story but hopefully it proves to be a good exercise in forensic work and scientific discovery.

Recently I was asked to look into a situation where some poor organization had been victimized over the web. Someone had visited their website and made threatening statements on an anonymous discussion form and they wanted to know if I could learn anything about the person who made the threats.

The first step in this (and probably any investigation) is to have a chat with your legal folks to make sure that it is OK to proceed. The person who made the threat was at a form that doesn't ask for a name so we need to ensure that there is no problem with trying to undo the anonymity. In this case the legal folks said we could go ahead because of the nature of the threat.

OK, so now we need more information about the source, and the first place I wanted to look was in the web logs. We know what time the posting was made and we know what page it was on so it was pretty easy to find the source IP address. This is where it really proves true that the first step in incident response happens long before the incident occurs. This organization has a process for saving web logs and a procedure that dictates how long the log files have to be saved. Going to the web logs, I ran a simple grep to find every IP address that had visited the victimized page: grep victim weblogfile.txt. I got back 42 results, and this is the relevant one...
192.168.1.1 - - [12/Jan/2010:23:26:09 -0600] "POST /security/victimizedpage.php
HTTP/1.1" 200 8106 "http://www.domain.com/security/victimizedpage.php"
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR
2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0;
InfoPath.2)"

So now we know that we're looking for 192.168.1.1. Obviously I've cleaned up the log files a bit, in truth it was some IP address out on the Internet somewhere. Next up I looked for other activity from that IP address. I also weeded out some of the stuff I wasn't interested in because it was making the results too cluttered to understand: grep 192.168.1.1 weblogfile.txt grep -v .css grep -v .png grep -v .jpg

There were a couple interesting things I saw here. For one, the person that posted the threat had been visiting the organizations web page all day long. This wasn't just a quick visit, drop off a threatening message, and leave. The person had been on the main page for a while, then over to Human Resources and a few other spots on the website. This happened several times throughout the day, but the threat wasn't dropped off until 11:26pm. The other thing that was interesting about the output was that the person had stopped by the Outlook Web Access page a few times. Make a note to check on OWA logins.

This organization also configures their Cisco firewall to log web activity. I decided that it would be worthwhile to check that out as well. Looking through the Cisco logs I saw a lot of activity from that machine to servers that are not open to the public. The results were again interesting.

This snippet (which is repeated often) shows that the machine had been trying to connect to the ldap port on all of the organizations domain controllers, which are not open through the firewall:
Jan 12 00:03:21 fw.domain.com %ASA-4-106023: Deny udp src
outside:192.168.1.1/62539 dst inside:172.16.52.10/389 by access-group "110"
[0x0, 0x0]
Jan 12 00:03:21 fw.domain.com %ASA-4-106023: Deny udp src
outside:192.168.1.1/62544 dst inside:172.16.52.109/389 by access-group "110"
[0x0, 0x0]
Jan 12 00:03:21 fw.domain.com %ASA-4-106023: Deny udp src
outside:192.168.1.1/62545 dst inside:172.16.52.108/389 by access-group "110"
[0x0, 0x0]
Jan 12 00:03:22 fw.domain.com %ASA-4-106023: Deny udp src
outside:192.168.1.1/62546 dst inside:172.16.52.1/389 by access-group "110" [0x0,
0x0]
Examining the logs further show that the person had many denied connections to internal services, but there doesn't seem to be any evidence of a port scan going on. It is possible that we could be dealing with a rather advanced attacker that was able to learn quite a bit about the internal network. However, it seems more possible that this computer may be a member of the organization's domain and have some hard coded values. Let's check out those Outlook Web Access logs.

The logs for Outlook Web Access are just the IIS logs, but since you have to authenticate to use OWA, the username sometimes appears in the logs for files that are in the secure area. It seems that the most reliable way to find login events is to search for POST events to /owa/auth.owa. Here is my example: unzip -c Exchange\ Logs.zip grep '192.168.1.1 ' grep -e '^2010-01-12' grep 'POST /owa/auth.owa'

There are a couple things you want to watch out for when you run these greps. First of all, when you're chaining grep statements together like this you want to make sure that you put the most restrictive grep first. The grep that will produce the fewest results should go first because then there is less work for your other grep statements. That's why the IP address is the first thing we're grepping for. Next, if you have a source IP address with a small number in the last octet, make sure you include a space after it or write a regular expression. Without it I would see results from 192.168.1.1, and also .12, .13, 101, etc. Here is a sampling of what I got:
2010-01-12 04:46:59 134.29.1.200 POST /owa/auth.owa - 443 user1 24.197.202.23
Mozilla/4.0+(compatible;+MSIE+8.0;+Windows+NT+6.1;+Trident/4.0;+SLCC2;+.NET+CLR+2.0.50727;+.NET+CLR+3.5.30729;+.NET+CLR+3.0.30729;+Media+Center+PC+6.0;+InfoPath.2)
2010-01-12 06:06:21 134.29.1.200 POST /owa/auth.owa - 443 user23
24.197.202.23
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506;+Tablet+PC+2.0;+InfoPath.2)
Two user names appeared, user1 and user23. I talked to the HR department and found out that there was a reasonable explanation for why these two users might have the same IP address. So we're in good shape, we now have two people of interest that we should interview to know more. But we can take it a step further. Check out the user-agent string that user1's browser sent and compare that to the user-agent string that was used to make the treat in the first place. It seems that they match! So between these two users, I think we are more interested in user1 than user23.

0

I has a sad...

Tuesday, December 29, 2009


Today I had to update the code on my beloved Sidewinder firewall, and with the new revision of code came rebranding. Now it doesn't even look like a Sidewinder anymore. It just looks as bland as the new name. "Secure Firewall." Meh.

0

Time-based alerts for snort

Monday, December 28, 2009

Snort is a very powerful intrusion detection system, and I've learned that when you combine it with a little kung fu you can do amazing things with it.  You can write incredibly granular alerts that will catch almost anything while minimizing false positives.  However, there is one thing missing in the alerting functionality and that is the ability to specify that some alerts only fire at certain time.

For example, let's say that you maintain a customer portal for your supply customers to order new shipments of some product.  You can expect that you will have customers hitting this page and trying to log during normal business hours so you probably wouldn't want to alert on that.  However, the same kind of traffic happening at 11:30 at night might seem suspicious.  At that time, events that might not be terribly interesting (like five failed logon attempts) suddenly become much hotter.

So how can we get time based alerts in snort?  Well there are two ways that I can think of and hopefully someone can think of a few more.  The first is the less-than-elegant solution.  You can write a script that adds a few rule lines to your local.rules file at certain times of the day and sends a kill -1 to your snort process so that it will reprocess it's rules files.  The advantage of using this process is that it is the simplest way of doing it. One way of doing it would be to have two different versions of your local.rules file. Then write a cron job that switches the two files and sends the kill -1 to the snort process. The disadvantage to this process is that it isn't very flexible. Let's say you want to ignore web activity between 8am and 5pm. Well that is pretty easy using this approach. But let's also say that on a different system you want to ignore activity from a block of IP addresses during a different time period. Now you would need to have three and possibly four versions of your local.rules file and your cron job would start to get pretty complicated. You would also need to make sure that you keep your script updated with the process ID that snort is running under. If you restart the service for some reason you're going to need to update your scripts. So I didn't like this approach.

Here is what I ended up doing to get these time-based alerts. I'll describe it in a nutshell, and then go into the detailed process. First, I set up a named pipe in the log directory that snort writes to. Then I created another type of rule called OddHours and told snort to write the alert for these rules into the named pipe I created. Then I wrote a python script that monitors the named pipe and takes an action whenever a new alert is found. It checks the day of the week and the time of day and then makes a decision to either send me an email or do nothing. Last step was to write the snort rules that I was looking for.

OK, so first is the named pipe. I have a lot of difficulty explaining what a named pipe is, but basically it is a way of sending the output from one program into another. For you command line linux types you probably do this all the time, like when you pipe the output of ps into grep to find your snort process ID.

ps aux | grep snort
That | symbol is doing the same thing as our named pipe, but it doesn't have a name and it isn't persistent on the file system the way our named pipe is. So let's create it:
mkfifo oddhours.csv


Now the custom alerts. In the snort.conf file that comes with snort, you can do a search for redalert and find an example of doing this. The custom alert is just a way of telling snort that for some alerts you want to react differently that you usually do. So I added this in underneath the redalert example:
ruletype oddhours
{
type alert
output alert_csv: oddhours.csv timestamp,sig_id,msg,proto,src,dst,dstport
}

So now if snort sees traffic that matches a rule that is written to use this custom ruletype it will send the time of thealert, the signature ID, the message, protocol, source and destination information into our named pipe.

This would be a bad time to restart snort if you're following along with me. The thing about named pipes is that you must have both ends of the pipe wired up for them to work. In the next step we'll create a script that "listens" to the pipe but if you don't have that script running when you start snort, then snort will sit there and wait for the script to start.

OK, let's dig into that python script. This is pretty easy. Just read a line of text from the named pipe and check what time it is. Right now the script is just writing to a log file, but I've put in the logic to send the email message that I ultimately want to receive.

import time
import smtplib
from email.mime.text import MIMEText
import logging

#######################
# Here is the logging setup stuff
#######################
LOG_FILENAME = '/home/kevin/oddoutput.txt'
logging.basicConfig(filename=LOG_FILENAME, level=logging.INFO)
#######################
# Here is the SMTP setup stuff
#######################
smtpServer = 'smtp.domain.edu'
smtpFrom = 'email.address@domain.edu'
smtpTo = 'email.address@domain.edu'

#######################
# Here i a function for sending alert emails
#######################
def SendAlertEmail(inMessage):
logging.debug('\tSending Email alert')
msg = 'Snort has detected activity at an unusual hour.\n'
msg += inMessage
msg = MIMEText(msg)
msg['Subject'] = 'Activity at an unusual time'
msg['From'] = smtpFrom
msg['To'] = smtpTo

s = smtplib.SMTP(smtpServer)
s.sendmail(smtpFrom, smtpTo, msg.as_string())
s.quit
logging.debug('\tMessage sent.')


infile = open('/home/kevin/snort/logs/oddhours.csv','r')
while True:
data = infile.readline()
if data:
logging.info('Line of data received.')
logging.debug('\tChecking if it is Saturday.')
if time.strftime( '%a' ) == 'Sat':
logging.critical('\t\tIt\'s Saturday! ALERT ALERT')
logging.critical('\t\t'+data)
#SendAlertEmail(data)
continue
else:
logging.debug('\t\tNope. It\'s '+time.strftime('%a'))
logging.debug('\tChecking if it is Sunday.')
if time.strftime( '%a' ) == 'Sun':
logging.critical('\t\tIt\'s Sunday! ALERT ALERT')
logging.critical('\t\t'+data)
#SendAlertEmail(data)
continue
else:
logging.debug('\t\tNope.It\'s '+time.strftime('%a'))
logging.debug('\tChecking if it is early in the morning.')
if int(time.strftime( '%H' )) <= 7:
logging.critical('\t\tIt\'s Early. ALERT ALERT')
logging.critical('\t\t'+data)
#SendAlertEmail(data)
continue
logging.debug('\tChecking if it is late in the day.')
if int(time.strftime( '%H' )) >= 17:
logging.critical('\t\tIt\'s Late. ALERT ALERT')
logging.critical('\t\t'+data)
#SendAlertEmail(data)
continue
logging.debug('\tPassed all tests.')
logging.debug('\t'+data)


OK. Last thing we need to do is write some rules that make use of our custom ruletype. In this example, I want to see web surfing that happens on Saturday or Sunday or outside of the normal work day. So my rule is going to look for anything on my home_net that is going to port 80 or 443 with the Syn flag set. Keep in mind that I wouldn't do this on a production system unless you want a lot of email or you're sure that this doesn't happen. I'm using this example because it fires a lot of alerts and lets you check right away if your rule is working.

oddhours tcp $HOME_NET any -> any 80 (msg:"Surfing at an odd hour."; flags:S; sid:2009122301; rev:1;)
oddhours tcp $HOME_NET any -> any 443 (msg:"Surfing at an odd hour."; flags:S; sid:2009122302; rev:1;)


OK. Now we're ready to fire the whole thing off. First, start up the python script and set it to run in the background: python oddhours.py &

Then fire up snort and start watching the output file. You can change the logging level so that you can get more or less information from the script if you want to do some troubleshooting.

Later on down the road, you can create functions for each sid that you want to monitor. When a line of data comes in you can pass control over to the function that you've written for that sid. That way you can have different time-based rules for each sid. It would also be pretty easy to expand the script so that you could send email alerts to different people based on the sid.

And hey, if you know a better way to do this then please hook me up with the answer. I'll gladly post it on my blog and give you all the credit.

0

Don't cry over spilled COFEE

Thursday, November 12, 2009

This morning I was looking at my Information Technology daily news feed from Infragard, which is supposed to be sensitive information but only ever contains links to public web sites and a brief discussion of the link. Anyway, in this morning's edition there was some discussion about Microsoft's COFEE being leaked into the wild and a link to this article:http://www.darkreading.com/security/vulnerabilities/showArticle.jhtml?articleID=221600872. Generally there seems to be terror surrounding the release of this tool. Here are the two money quotes:

"the danger is that a detection tool will be written for COFEE so that the bad guys can cover their tracks."

and
"One researcher who got a copy of COFEE online says bad guys could abuse the tool by taking one of its Dynamic Link Libraries (DLL) and loading it into a compromised machine’s memory, where it then dumps stored clear-text passwords to a file."

I believe these feelings are being expressed by people who probably don't know much of the fundamentals of forensics or information security. I could see this being very disturbing news for a law enforcemet agent that doesn't know anything other than "insert this magic USB stick into a computer and magic happens and you get the stuff you need."

Sure, somebody could write a rootkit that watches for COFEE and starts trashing evidence, and it probably will happen before too long. So what? Many of us use DD to image the memory on a computer and the same threat has existed for us, and we're not freaking out about it. If malware writers started to do that, they would just end up on the same hamster wheel that anti-virus writers are on. Today your malware can detect COFEE so we pack the code differently. Now your malware has to detect two signatures for COFEE. And so on, and so on, and so on.
And so I find myself in agreement with Microsoft's Richard Boscovich, an attorney in the Internet Safety Enforcement Team.
"we do not anticipate the possible availability of COFEE for cybercriminals to download and find ways to 'build around' to be a significant concern..."
Unfortunately, that quote didn't make it into the Infragard summary of the article, which is too bad because I think that is the money quote. Here is the next best quote from the article:
"COFEE was designed and provided for use by law enforcement with proper legal authority, but is essentially a collection of digital forensic tools already commonly used around the world. Its value for law enforcement is not in secret functionality unknown to cybercriminals -- its value is in the way COFEE brings those tools together in a simple and customizable format for law enforcement use in the field."

The second quote from above is what really steamed my broccoli; the one about dumping clear text passwords by loadingg a DLL into memory. Obviously there are the security problems about any program that is keeping passwords in clear text, and users should be purging themselves of such software. Mainly thought, I feel like that functionality is actually exploiting a vulnerability in Microsoft's code and should be patched. Seriously, if such functionality exists (and I'm not positive that it does) this should be considered a major security flaw. Unfortunately I can't give you an educated opinion on this because I'm not a law enforcement agent and so I can't see the secret program. Here is a decent write up of what it can do: http://praetorianprefect.com/archives/2009/11/more-cofee-please-on-second-thought/

Verdict: everybody chill out. No big deal. Nothing to see here. Move on.