Sunday, February 15, 2009

Classic Bug: Windows 95/98/ME share password bypass (part 2)

In part 1 of this article I described how MS00-072 could be used to bypass authentication on a Windows 95/98/ME share. In this part, I will describe how this can be used to extract the password.

I described how a zero length password could bypass the authentication, but what if we want to know the actual password? This could be handy as the password may be used on other systems or if we want to use non-modified software to access the share after extracting the password.

To accomplish this we simply try to guess the password one character at the time. Let me explain: instead of using a zero length password, we use the following:

[password length=1][password=A]

Notice we do not NULL terminate our password, and do not add one to the password length. Lets revisit our verifyPassword function:

bool verifyPassword(int givenLength, char * givenPassword, char * realPassword){
for(int i=0; i<length; i++){
if (givenPassword[i] != realPassword[i]){
return false;
}
}
return true;
}


When we supply a password with a length of one, the function will compare our one character password ('A') with the first character of the actual password. If they match, authentication is successful, if they do not, authentication fails. We can use this to determine the first character of the actual password. If authentication fails, we simply try the password 'B' and so on.
When we have found the first character (say it’s 'P'), we add another character to the password and try ‘PA’ with a length of 2. When we found the second character we add a third one and so on. If we want to know if we have the full password we simply add a NULL byte instead of a character and if authentication succeeds, we have the complete password.

This process is automated by the tool pqWak, which can be found here.

So is this bug still relevant? Well I think so, as it certainly isn’t the only one of its kind. In 2004 a very similar bug was found in MySQL (advisory), you could access a MySQL server without actually knowing the password.

Classic Bug: Windows 95/98/ME share password bypass (part 1)

Another oldie, this time MS00-072: bypassing Windows 95/98/ME share level passwords. In Windows ME and earlier, you could share a folder and put a password on it, so only people in possession of the password could access your shared files over the network.

This vulnerability is interesting because this authentication could by bypassed completely. Furthermore, you could use it to recover the actual password. The function to verify the password probably looked something like this pseudo code:

bool verifyPassword(int givenLength, char * givenPassword, char * realPassword){
for(int i=0; i<length; i++){
if (givenPassword[i] != realPassword[i]){
return false;
}
}
return true;
}


The code does not look so bad at first glance. It takes three parameters, the supplied password and its length and the actual share password. Both passwords are NULL-terminated. The password length includes the NULL byte, so the password ‘12345’ would have a length of 6. It then starts to compare the two byte-by-byte. If any of bytes in the two passwords differ, the verification fails and access is denied.

As I mentioned in the above paragraph, the supplied length of the password includes the NULL byte, so even an empty password would have a length of 1 (the NULL byte itself). This is where the problem lies. The relevant part of a legitimate authentication packet would look like this (password could be empty):

[password length+1][password][NULL byte]


So for an empty password, password length = 1 and the above function would simply compare 1 byte (the NULL byte). If the actual password is also empty (e.g. consists of only a NULL byte), access is granted.

Now you might wonder what happens if the password length is set to 0 (this should never happen, as there is always a NULL byte). What happens is we bypass authentication. Looking at the above function, if givenLength is equal to 0, we never enter the for loop. Thus, we never compare any characters and authentication is always successful.

In part 2 I will describe how an exploit called pqWak uses this bug to determine the password remotely.

Some DECT updates

The dedected team has gotten the Type III cards to work! I tested one of mine today (an Ascom Voo:doo) and it seems to be working properly. Meanwhile the prices on Type II cards are still pretty high.

In a previous post I mentioned a patch which allows capturing directly to .wav files, so conversion is no longer necessary. A newer version of this patch was posted about a month ago. This version also allows live voice playing. I tested the patch last weekend but on my laptop the live voice playing feature ‘stutters’ a bit (could be because I also applied the patch from r44). The capturing directly to .wav files works great though. I haven’t posted a sample with good audio quality so far, so here is one to get an idea of the sound quality (some random English voice menu). There are some manual decoding hints on the mailing lists, I’ll have to look up which method the patch uses.

Siemens Germany has posted a list of Gigaset phones which use encryption here (I could not find it on the Dutch or English versions of gigaset.com). The Gigaset 4010 phone I was able to eavesdrop on is simply not on the list.