Monday, July 13, 2009

Why Software Certificates Aren't a Second Authentication Factor

Two Factor authentication is better than one. It is a requirement for some systems that need to be more secure, such as PCI covered systems. What does this actually mean and why is it more secure?

Two-factor authentication means that you have authenticators from to different classes of authenticator:

  1. What you know, like a password or pass phrase.
  2. What you have, like a OTP Token or a smart card.
  3. What you are, like a fingerprint, voice print, keystroke rhythm.
These general definitions are generally accepted by all. Let's go a step further and look at what they actually mean, and what the intent is. What are the kinds of attacks against a specific authenticator.

Why would you even want a second factor and why from a different class?
We don't want more security! If we use a send factor, an attacker has something else to get in order to impersonate the legitimate user. However, if the user can get the first factor, then you surely don't want to use one just like it. Different classes of authenticators have different threat models, attack vectors and vulnerabilities. If the attacker can steal one password, they can surely steal a second. They just do what they did, for a bit longer.

If an attacker has to somehow get my password and steal my physical token without me knowing, that's a tall order. You can get my password remotely, but you have top travel and sneak to get my token. On top of that, I carry a Spyderco Delica. That's how I spell compensating control.

The intent of the "what you have" factor, in my opinion, is that the authenticator be a physical object that can not be easily duplicated. This maintains the threat model and the Spyderco control. The "what you have" factor should be hard to copy even if the legitimate owner is colluding. "Here, have a copy of my certificate and private key", should not be an option. If the what you have can be transmitted electronically, it's not a true what you have.

Software certificates and the corresponding private keys, that are stored in some sort of non-volatile storage, i.e. your hard drive. I'll focus on windows boxes, as I can speak very accurately about them, but the following is true with any OS. If the users have physical access to the computers, then they can get admin rights, which means that they can get the private key for the certificate. Don't believe it... Remember, if you have physical access to the box, you own the box. Did you think that your whole disk encryption product could protect you? Take a look at cold boot attacks.

Once you have admin rights, there are two methods to get the private key. The private key is stored in the registry and file system. It's obfuscated a bit and protected with DPAPI, in the machine context. This means that an admin can export the private key. Wait, you've marked the private key as not exportable! Remember, the admin owns the box. The key is there, a piece of code is just telling the system to not hand it over. Let's look at C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\My\Certificates and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\My\Keys
These are all linked together to protect you from getting the key. If we take a look in one of the key files, we see an Export Flag. In this case, local software is reading that flag and choosing whether or not to respect it. Once could just use a little magic and pull out the key. Enter the ninjas at ISEC Partners and their Jailbreak. Give it a shot, and you will see that you can export the key!

So, if the user colludes, copying the software certificate is trivial. If the user is just negligent, the attacker could ghost (clone) the drive and then get access later. If the user is negligent, but uses a good full drive encryption product, the attacker will need some time with the computer to get the key.

Protections of Certificates and Keys That Work
My examples above are related to machine certificates. Those are the only ones that can be used for IPSec, in most cases. If your user does not collude with the attacker and cant' be tricked into running their attack code, (that seems unlikely, users will click on anything) then user certificates are secure. Why? User certificates are protected by DPAPI in the user context. This means that they private key can only be decrypted if the user has typed in their password. The system does not escrow the key for the user, the user's private keys are protected with a key that is derived directly form the password using PKCS 7. If the actual password is not available, their is no way to recover the key. In a workgroup, this is absolute. If the machine is domain joined, an administrator of the domain can reset the user's password and reconnect the machine to the domain and the key can be recovered. Collusion by your domain admins is a whole lot more worrisome than your user.

Whole disk encryption that requires keys stored on a smart card or token can stop most attacks. The problem with most whole disk encryption implementations is that they are not actually secure. They just keep the dumb and honest honest. If you can boot the PC without entering a pass phrase or insert a token, then your disk encryption keys are stored locally and can be accessed by your boot loader. This means that it's just a matter of understanding how that works to get the key, or one can let the machine boot and then use the cold boot method to get the key from RAM. Use real encryption, get a token or smartcard!

One could also use SYSKEY in mode 2 or 3. This encrypts some of the SAM using a key that is derive from a password or on a floppy disk. Neither of these is particularly manageable on an enterprise scale. Most users will leave the floppy in the drive and the password has no rotation policy. Either you have to track it per PC or have a universal password for your org, which will surely get out.

