Logo




Subscribe:
RSS 2.0 | Atom 1.0
Categories:

Sign In


[Giagnocavo]Michael::Write()

 Sunday, April 11, 2004
How to protect your Windows NT hashes

So I've been worried that the NT password hashing calcuation is: MD4(passwordInUnicode). Yes, that's right. No salt or anything. As you might be imagining, this is bad. I was wondering how this can be mitigated, short of extra physical security (smart cards, for instance). I found that there is a way to cipher the passwords on disk: SYSKEY.

SYSKEY is running by default on Windows 2000+ machines. Basically it encrypts the password hashes with RC4, meaning the attacker must break the RC4 encryption. However, by default, SYSKEY runs in Mode 1, which stores the RC4 as an LSA secret, so it's trivial to get it out. So, if someone has physical access to your machine, SYSKEY doesn't do much.

However, there are additional modes. These allow you to use a password to derive the RC4 key. The password must be entered when the machine starts up. The other mode generates a random RC4 key, and stores it on a floppy disk. The floppy must be present when booting.

To enable these, just run SYSKEY (Start -> Run: Syskey). Select the mode [and password]. Enjoy a more secure computer.

Security
Sunday, April 11, 2004 5:59:06 PM UTC  #    Comments [0]  |  Trackback

VS2005 - Just a small cool feature

I was just opening up some of the BCL code in VS2005. Wow, do I love this product. I just noticed some new things on the document tabs:
  “Close all but this”
  “Show File In Explorer”

When I've got a lot of files open that aren't part of a solution (like the framework sources), that last item is really nice. As is the former item, as you can imagine. Now if I could just get the tabs to open in the right order -- the tabs are organized by some kinda MRU system, which I find rather annoying.

Just 3 out of 10 million new things in the new IDE. Got a cool tip/trick (or a change you dislike) for the Community Technical Preview? Leave a comment.

Misc. Technology
Sunday, April 11, 2004 4:05:23 AM UTC  #    Comments [1]  |  Trackback

 Tuesday, March 30, 2004
Why you should hash a lot

So, why do we care about multiple iterations, good salting, etc.? Isn't a simple MD5 hash enough?

http://www.whitehat.co.il/forum_viewtopic.php?14.149

Yes, that's right. Rainbow tables (almost 120GB in total), so that passwords like “!BinM,$YuSt.b7“ can be easily cracked -- If you are using LM hashes. The newer NT hashes don't have this problem yet.

That's another thing to consider when determining password strength requirements. Normally we can say “Oh, doing n steps will take at least x time, and passwords expire in x/16 time, so we're safe.“ However, if our apps are designed in a way that allows someone to precompute an attack and make a time tradeoff, our password strength versus time no longer means anything.

Update: Edited article because as far as I can tell (they won't answer my inquiries) these tables do not attack NT hashes, only the weaker LM hashes (no surprise).

Security
Tuesday, March 30, 2004 3:42:29 AM UTC  #    Comments [0]  |  Trackback

 Thursday, March 25, 2004
Storing passwords and hashing

I see a lot of articles on hashing passwords, however many of them skip over an important part of setting up this kind of system: iterations. But first, a quick primer on hashing in general.

Hashing is a cryptographic function that takes variable-length input, and creates a constant-length output. The output is commonly called a hash, or a digest. The most common algorithms are MD5 and SHA1. MD5 creates a 128-bit hash, and SHA1 creates a 160-bit hash. There are also SHA256, SHA384, and SHA512, although 384 is pointless, since it's just the SHA512 with some data discarded. It's computationally unfeasible to find two plaintexts that have the same hash output. Hash functions are used in some common scenarios:

1: Creating a digest of a message to ensure the message was not modified (intentionally or unintentionally). Sometimes this is referred to as a checksum. eDonkey is an example that uses MD4 hashes to identify files (and as files are downloaded, they can be checked to be good by computing the hash).

2: Digital signatures, where the hash is encrypted with a the private key of an asymmetric algorithm (like RSA). This can then be decrypted by anyone with the public key, and checked against the computed digest to ensure that something with the private key did “sign” the message, and that the message contents have not changed.

3: Securely storing passwords. Since a hash is a one-way function, it's impossible to *decrypt* the hash and retain the password. Well designed systems will not store plaintext passwords (otherwise someone who reads the database could get your password and do nasty things as “you”). If you ever use a site that sends your current password back to you if you forgot it, then they most likely have a badly designed system (and you should question the rest of their security).

We're going to focus on the password issue. Attackers can figure out a password by computing the hash themselves for a suspected password, then comparing to the actual value. So, while the hash value might be 160-bits, it certainly doesn't take 2^160 steps to find the right password, since many users use weak passwords.

When hashing a password, it's common to add some random bytes to the password that are unique for the user. This is called a salt, and it ensures that for each user has a different hash, even if the password is the same -- since hash(”password”) will always return the same, but hash(”password” + “randomData”) is going to be different. This means that an attacker must compute a separate hash for each possible password, *per user*. This helps stop an attacker from trying to attack all the users at once, since each additional user requires a complete attack (since there's a salt).