So, if you have a software certificate and private key, they are electronic assets with many avenues that can allow an attacker to copy and electronically copy and transmit them. While the attack vectors for getting the private key differ from getting the user's password, the spirit of "something you have" is not met by a software certificate. This is not to discount the value of software certificates in many situations, they are great. I simply am making the point that they are what they are and one should never forget.

Thursday, June 25, 2009

Sniffing the Unsniffable

In a previous post I covered how to export a private key to decrypt SSL traffic in Wireshark. This is dandy, as long as you have access to the private key.

What do you do if you don't have access to the private key??? Perhaps you are using a windows box and the certificate policy is set to not allow the export of the private key. Yes, a super ninja can take it, if they know enough about the file locations and DPAPI, but it's hard. Maybe I'll cover that soon. What if you are the client and the server is some commercial service? You'll never get that key.

If you are on a windows host, you are in luck! Enter my new best friend, STrace, from Microsoft. STrace uses MS Research's amazing tool, detours. I'll avoid a huge digression and just say that detours is crazy awesome. It intercepts win32 functions in memory and allows the code to be altered on the fly. That's right "re-writing the in-memory code for target functions". Yikes!

STrace was written for something other than our purposes. It's meant to be used in conjunction with HTTPREPLAY. This allows of debugging a web browser session over and over, without the server. Booooorrrriiinnnggg. Actually it's very cool, but not for us.

One of the things that STrace does for us, to support its original goes, is to inject itself into processes that are using SSL. You simply find the PID of the process and inject the DLL and you get your data out, unencrypted. The data is in a format designed for HTTPREPLAY, which is only a bit of a pain.

Going for the Gold!
If you've ever dealt with LDAPS failures in AD, you know how tricky they can be. You can only watch the SSL negotiation, then you lose out. If the issue involves a lying crappy vendor of a developer who just read about LDAP when the project started, you always want to look at the data they are sending. LDAP on the wire never lies! Too bad that by default, the Domain Controller Certificate Template is set to not allow export of your private key. If you're like me, you may have the party turn off SSL and suddenly it all works. Hmmmm... We must see what is really being sent!

First off, the strace readme.txt is full of awesome and it's short. It's worth a once over.

The first step in the process is to figure out which process is our LDAP SSL server. We know that SSL for LDAP is on port 636, so we run netstat -b -n -a to get the list of ports and their process names and the PID

That gets us this:
TCP 0.0.0.0:636 0.0.0.0:0 LISTENING 428
[lsass.exe]

Now we know that LSASS is the process and the PID is 428. LSASS!! Oh no, that is super protected certainly we can't touch it. This may be the Holy Grail.

If you follow the readme file, your first attempt will fail. Luckily the error is mentioned right in the file.

Note that you may get some permission issue if you want to "inject" the STRACE DLL in "protected" processes (Injib may fail with error 5 (ACCESS_DENIED) on OpenProcess()). One way to workaround this problem is to run INJLIB from a CMD running under the system account.

That sound great, but how?

We will use some pstools to get the rest of what we need. If you don't know pstools and the Sysinternals Suite, you may not actually be a windows admin.

psexec -s will let us run a process as system!

let's try
psexec -s "C:\Program Files\STRACE\INJDLL.EXE" /p:428 /d:"C:\Program Files\STRACE\STRACE.DLL"

Now, if you run something like Sysinternals Process Explorer and do a find for "strace" you will see it is now attached to LSASS. No errors, no LSASS detects evil, shutting down...

At this point, you should see a strace log file on your desktop, but you don't. Sysinternals Filemon will show us why. The default location is the desktop, but where is system's desktop, it's not under documents and settings. Filemon finds it here.

C:\WINDOWS\system32\config\systemprofile\Desktop\STRACE_LSASS_PID_428_24062009_223405.LOG

3:35:26 PM lsass.exe:400 WRITE C:\WINDOWS\system32\config\systemprofile\Desktop\STRACE_LSASS_PID_428_24062009_223405.LOG SUCCESS Offset: 9630 Length: 26

Now, we can use some LDAP Tools to connect to the server over SSL and watch what happens.

When I bind to the DC, I get a whole lot, but I'll pull out the good stuff:

06/25/2009 23:55:41:078 - SecBuffer #1 BufferType:0x00000000 cbBuffer:47906816
06/25/2009 23:55:41:078 - SecBuffer #2 BufferType:0x00000000 cbBuffer:54197772
06/25/2009 23:55:41:078 - SecBuffer #3 BufferType:0x00000000 cbBuffer:-1
06/25/2009 23:55:41:078 - SecBuffer #0 BufferType:0x00000007 cbBuffer:5
06/25/2009 23:55:41:078 - SecBuffer #1 BufferType:0x00000001 cbBuffer:45
06/25/2009 23:55:41:078 - SECBUFFER_DATA - 45 byte(s) / DecryptMessage - OUTPUT
=====================================================
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 0123456789abcdef

0000: 30 2b 02 01 01 60 26 02 01 03 04 17 61 64 6d 69 0+...`&.....admi
0010: 6e 69 73 74 72 61 74 6f 72 40 62 6c 69 6d 2e 62 nistrator@blim.b
0020: 6c 61 6d 80 08 70 61 73 73 77 6f 72 64 lam..password
=====================================================
06/25/2009 23:55:41:078 - SecBuffer #2 BufferType:0x00000006 cbBuffer:16
06/25/2009 23:55:41:078 - SecBuffer #3 BufferType:0x00000000 cbBuffer:-1
06/25/2009 23:55:41:093 - SecBuffer #0 BufferType:0x00000002 cbBuffer:5
06/25/2009 23:55:41:093 - SecBuffer #1 BufferType:0x00000001 cbBuffer:22
06/25/2009 23:55:41:093 - SECBUFFER_DATA - 22 byte(s) / EncryptMessage - INPUT
=====================================================
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 0123456789abcdef

0000: 30 84 00 00 00 10 02 01 01 61 84 00 00 00 07 0a 0........a......
0010: 01 00 04 00 04 00 ......
=====================================================

We see here that it gets some buffers and decrypted messages. I see my username and password and then some sort of response.

To verify our suspicions, we make the same conneciton, this time without SSL and capture it via wireshark.

If we look for the same data, we get these two frames:

0000 00 0c 29 bb 00 2e 00 1a 4b 79 8d 34 08 00 45 00 ..).....Ky.4..E.
0010 00 55 c1 14 40 00 80 06 5c 60 0a 01 64 97 0a 01 .U..@...\`..d...
0020 64 95 0a 87 01 85 b6 56 6c 8e 73 0a 76 db 50 18 d......Vl.s.v.P.
0030 fc 00 d0 48 00 00 30 2b 02 01 01 60 26 02 01 03 ...H..0+...`&...
0040 04 17 61 64 6d 69 6e 69 73 74 72 61 74 6f 72 40 ..administrator@
0050 62 6c 69 6d 2e 62 6c 61 6d 80 08 70 61 73 73 77 blim.blam..passw
0060 6f 72 64 ord


0000 00 1a 4b 79 8d 34 00 0c 29 bb 00 2e 08 00 45 00 ..Ky.4..).....E.
0010 00 3e 26 b4 40 00 80 06 f6 d7 0a 01 64 95 0a 01 .>&.@.......d...
0020 64 97 01 85 0a 87 73 0a 76 db b6 56 6c bb 50 18 d.....s.v..Vl.P.
0030 fa c3 f6 bf 00 00 30 84 00 00 00 10 02 01 01 61 ......0........a
0040 84 00 00 00 07 0a 01 00 04 00 04 00 ............

If you notice, we have a byte for byte match for the bottom part of the packet. If you break out your TCPIP Illustraed, you will find that the top of each frame is the Ethernet, IP and TCP header data, we are getting just the LDAP protocol payload!

If we look closer, we see that all our LDAP traffic is there. The downside being, that we don't get information on the host sending the data and we don't have libcap format, so tools like wireshark can't dissect the protocols for us in a nice way. If you understand libcap, it looks trivial to create fake Ethernet, IP and TCP data and drop in the payload to make a libcap file, or use existing parsers to dissect the messages. Its beyond me though.

The last down side is that I can't find out how to un-inject the strace dll. So far, only rebooting has fixed this.

And that is that... If you can detour the SSL from LSASS, you can do it anywhere!

Wednesday, May 27, 2009

Analysis of Oracle Hyperion Web Analysis Studio 9.3 Logon Security

Before I start I'll point out that Oracle does not make any claims that the Hyperion Logins are secure without SSL. This analysis was performed to clear up misconceptions on the part of others.

Analysis of Oracle Hyperion Web Analysis Studio 9.3 Logon Security
Abstract
A quick vetting of how Hyperion handles usernames and passwords shows that their controls offer little protection of credentials while crossing the network, in the absence of SSL. While passwords are not sent across the network as clear text, they are only lightly obfuscated and subject to multiple attacks.
Hyperion should not be used unless the login pages are encrypted using SSL derived from a certificate that chains to a trusted Root Certificate Authority. This is most important when using the LDAP connector as it then puts credentials at risk that might grant access to other systems.