However, lets say that the attacker is going after a specific user. If the user picked an easy password, say 6 alphanumeric chars, the password's strength is ~36 bits (35.7 to be more precise, 5.95 bits per char). This is assuming completely random characters are used, which is hardly ever the case. That's not that much work for a attacker, and we're considering 64-bit security (128-bit keys) to be the “required security” level.

However, suppose instead of calculating one hash per password+salt, we take the hash, and re-hash it n number of times, where n is something between 2^14 and 2^18? Well, now the number of steps required per password goes up that much. The 36-bit password now has an effective strength against brute forcing of 2^50 to 2^54. Essentially, by adding 2^18 steps to the hashing, we've added the equivalent of 3 *random* characters to their password.

So, do you need to iterate? Find out your minimum security level (48-bit? 56-bit?). Figure out how many iterations you can perform on your hardware before performance is unacceptable (probably between 2^14 and 2^18). Subtract that from your required level, and you have the minimum password entropy level.

For instance, let's say that I want to have 64-bit security from my passwords. My hardware can do 2^16 iterations without hurting logon times, thus I need 64-16= 48 bits of entropy in each password. This can be accomplished by requiring passphrases consisting of four common words (say a dictionary of 4000). (12 bits per word = 48 bits in the password + 16 for iterations, and I'm set).

Hashing is even more important when you don't have control of how good the passwords are. For instance, you're saving customer's credit card data, and the key is based off their password (so that they MUST login for your system to access that data). In these cases, requiring a complex password might not work for various reasons such as customer pushback, or risk of customer choosing something like your site name or their name as a password. It's important to determine the level of password complexity that will “push users over the edge” - the point when they stop using something remotely random, and start using things like their last name, their SSN, etc. When that point is reached, the entropy of their password is uselessly low.

Now, assuming a semi-casual attacker with a strength of 40 bits. He's got the power to do 2^40 steps of computational work. If your users use 24-bit passwords, their hashes can be broken by this attacker easily. But, with 2^18 iterations, those weak 24-bit passwords now require 2^42 steps, and the hash is saved.

So, there is really no good reason not to do multiple iterations. Even 1024 will provide some strength (equivalent to 2-3 extra characters in the password). In fact, the .NET framework already has a class that does all of this (hashing with whatever algorith, salting, and iterations) for us: System.Security.Cryptography.PasswordDeriveBytes. Use it!

Code | Security
Thursday, March 25, 2004 4:06:06 AM UTC  #    Comments [1]  |  Trackback

 Wednesday, March 17, 2004
Easy on your eyes

I just got to Atlanta, and the next morning, UPS showed up with my new Sony SDM-S73/B, a wonderful 17” LCD panel (analog). Wow. I've been using CRTs for 18 years, and my eyes hurt.  This panel is such a welcome relief!

Big benefit: no refresh.  I'm really sensitive to refresh rate, and pretty much any CRT running at less than 85Hz gives me a headache within a few minutes. Even though this panel runs at only 75Hz, the way that LCD works means that you don't notice it. It's a solid display that's just... there. Feels like it's just painted on.

Another big benefit: low output. Every CRT I've used, I feel like there's a lot of energy coming towards my eyes. It's a lot to handle, and it's hard on them, thus my articles on using gray. This Sony display has a great “Eco” button that flips between energy levels (both in consumption and output). Thus I can keep my display as low as possible throughout the day and night, and save energy too.

Another nice thing is that the stand makes it very simple to move up and down, so as I change my sitting (slouching?) position, I can make sure I'm straight-on, which is best for ClearType reading. ClearType really makes text look better. Windows Media Video HD looks spectacular on this display. It has a 160-degree viewing angle, so a few people can sit around and watch too.

TigerDirect has them for $450, which is about $50 cheaper than anywhere else I found them.

Misc. Technology | Personal
Wednesday, March 17, 2004 7:10:13 PM UTC  #    Comments [3]  |  Trackback

Lame: Cyberlink PowerDVD 5.0 Multilingual

I tried out Cyberlink PowerDVD 5.0.  The install program displayed all its text as question marks and garbage text.  This normally happens if a font doesn't support extended characters (you get ?? instead), or if codepages don't match up (they don't use Unicode, and instead use a DBCS, which gives all the wierd looking garbage on my codepage).  Why, oh why, would a program that's supposed to be “multilingual” mess this up?

Turns out, my formatting settings are set to Korean.  Everything else is currently in English (debugging cryptic Javascript errors in Korean was too hard).  So the PowerDVD software decides that if my formatting settings are for a certain region, I must be using that language.  See the jump in logic?  Changing my regional settings to English (United States) makes it all good again.  Who codes this stuff?

Misc. Technology
Wednesday, March 17, 2004 6:41:52 PM UTC  #    Comments [0]  |  Trackback

 Thursday, March 11, 2004
Packing up and shipping out

Well, I'm moving to Atlanta tomorrow (with a few day stop in Miami).  It's rather sudden (only decided about 2 weeks ago).  As I try to pack up everything I have, I'm amazed at how much stuff I have that's just sitting around.  I'm destroying ~500 CD-ROMs and DVDs (old backups, beta CDs, etc.).  I've noticed that MSDN contributes quite a bit to this (because MSDN Latin America refuses to send just English, but insists on sending all sorts of localized versions that I'm never going to use (because I have MUIs!)).

On the other hand, there aren't that many things I'm taking (a few suitcases is all of my stuff).  Apart from my CPU case, the largest thing I have is my Go board.  Makes me wonder why I keep so many things lying around. 

Anyways, does anyone have any hints for a .NET MVP getting into Atlanta?  I'm looking for apartments (2BR) in Midtown... we'll see how that goes.  If any other .NET people are interesting meeting up sometime for a drink, let me know.  I hope there's a good local user group in Atlanta...

(Yes, because of this I won't be posting anything substantial for a bit.)

Misc | Personal
Thursday, March 11, 2004 7:10:36 PM UTC  #    Comments [2]  |  Trackback

 Monday, March 08, 2004
Nothing is secure

One thing to keep in mind is that nothing that I know of in this world is secure.  I'm not just talking about software.  Dictionary.com defines secure as “free from danger or attack”.  Can you think of ANYTHING that meets that definition?  Leave a comment and win a prize if you can.

Security is about probabilities.  “How secure is X?” is often asked.  Does that mean if we use ultra-high encryption that it's impossible for someone to break through?  If I chose a 256-bit key right now and encrypted my data with it, is my data secure?  Remember, it's *possible* that someone could guess a 256-bit key in one shot.  The probability of that is usually extremely low, although if I picked a key of all zeros a system might try that to start off and thus win in one turn.

So, when choosing your defenses and making your tradeoffs, always consider the probabilities of a certain attack occuring.  Wasting time “bulking up” defenses in one area while ignoring weaker areas is like optimizing code that isn't slowing your system down: pointless and a waste of time.  You will never have something that's “secure”.

Code | Security
Monday, March 08, 2004 6:48:27 PM UTC  #    Comments [0]  |  Trackback

Cracking code - Part 2: Other simple attacks

In part 1, we attacked the code by stopping it at a known point, the “invalid code“ message box.  From there, we were able to trace up to where a decision was made as to the validity of our serial/code, and change that logic around.

Going through someone else's compiled x86 code can be somewhat like going through your server's logs to find some specific information.  Most people don't start with log entry 0 and read each one.  We filter the logs, look for error entries, etc.  Depending on what we do know about the events we are looking for, we can find the related entries in different ways.  The same applies when going through code.  Here are two other simple things that we could do to SimpleCode.exe to break it:

Strings
We could search for all strings, and then look for “good“ strings, something we'd expect to see when our code is valid.  OllyDbg can dump these strings and search them, and then take us to the places where they are used.  From there, we can track up and see where/why that code wasn't called.

Our input
Every program needs to take our input, then somehow validate it.  If we enter some data that's easily recognizable (like “AAAA”), we can set a breakpoint on memory access to that location.  From there we can figure out what's being done to our input, which is useful for reverse engineering -- creating a “keygen”.  Having a keygen is much more valuable, because we don't need to make binary patches and modify the executable.  Between different versions of the software, the key validation will probably remain the same.  If we know how to generate our own keys, we have a “one size fits all” attack.

Code | Security
Monday, March 08, 2004 6:01:59 PM UTC  #    Comments [0]  |  Trackback

Vault - great source control

I just found a great product, Vault.  Vault is a source control system written entirely in .NET.  The main advantage of it is that it's easy-to-use, and also important, easy-to-setup.  I tried using VSS, really, I did!  But wow, it's really poor.  Getting things working correctly even on my local machine was a pain, not to mention on the LAN or over the Internet.  Vault took all of 5 minutes to install on an Internet-based development server, and works quite well -- as well as anything that has to interface with VS.NET can.  As well, if you're just looking for a system for your local machine, it's free for one user.  Very cool!

Code | Misc. Technology
Monday, March 08, 2004 5:36:33 PM UTC  #    Comments [0]  |  Trackback

Who do they think they are?

http://www.korea.net/menu/government/newscontent.asp?Number=20040307006

Last time I checked, this wasn't part of the states.

Misc
Monday, March 08, 2004 6:25:33 AM UTC  #    Comments [0]  |  Trackback

 Sunday, March 07, 2004
I've been Scobleized!

Scoble linked to me!  Around 2AM or so.  And now by 11AM, I've had over 500 visits (and some new subscribers)!  And this is on a Sunday.  Very cool.  Time to turn on the caching.

Personal
Sunday, March 07, 2004 5:07:35 PM UTC  #    Comments [1]  |  Trackback

Fixing dasBlog with intraVnews

I use intraVnews (www.intraVnews.com) to read RSS feeds.  It's free, and most importantly, it's integrated into Outlook.  However, I was having trouble getting intraVnews to read my blog's RSS feed.  I emailed intraVnews support (which is VERY good) and found out that intraVnews DOES have a problem with some dasBlog feeds.

The issue is that intraVnews sends an HTTP HEAD request to the RSS feed first, to see if it has changed.  A HEAD request is just like a GET, except that only the HTTP headers are returned.  Well, dasBlog uses a web service (.ASMX) to render the XML.  ASP.NET doesn't allow HEAD requests to ASMX files and will error.  If you have customErrors on (I think this is the default for dasBlog?), instead of a 500 internal service error, you get a 302 Found -- a redirection to an error page.  intraVnews then decides to throw this out.

Just by turning customErrors off in the web.config, the normal HTTP error will be returned, and intraVnews treats this just fine.  Thanks to intraVnews for pointing this out, and Rex Swain, for his cool HTTPView page, which lets you see exactly what's coming back in an HTTP response.

Misc. Technology
Sunday, March 07, 2004 5:01:25 PM UTC  #    Comments [0]  |  Trackback

 Tuesday, March 02, 2004
Cracking code - Part 1

Update 2004-03-07: Added screenshots.

Read the intro to find out why I'm writing this.

Alright, before we get into attacking .NET, let's see how it's done against common Win32 programs in x86.  First, you'll need a good disassembler/debugger.  I recommend OllyDbg.  It's very easy to use, and does a good analysis of the code, which helps us out quite a bit.  SoftICE is another alternative, but it's low-level, harder to use, and it costs $1000.  People tend to use this when they want to debug something like a device driver, or make a patch for Windows.

Here's the executable I wrote for this sample: SimpleCode.exe (44 KB) and if you feel like cheating, the source code: SimpleCode.cpp.txt (1.28 KB).  It's very simple.  In fact, the whole purpose is to validate the user code -- there's no real content that's protected.  However, it will be enough to learn from.  Also note that it only runs on Windows 2000 and above.  If you aren't using that OS, upgrade :), or get the code and fix it, or email me for a version you can use.

So, let's open OllyDbg and make sure the analysis options are on (Alt-O, check all of them out).  Now, load SimpleCode.exe.  OllyDbg loads and disassembles the code.  You now have a console window open, and a bunch of x86 on your screen.  Let's run through the program (F9).  Enter 4 chars for your serial, and 4 for your activation code (no checking is done, so you'll screw up the program if you enter more data).  A message box appears telling us the code is invalid:


That's our way in, for this example.  We know that somewhere before the message box was shown, our activation code was tested.  So, let's go breakpoint at the message box.  Restart SimpleCode (Ctrl-F2).  Right click in the main window and select Search for -> All intermodule calls.  In the new window, type MessageBox.  You'll see two calls to MessageBoxA.  A real program would have many more.  Right click one of the calls and select “Set breakpoint on every call to MessageBoxA”. 


Run the program and enter fake serial/activation again.  The program breaks at “00401163  |.  FF15 DC804000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA“.  If we look up a bit, we can see that the arguments loaded are for the invalid serial.  This is the message box we want.  Go into breakpoints (Alt-B) and disable both breakpoints.  Now, the opcode right after the MessageBoxA call is C3, RETN, the end of the function.  Considering the code for this function is very short (21 lines), it should contain only the “bad” code -- code we don't want executing.  Press F8 to step over that call.  Dismiss the message box.  Notice you can press “;“ to add comments to lines.  It'd be good to mark this line with something like “Return from displaying bad message box.“, just in case we get lost later on.  In many programs, there will be many interesting points, so good commenting is key.


If you're going to be doing real attacking, you need to learn some X86.  Important things are CALL, RETN, the various jumps, and comparisons.  Because most likely, somewhere inside your target program, a check is performed and then a corresponding action is taken.  If we can reverse the logic, then we can make the program think correct data was entered when it wasn't (and the opposite: correct data will be considered incorrect).

Now we're about to return to the point that called this function.  Press F7 to see where that takes us.  Now we're on “00401274  |.  8B4C24 3C     MOV ECX,DWORD PTR SS:[ESP+3C]“.  The line above that is the callsite of the “bad display function“.  Comment it as such.  Look around.  OllyDbg should display some arrows indicating jumps and targets.  If it doesn't go into debugging options and check your settings. 

Notice that the callsite of the bad function is a jump target from “00401259  |. /74 14         JE SHORT SimpleCo.0040126F“.  If we take the jump, we end up calling the bad function.  If we don't we RETN (look at the line right above the bad callsite).  Sounds interesting.  Set a breakpoint on that JE instruction, restart, run and enter the data.


JE means “jump if equal“.  It's opposite is JNE (jump if not equal).  Our program is stopped right now at a JE, and OllyDbg says the jump will be taken.  Since the jump goes someplace bad, we don't want it to happen.  Press space.  This opens the reassembler.  Change the JE to JNE and press assemble.  OllyDbg patches the in-memory executable. 


Let's see what happens.  If we're lucky, this will call the “good“ code.  If not, we just patched something else and the program at the best is going to do something strange, but most likely will crash and burn.  Press F9.



What's that?  Thanks for activating?  Why, you're quite welcome!  That jump did it.  Wasn't that easy?  And we didn't have to learn much X86 at all.  To save your changes, we'll need to restart (OllyDbg will complain since the breakpoint code was patched and changed) and goto the breakpoint and re-patch.  This time, right click and select “Copy to executable -> All modifications”.  Now we've got a patched program.

This was extremely easy (it was a very simple program!), and just demonstrates one way that someone could attack your code.  It's also an inflexible attack (a binary patch, versus finding the algorithm), so if a new version is released, we need to debug and patch it again.  Hope you learned something!

Update 2004-3-8: Part 2 now available.

Code | Security
Tuesday, March 02, 2004 7:20:18 PM UTC  #    Comments [7]  |  Trackback

Cracking code - Introduction

To defend, you must have some idea of what you're defending, and who and what you're defending against, specifically, which attacks.  Failure do understand and know these things means that your defense will most likely not be effective, and could in fact decrease your security.  Here's an example:

Near where I live, thieves were stealing cars that people parked in the street.  The neighbourhood committee decided that they'd stop this.  The solution they implemented was to put gates at all entrances and exits of their area, and have guards that only allow cars with a particular sticker get through.  This makes people FEEL more secure.  However, for the cost (guardhouses and gates construction, guard salaries), it's not as effective as it could be.  A thief can still walk in just as easily (gates only block roads), and when driving a stolen car out, the guards will see the car and sticker, recognize it, and let them leave.  If they had thought about how thieves operated, then they would have realised this and done something more effective, perhaps hiring the same number of guards, but setting them on a patrol, instead of just sitting at their posts.  With unlimited resources, they could do both things, and give each member a special remote key-code to unlock the gate when they are driving.  However, the tradeoff in cost and convenience is too high for them.

This is how security is, in the physical and electronic worlds.  We have many possibilities, each with their tradeoffs.  Deciding which measures to implement requires us to understand how our opponent is going to operate, as well as the details of how exactly our defenses work.

In this series, I'm going to show you how to crack simple code.  I'm going to make a series of samples to try this out on (to avoid DMCA problems with real code), so as to get a feel of what crackers do to code.  It is not going to be in-depth or show how to become a master cracker.  Just enough so that we could attack a simple Windows/.NET program's licensing key system, which is a common theme in software protection.

Continue to Part 1, where we'll crack some simple code...

Code | Security
Tuesday, March 02, 2004 5:26:40 PM UTC  #    Comments [5]  |  Trackback