Analysis
There are multiple ways to take a look at Hyperion yielding varying results. Hyperion sends data via Java code to the app server via an unknown application protocol. It uses Java serialized objects, which may be meaningful to some else. At the TCP level, the usernames can be seen on the wire in clear text, along with what appears to be a base64 encoded password.
A message snippet looks like this:
------------------314159265358979323846
Content-Disposition: form-data; name="param type 1"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

com.hyperion.atf.security.authentication.IAuthenticationHelper

------------------314159265358979323846
Content-Disposition: form-data; name="param type 2"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit

com.hyperion.atf.security.users.IUserManagerCreateTask

------------------314159265358979323846
Content-Disposition: form-data; name="param value 0"
Content-Type: application/x-java-serialized-object
Content-Transfer-Encoding: binary

....sr.
csPasswordt..Ljava/lang/String;L.
csUserNameq.~..xpt..DmFVYnsCImM=t..markgamache


------------------314159265358979323846

The first thing we see is that the protocol breaks up messages with Pi. Who knows… The second thing we see is that the helpful words, Password and UserName can be found. These are followed by DmFVYnsCImM=, presumably my password and then markgamache, my username. By simply trying a few attempts with different usernames and passwords, it becomes clear that we are correct in our assumptions. Third, but for later, we also get a java class name, hyperion.atf.security.authentication.SimplePasswordToken.

Replay Attacks
Before we look at any technical attacks, we’ll look at that messaging format. The TCP data sent along with the username and password contain no sequence numbers, nonces, or timestamps. As you will see in the next section, a username and encrypted password for an account do not change across login sessions. This makes it highly likely that a simple replay would allow access to a session as another user. This does not put the password at risk, only data within the application. If the application data is not encrypted, it is likely that the session could be hijacked as well. This is a smaller concern generally.
The next step is to try and make sense of the password data. The system lets us send as many usernames and passwords as we like.

Chosen Plaintexts
By sending data we select through the password encryptor, we can then analyze the results.

Username: markgamache
Username Hex: 6d 61 72 6b 67 61 6d 61 63 68 65

Password : 1q2w3e4r
Plaintext hex: 31 71 32 77 33 65 34 72
Cyphertext Hex: 0e 61 55 62 7b 02 22 63

Password: 11111111
Plaintext hex : 31 31 31 31 31 31 31 31
Cyphertext Hex : 0e 21 56 24 79 56 27 20

Password: 111111111
Plaintext hex : 31 31 31 31 31 31 31 31 31
Cyphertext Hex 0e 21 56 24 79 56 27 20 e9

Password: 22222222
Password hex: 32 32 32 32 32 32 32 32
Cyphertext Hex : 0d 22 55 27 7a 55 24 23

Password: 33333333
Password hex : 33 33 33 33 33 33 33 33
Cyphertext Hex : 0c 23 54 26 7b 54 25 22

Password: 44444444
Password hex : 34 34 34 34 34 34 34 34
Cyphertext Hex : 0b 24 53 21 7c 53 22 25

Password: 55555555
Password hex : 35 35 35 35 35 35 35 35
Cyphertext Hex : 0a 25 52 20 7d 52 23 24

Password: 12345678
Password hex : 31 32 33 34 35 36 37 38
Cyphertext Hex : 0e 22 54 21 7d 51 21 29


Username: ted
Username Hex: 74 65 64

Password: 11111111
Password hex : 31 31 31 31 31 31 31 31
Cyphertext Hex : ab 28 71 f4 fe cb 1d 46


Username: 1111
Password hex : 31 31 31 31 31 31 31 31
Cyphertext Hex : 51 2b f3 5c a6 76 db 43


Username : 2111
Password hex : 31 31 31 31 31 31 31 31
Cyphertext Hex : af a8 8d c5 48 db 27 7c



From the small sample, we can see a few things:
• If the username is unchanged, then the password data seems to be consistent
o For markgamache, as long as the password starts with 1, the cyphertext starts with 0e
o The transform is not s simple substitution, as the 0e only corresponds to 1 as the first character
o Incrementing the value of a character in a particular position produces predictable results. In pos 1, 0e = 1, 0d = 2, 0c = 3
o The pattern is not completely predictable. In Pos 4, 24 = 1, 27 = 2, 26 = 3
o The value of a position is not varied by the character before or after. The encrypted value of Pos 3, when the plaintext is 2, is 55, both when the password is 1q2w3e4r and 2222222
• If the username changes, the cyphertext value no longer match for a position, with the password unchanged. See users 1111 and 1112 above.
• The values at a position do not vary based on the overall password lenghth. See password 11111111 vs 111111111

This tells us that the encrypted version of the password is derived in part from the username. It also shows us that for any username, we can perform a simple position by position chosen plaintext attack to find the corresponding encrypted values. This means in about 100 attempts, a user’s password can be derived. As the application allows unlimited retries, this cannot be stopped. The account would likely be locked out due to password policy, but in 10 – 30 minutes, it is likely to be unlocked by policy.

Code Attacks
As the password is “encrypted” using the client side Java code, we can take a look at that code. While the app runs automatically when you click on a web link, there is nothing stopping us from getting the code to look at. Remember, we can’t execute the code if we can’t get to it.
A simple curl command allows us to get a copy of the jar file, AnalyzerClient.jar. From there, it is a simple task to extract the jar and decompile the classes. There are lots of them, but we are saved time by the data from the wire, remember hyperion.atf.security.authentication.SimplePasswordToken.
Sure enough, there is a class named hyperion.atf.security.authentication.SimplePasswordToken. The class has both encrypt and decrypt methods referencing com.hyperion.atf.utils.encryption.EncryptionManager.
Upon investigation of EncryptionManager, we see that the username is used as the key and RC4 is used to encrypt the password. This is bad, but is validated by the chosen plaintext operations.
Following the bouncing ball and stripping the error handling for prettiness…
1. We get csPassword and a value from the wire.
2. We get csPassword = EncryptionManager.encrypt(asUserName, asPassword); from SimplePasswordToken
3. From EncryptionManager we get
public static String encrypt(String asEncryptionKey, String asClearText)
{
return encryptRC4(asEncryptionKey, asClearText);
}

And
protected static String encryptRC4(String asEncryptionKey, String asClearText)
{
byte myCypher[];
Rc4Cipher mRc4 = new Rc4Cipher(asEncryptionKey.getBytes("UTF8"));
byte myClear[] = asClearText.getBytes("UTF8");
myCypher = new byte[myClear.length];
mRc4.encrypt(myClear, myCypher);
return Base64Codec.encode(myCypher);
}

Indeed, the encryption key is the username, which is sent in the same packet as the encrypted password. The key is shipped in the lock.
All of our assumptions are confirmed.
Lastly, even thought the client should never need to decrypt the password, that’s the server’s job, the decrypt code is in the classes. This makes creating your own exploit code extra easy.

Character Positions Explained
Now that we know that RC4 is being used with the username as the key, we can see why there is a predictable shift in the cyphertext at any position if the username does not change. If you recall, for username markgamache, a 1 as the first character always yields 0e as the first byte of cyphertext. This is because RC4 is a stream cipher. It acts on a byte stream, one byte at a time. One byte in the stream had no mathematical effect on the previous or next byte. This is why block ciphers are considered better, as a rule of thumb. As our passwords are made up of characters that are, unluckily, one byte each, each character is essentially encrypted by its self. To defeat this, some sort of bit shift or IV (initialization Vector) should be used. It’s all moot though, as the key is shipped with the lock, as it were.

Summary
Hyperion passwords, and any linked SSO directory passwords, are put at considerable risk by simple code inspection or by chosen plain text attacks. While it has not been tested, a session with the application can probably be established via a TCP replay. Without additional controls, it is likely that sessions can also be hijacked. While the last two issues do not put passwords at risk, they do put the application and its data at risk.
Hyperion should not be used without SSL via a certificate that chains to a trusted root certificate authority. This will provide for secure key exchange, secure authentication, stop replay attacks and make the world a better place.

This just reinforces the basic security principal; Trust well vetted cryptosystems (like SSL) over custom solutions.


Monday, May 25, 2009

My First Vendor Security Flaw Submission

I sent in my first security analysis/vulnerability to Oracle on Friday. It was for the product, Hyperion Web Analysis Studio 9.3. I've heard horror stories about vendors abusing security professionals, rather than being thankful. I hit send with a bit of trepidation. I got a fairly quick reply (12 hours or so) that was very pleasant, thanking me for the analysis and asking for a few clarifications. It was clear that my analysis was thoroughly read and understood. I must say, they are friendly folks. I'm waiting to hear back as to when I can blog on my analysis, so something will be forthcoming in the 3 4 weeks.

One thing that was annoying was that it took me quite a while to figure out where to send the information.

On a side note, the flaw is not serious, as long as you use SSL, which you should be doing anyway.