During my HAR talk, I briefly described the password filter mechanism. A password filter is a DLL that is listed in the registry at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Notification Packages.
Whenever a user changes his password, Windows passes the plaintext password to all the DLL’s listed there. The password filter can then determine whether the password meets its requirements (complexity, length etc.) and approve or disapprove the password. You can use this feature to implement your own password filter DLL and enforce your custom company password policy.
Of course, a password filter could also choose to do something else with the plaintext password. As I described in my previous blog post, Microsoft does this with RASSFM.DLL. An attacker could also create his own backdoor password filter that, for example, sends the password to a remote server.
The procedures you need to implement are quite well documented on MSDN. There is even a universal password filter available on Sourceforge. This allows you to pass the password to a custom script.
Showing posts with label vulnerability. Show all posts
Showing posts with label vulnerability. Show all posts
Thursday, August 27, 2009
Wednesday, August 26, 2009
Passwords stored using reversible encryption: how it works (part 2)
In part one of this article, I described how the reversible encryption of Windows domain passwords works. In this part, we will look at the security of this mechanism.
To decrypt the password you need the following components:
- The encrypted password (G$RADIUSCHAP)
- The 16 byte random (G$RADIUSCHAPKEY)
- The global LSA secret (G$MSRADIUSCHAPKEY)
- A static key hardcoded in RASSFM.DLL
The hardest thing to get is that global LSA secret. This is stored in active directory and synchronized between domain controllers. To access this key, you need domain administrator privileges. An obvious risk here is that once someone gains domain administrator privileges, he won’t need to crack any passwords, but can simply decrypt them. Of course, if an attacker gains domain administrator privileges on your domain, you are already in big trouble anyway.
However, the other components are all semi-public information. The static key is hardcoded in RASSFM.DLL which comes with every Windows server, so is easy to get. The G$RADIUSCHAP and G$RADIUSCHAPKEY are stored in active directory in the userParameters structure. If you have a user account on a domain you can use AD Explorer to access the Active Directory database and read this information. Of course, to decrypt the password you will still need that LSA secret.
The encrypted version of the password can be interesting though; by looking at the encrypted password you can derive the length of the plaintext password. Two examples I used in my presentation:
Pwd1 encrypted: 0f53 8420 9418 05ce 01ad
Pwd12 encrypted: 5d69 9375 6f92 1b63 7728 439f
So, by looking at the encrypted passwords you should notice that the encrypted version of Pwd12 is two bytes longer than the encrypted version of Pwd1. So, although we cannot determine from just looking at the encrypted password that they are very similar, we can determine their length. What this means is, that as a domain user, you can determine the length of other people’s passwords, which could be quite interesting.
If you obtain the LSA secret somehow (maybe because you temporarily gain domain administrator privileges), from that point on you can decrypt passwords stored using reversible encryption. This could be used as a nice backdoor, just steal the LSA secret, enable reversible encryption (if it hasn’t been enabled yet) and you can grab the domain administrator password with just a normal user account.
Someone in the HAR 2009 audience had a very nice question: Is it possible to recreate the LSA secret if you’re afraid it has been stolen. Of course the better option is to recreate the entire domain, but this is not always an option. To recreate the LSA secret you need to write a program that sets the LSA secret to NULL. According to the documentation, Windows will delete the LSA secret. It will generate a new LSA secret when it needs to encrypt another password. Of course, Windows won’t be able to decrypt the passwords stored before that point anymore. However, it will still try to decrypt them using the new LSA secret, which will result in gibberish most of the time. If you’re really unlucky it could decrypt the first two bytes to NULL, which basically means the password is suddenly empty. So if you ever have to do this, resetting all passwords immediately is probably a good idea.
To decrypt the password you need the following components:
- The encrypted password (G$RADIUSCHAP)
- The 16 byte random (G$RADIUSCHAPKEY)
- The global LSA secret (G$MSRADIUSCHAPKEY)
- A static key hardcoded in RASSFM.DLL
The hardest thing to get is that global LSA secret. This is stored in active directory and synchronized between domain controllers. To access this key, you need domain administrator privileges. An obvious risk here is that once someone gains domain administrator privileges, he won’t need to crack any passwords, but can simply decrypt them. Of course, if an attacker gains domain administrator privileges on your domain, you are already in big trouble anyway.
However, the other components are all semi-public information. The static key is hardcoded in RASSFM.DLL which comes with every Windows server, so is easy to get. The G$RADIUSCHAP and G$RADIUSCHAPKEY are stored in active directory in the userParameters structure. If you have a user account on a domain you can use AD Explorer to access the Active Directory database and read this information. Of course, to decrypt the password you will still need that LSA secret.
The encrypted version of the password can be interesting though; by looking at the encrypted password you can derive the length of the plaintext password. Two examples I used in my presentation:
Pwd1 encrypted: 0f53 8420 9418 05ce 01ad
Pwd12 encrypted: 5d69 9375 6f92 1b63 7728 439f
So, by looking at the encrypted passwords you should notice that the encrypted version of Pwd12 is two bytes longer than the encrypted version of Pwd1. So, although we cannot determine from just looking at the encrypted password that they are very similar, we can determine their length. What this means is, that as a domain user, you can determine the length of other people’s passwords, which could be quite interesting.
If you obtain the LSA secret somehow (maybe because you temporarily gain domain administrator privileges), from that point on you can decrypt passwords stored using reversible encryption. This could be used as a nice backdoor, just steal the LSA secret, enable reversible encryption (if it hasn’t been enabled yet) and you can grab the domain administrator password with just a normal user account.
Someone in the HAR 2009 audience had a very nice question: Is it possible to recreate the LSA secret if you’re afraid it has been stolen. Of course the better option is to recreate the entire domain, but this is not always an option. To recreate the LSA secret you need to write a program that sets the LSA secret to NULL. According to the documentation, Windows will delete the LSA secret. It will generate a new LSA secret when it needs to encrypt another password. Of course, Windows won’t be able to decrypt the passwords stored before that point anymore. However, it will still try to decrypt them using the new LSA secret, which will result in gibberish most of the time. If you’re really unlucky it could decrypt the first two bytes to NULL, which basically means the password is suddenly empty. So if you ever have to do this, resetting all passwords immediately is probably a good idea.
Labels:
reversible encryption,
security,
vulnerability
Tuesday, August 25, 2009
HAR 2009 talk references
I promised to put up some nice ‘further reading’ material for those who have seen my HAR talk. So here it is:
LM/NTLM
Disabling the LM hash
Free Rainbow Tables and download site
Passing the hash
The original post from 1997 by Paul Ashton
Core Pass-The-Hash toolkit
Tenable SMBshell
Token stealing
Luke Jennings research page
A tutorial on the tool by CG
You can see the video of my talk here or download it here or here.
LM/NTLM
Disabling the LM hash
Free Rainbow Tables and download site
Passing the hash
The original post from 1997 by Paul Ashton
Core Pass-The-Hash toolkit
Tenable SMBshell
Token stealing
Luke Jennings research page
A tutorial on the tool by CG
You can see the video of my talk here or download it here or here.
Passwords stored using reversible encryption: how it works (part 1)
In case you missed my HAR2009 talk: in the second part I talked about a Windows feature called ‘Store passwords using reversible encryption’. When this is enabled (per user or for the entire domain), Windows stores the password encrypted, but in such a way that it can reverse the encryption and recover the plaintext password. This feature exists because some authentication protocols require the plaintext password to function correctly, the two most common examples are HTTP Digest Authentication and CHAP.
This feature is not enabled by default but I’ve seen it a couple of times in customer networks. As I couldn’t find any description of how this mechanism works or any tool to recover these passwords, I decided to investigate.
When you change your password on a domain that has reversible encryption enabled, a password filter called RASSFM.DLL is used to store the password using reversible encryption. The key that is used to do this is G$MSRADIUSCHAPKEY, which is stored as a global LSA secret. This key is decrypted using a static key (hardcoded in the DLL). The result of this operation is combined with a 16-byte random value (generated every time someone changes their password) and that key is used to encrypt a Unicode version of the password using the RC4 algorithm.
I found out these passwords are stored in Active Directory in a per-user structure called userParameters. If you use a tool such as AD Explorer you can look at this structure in an AD that has enabled this feature. When you look at this structure, it looks like a binary blob, with some human-readable parts in there. When you enable reversible encryption you will notice two readable strings: G$RADIUSCHAP and G$RADIUSCHAPKEY. The userParameters can also be used to store settings unrelated to reversible encryption, such as per-user Terminal Server settings.
Following the G$RADIUSCHAP part is the ascii-hex encoded encrypted password. The part following the G$RADIUSCHAPKEY name is the 16-byte random value.
So to decrypt this password we use the following steps:
- Take the G$MSRADIUSCHAPKEY Global LSA secret
- Decrypt it using the static key
- Parse the userParameters structure and extract the G$RADIUSCHAP and G$RADIUSCHAPKEY values
- Combine the value of G$RADIUSCHAPKEY (the 16-byte random) with the decrypted LSA secret to create an RC4 key
- Decrypt the value of G$RADIUSCHAP using that RC4 key
The result is a plaintext Unicode password. My tool 'Revdump' automates this procedure.
In part two of this article, I will look at the security of this mechanism.
This feature is not enabled by default but I’ve seen it a couple of times in customer networks. As I couldn’t find any description of how this mechanism works or any tool to recover these passwords, I decided to investigate.
When you change your password on a domain that has reversible encryption enabled, a password filter called RASSFM.DLL is used to store the password using reversible encryption. The key that is used to do this is G$MSRADIUSCHAPKEY, which is stored as a global LSA secret. This key is decrypted using a static key (hardcoded in the DLL). The result of this operation is combined with a 16-byte random value (generated every time someone changes their password) and that key is used to encrypt a Unicode version of the password using the RC4 algorithm.
I found out these passwords are stored in Active Directory in a per-user structure called userParameters. If you use a tool such as AD Explorer you can look at this structure in an AD that has enabled this feature. When you look at this structure, it looks like a binary blob, with some human-readable parts in there. When you enable reversible encryption you will notice two readable strings: G$RADIUSCHAP and G$RADIUSCHAPKEY. The userParameters can also be used to store settings unrelated to reversible encryption, such as per-user Terminal Server settings.
Following the G$RADIUSCHAP part is the ascii-hex encoded encrypted password. The part following the G$RADIUSCHAPKEY name is the 16-byte random value.
So to decrypt this password we use the following steps:
- Take the G$MSRADIUSCHAPKEY Global LSA secret
- Decrypt it using the static key
- Parse the userParameters structure and extract the G$RADIUSCHAP and G$RADIUSCHAPKEY values
- Combine the value of G$RADIUSCHAPKEY (the 16-byte random) with the decrypted LSA secret to create an RC4 key
- Decrypt the value of G$RADIUSCHAP using that RC4 key
The result is a plaintext Unicode password. My tool 'Revdump' automates this procedure.
In part two of this article, I will look at the security of this mechanism.
Labels:
reversible encryption,
security,
vulnerability
Thursday, June 25, 2009
Zen Cart authentication bypass
Zen Cart is a popular open source e-commerce application, written in PHP. Yesterday, two exploits for Zen Cart showed up on milw0rm. The first one is a remote code execution, the second one an SQL injection exploit. The root cause of the two bugs however, is the same: an authentication bypass on the administrative interface of Zen Cart discoverd by Ghyslain/BlackH. Zen Cart has released a patch for this issue here.
Zen Cart does a pretty decent job verifying administrators are actually authenticated, however it has some exceptions to the rule:
This code is present in /admin/includes/init_includes/init_admin_auth.php (slightly simplified code):
So basically, if you are not logged in, Zen Cart will redirect you to the login page, unless you are accessing the password_forgotten.php page.
The problem here is trusting the PHP_SELF variable to determine which script is being accessed. Here a bit of strange PHP behaviour comes in. If I request http://server.com/index.php, the PHP_SELF variable will be /index.php. However if I request http://server.com/index.php/foobar , the PHP_SELF variable will be /index.php/foobar, but the script being executed will still be index.php!
So in this case we can trick Zen Cart into thinking we are accessing password_forgotten.php, while we are actually accessing a different file by requesting:
http://target/admin/customers.php/password_forgotten.php
The file we are executing is customers.php, but basename(PHP_SELF) will return password_forgotten.php! Zen Cart thinks we are accessing the ‘I forgot my password’ page, which does not require authentication and allows us to continue without logging in. We can now view a list of customers on our target site, without logging in!
The code execution exploit uses this to access an admin script that allows an administrator to create new files. The exploit uses this functionality to create a new php file on the server, this php file contains a simple backdoor and voila: remote code execution.
Luckily Zen Cart has released a fix for this (although I expect most installations are still vulnerable). I took a look at the patch and noticed it attempts to fix the bug by checking if the string '.php' appears more than once in PHP_SELF. At first this seems to be an (ugly but) effective fix and I think it is in most cases. However, Zen Cart supports multiple platforms, including Windows. As you may know, filenames on Windows are not case sensitive (foo.txt is the same as foo.TXT). The new check however only checks for lowercase instances of '.php'… So if our target is a Windows system, we can circumvent the patch by requesting:
http://target/admin/customers.PHP/password_forgotten.php
So by changing the extension of customers.php to .PHP, we modify the PHP_SELF variable so '.php' is only present once and bypass the new check! I modified the code execution exploit on milw0rm to reflect this and was able to succesfully exploit my installation of Zen Cart on a Windows platform.
Of course I notified the Zen Cart developers of the shortcoming in their patch and they have released an updated version which does a case insensitive check.
Zen Cart does a pretty decent job verifying administrators are actually authenticated, however it has some exceptions to the rule:
This code is present in /admin/includes/init_includes/init_admin_auth.php (slightly simplified code):
if (if (!isset($_SESSION['admin_id']) &&
!(basename($SERVER['PHP_SELF']) == 'password_forgotten.php')) {
zen_redirect('login.php');
}
So basically, if you are not logged in, Zen Cart will redirect you to the login page, unless you are accessing the password_forgotten.php page.
The problem here is trusting the PHP_SELF variable to determine which script is being accessed. Here a bit of strange PHP behaviour comes in. If I request http://server.com/index.php, the PHP_SELF variable will be /index.php. However if I request http://server.com/index.php/foobar , the PHP_SELF variable will be /index.php/foobar, but the script being executed will still be index.php!
So in this case we can trick Zen Cart into thinking we are accessing password_forgotten.php, while we are actually accessing a different file by requesting:
http://target/admin/customers.php/password_forgotten.php
The file we are executing is customers.php, but basename(PHP_SELF) will return password_forgotten.php! Zen Cart thinks we are accessing the ‘I forgot my password’ page, which does not require authentication and allows us to continue without logging in. We can now view a list of customers on our target site, without logging in!
The code execution exploit uses this to access an admin script that allows an administrator to create new files. The exploit uses this functionality to create a new php file on the server, this php file contains a simple backdoor and voila: remote code execution.
Luckily Zen Cart has released a fix for this (although I expect most installations are still vulnerable). I took a look at the patch and noticed it attempts to fix the bug by checking if the string '.php' appears more than once in PHP_SELF. At first this seems to be an (ugly but) effective fix and I think it is in most cases. However, Zen Cart supports multiple platforms, including Windows. As you may know, filenames on Windows are not case sensitive (foo.txt is the same as foo.TXT). The new check however only checks for lowercase instances of '.php'… So if our target is a Windows system, we can circumvent the patch by requesting:
http://target/admin/customers.PHP/password_forgotten.php
So by changing the extension of customers.php to .PHP, we modify the PHP_SELF variable so '.php' is only present once and bypass the new check! I modified the code execution exploit on milw0rm to reflect this and was able to succesfully exploit my installation of Zen Cart on a Windows platform.
Of course I notified the Zen Cart developers of the shortcoming in their patch and they have released an updated version which does a case insensitive check.
Labels:
exploit,
exploit development,
security,
vulnerability,
zen cart
Tuesday, May 12, 2009
Time to update SquirrelMail
Today Squirrelmail released version 1.4.18. This version fixes a couple of vulnerabilities, some of which I spotted while browsing through SquirrelMail source code while installing it:
The second XSS is rather interresting. SquirrelMail comes with a test script which (given ciphertext and a key) decrypts user supplied data. The decrypted data was then displayed unfiltered (resulting in an obvious XSS). Pretty stealthy and should circumvent any IDS or WAF. Having this kind of script in your webroot is obviously a bad idea anyway.
The last bug occurs only in very specific configurations. If you have more than one imap server, there is a way to configure that in SquirrelMail. If you configure this and use the example map_yp_alias function for this, unauthenticated attackers could execute shell commands on your server. If you built your own function for this, you should probably check if it handles input correctly. It is unlikely that you're running this kind of configuration, but there are probably a couple of installations out there using this.
- A reflected XSS caused by unsafe handling of the $PHP_SELF variable
- A reflected XSS caused by unsafe handling of user supplied encrypted data
- A remote command execution vulnerability (only in very specific configurations)
The second XSS is rather interresting. SquirrelMail comes with a test script which (given ciphertext and a key) decrypts user supplied data. The decrypted data was then displayed unfiltered (resulting in an obvious XSS). Pretty stealthy and should circumvent any IDS or WAF. Having this kind of script in your webroot is obviously a bad idea anyway.
The last bug occurs only in very specific configurations. If you have more than one imap server, there is a way to configure that in SquirrelMail. If you configure this and use the example map_yp_alias function for this, unauthenticated attackers could execute shell commands on your server. If you built your own function for this, you should probably check if it handles input correctly. It is unlikely that you're running this kind of configuration, but there are probably a couple of installations out there using this.
Tuesday, December 16, 2008
Classic bug: phpBB 2.0.12 authentication bypass
December is always a very busy month at work, so it has been a while since my last post. Here's another classic bug: the phpBB 2.0.12 authentication bypass. I am not sure who discovered this bug, but the first references to it seem to be from February 2005.
As the title says, this is an authentication bypass bug, which means an attacker can access any account on a vulnerable phpBB version without knowing the password. This is not your typical web application bug though, it has to do with serialization and you could patch it by adding only one byte to the vulnerable code.
So how does it work? A phpBB forum has a ‘remember me’ function, which basically gives you a cookie which automatically logs you in. The cookie looks something like this:
a:2:{s:11:"autologinid";s:32:"96948aad3fcae80c08a35c9b5958cd89";s:6:"userid";s:4:"3207";}
This format is created by the PHP serialize function. Basically, it is a technique to store a complex structure into a string. If we unserialize the above example, we get this (print_r output):
Array
(
[autologinid] => 96948aad3fcae80c08a35c9b5958cd89
[userid] => 3207
)
So our cookie is used to store an array containing two strings: our userid and something called an ‘autologinid’. As it turns out, the autologinid is just an MD5 hash of the phpBB password. Not such a good idea, as this makes phpBB vulnerable to passing-the-hash attacks. phpBB 3 doesn’t use this type of cookie anymore though.
The bug is in this part of the phpBB source code (simplified):
$sessiondata = unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename]));
if( $sessiondata['autologinid'] == $userdata['user_password'] ){
// autologinid matches password
$login = 1;
}
Doesn’t look that bad does it? After unserializing the data, It simply compared the autologinid in our session with the MD5 of the user’s password. They use the == operator to compare two strings, nothing wrong with that. But what if one of the operands in the comparison is not a string? Take for example the following PHP code:
if(true == ‘96948aad3fcae80c08a35c9b5958cd89’){
echo ‘true!’;
}
You may not expect it, but this piece of code outputs ‘true!’. PHP simply converts the string to a boolean and unless the string is empty or ‘0’ PHP will convert it to ‘true’. So what does this have to do with our vulnerability? Let’s take another look at a part of our serialized cookie:
s:32:"96948aad3fcae80c08a35c9b5958cd89"
Our MD5 hash is prefixed with s:32:, which means this variable is a string with a length of 32. So instead of just specifying the string itself, we also specify its type! The trick is to simply change this part of our cookie to:
b:1
Which makes our cookie:
a:2:{s:11:"autologinid";b:1;s:6:"userid";s:4:"3207";
For the unserialize function, this simply means: the value of autologinid is a boolean with the value ‘true’. The next step is to change our cookie on the forum to this one. The forum will compare the password hash of the user with userid 3207 to ‘true’, tricking phpBB into thinking we have the actual password hash! A logical next step would be to change the userid to '1', which is the userid of the forum administrator user, giving us full control over the forum.
The patch for this vulnerability whas a simple one. The phpBB team simply changed the line:
if( $sessiondata['autologinid'] == $userdata['user_password'] ){
to
if( $sessiondata['autologinid'] === $userdata['user_password'] ){
In other words, they switched from the == to the === operator. The PHP manual has the following description for the === operator: “TRUE if $a is equal to $b, and they are of the same type.”. The fix was this simple, by changing the operator, the two compared types have to be equal, so an attacker can no longer supply a boolean instead of a string and bypass authentication.
The moral of this story? Every piece of input is important, don’t allow users to supply serialized data, unless absolutely necessary!
As the title says, this is an authentication bypass bug, which means an attacker can access any account on a vulnerable phpBB version without knowing the password. This is not your typical web application bug though, it has to do with serialization and you could patch it by adding only one byte to the vulnerable code.
So how does it work? A phpBB forum has a ‘remember me’ function, which basically gives you a cookie which automatically logs you in. The cookie looks something like this:
a:2:{s:11:"autologinid";s:32:"96948aad3fcae80c08a35c9b5958cd89";s:6:"userid";s:4:"3207";}
This format is created by the PHP serialize function. Basically, it is a technique to store a complex structure into a string. If we unserialize the above example, we get this (print_r output):
Array
(
[autologinid] => 96948aad3fcae80c08a35c9b5958cd89
[userid] => 3207
)
So our cookie is used to store an array containing two strings: our userid and something called an ‘autologinid’. As it turns out, the autologinid is just an MD5 hash of the phpBB password. Not such a good idea, as this makes phpBB vulnerable to passing-the-hash attacks. phpBB 3 doesn’t use this type of cookie anymore though.
The bug is in this part of the phpBB source code (simplified):
$sessiondata = unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename]));
if( $sessiondata['autologinid'] == $userdata['user_password'] ){
// autologinid matches password
$login = 1;
}
Doesn’t look that bad does it? After unserializing the data, It simply compared the autologinid in our session with the MD5 of the user’s password. They use the == operator to compare two strings, nothing wrong with that. But what if one of the operands in the comparison is not a string? Take for example the following PHP code:
if(true == ‘96948aad3fcae80c08a35c9b5958cd89’){
echo ‘true!’;
}
You may not expect it, but this piece of code outputs ‘true!’. PHP simply converts the string to a boolean and unless the string is empty or ‘0’ PHP will convert it to ‘true’. So what does this have to do with our vulnerability? Let’s take another look at a part of our serialized cookie:
s:32:"96948aad3fcae80c08a35c9b5958cd89"
Our MD5 hash is prefixed with s:32:, which means this variable is a string with a length of 32. So instead of just specifying the string itself, we also specify its type! The trick is to simply change this part of our cookie to:
b:1
Which makes our cookie:
a:2:{s:11:"autologinid";b:1;s:6:"userid";s:4:"3207";
For the unserialize function, this simply means: the value of autologinid is a boolean with the value ‘true’. The next step is to change our cookie on the forum to this one. The forum will compare the password hash of the user with userid 3207 to ‘true’, tricking phpBB into thinking we have the actual password hash! A logical next step would be to change the userid to '1', which is the userid of the forum administrator user, giving us full control over the forum.
The patch for this vulnerability whas a simple one. The phpBB team simply changed the line:
if( $sessiondata['autologinid'] == $userdata['user_password'] ){
to
if( $sessiondata['autologinid'] === $userdata['user_password'] ){
In other words, they switched from the == to the === operator. The PHP manual has the following description for the === operator: “TRUE if $a is equal to $b, and they are of the same type.”. The fix was this simple, by changing the operator, the two compared types have to be equal, so an attacker can no longer supply a boolean instead of a string and bypass authentication.
The moral of this story? Every piece of input is important, don’t allow users to supply serialized data, unless absolutely necessary!
Tuesday, November 25, 2008
Classic bug: Modem AT command injection
This is the first article in a new series: classic bugs. These are bugs that may not always be recent, but surely are interesting, or just still relevant. I think this first bug is both.
I am talking about a bug which could be read about on the Bugtraq mailing list in 1998. The poster, Max Schau started his e-mail with ‘this is an old exploit’, even then. With this bug, you can tell modems (the old analog 56k kind) to hang up. The problem is that with a modem, the data and the modem commands all go through the same communications channel. Sometimes, modems have hard time distinguishing between the two. So, if you can trick someone into sending a modem command, you can influence their modem.
The classic example is the hang up command (ATH0). If I can trick someone into sending that string (preceded by three plus signs) through their modem, a vulnerable modem will hang up. This is easier than it may sound, many systems respond to ICMP echo (ping) packets, and reply to the packet with the same data. So all I have to do is send a modem user an ICMP echo packet containing an AT command and it will reply to the packet, sending the command through the modem.
This denial of service used to be very popular and the beautiful thing is: it still works! At Fox-IT we still have an analog line we use for war dialing. Today, I hooked up a modem and dialed into one of the free dialup ISPs. Using a simple ping command from the original advisory, I was able trick the modem into hanging up! A couple of sources report some modems will hang up when merely visiting a site with an AT command in it, I was not able to reproduce that behavior with my modem.
I spend about half an hour trying to inject other commands (for example to trick the modem into dialing a given number), but was unsuccessful. With other modems this might work better. In the original advisory, someone mentions it may be possible to get modems to dial 911, which would be a big deal. In today’s world, criminals would most likely use it to get modems to dial their premium-rate telephone numbers.
Fortunately, not all analog modems are vulnerable to this attack. Some modems require a pause before sending commands, which makes this attack impossible (or at least very hard). A way of ‘patching’ your modem is in the original advisory, this involves changing the default escape character (+) in your modem using an ATS2 command. It seems the escape character can only be a single byte, so it would be easy to brute force if you know someone has changed it.
I am talking about a bug which could be read about on the Bugtraq mailing list in 1998. The poster, Max Schau started his e-mail with ‘this is an old exploit’, even then. With this bug, you can tell modems (the old analog 56k kind) to hang up. The problem is that with a modem, the data and the modem commands all go through the same communications channel. Sometimes, modems have hard time distinguishing between the two. So, if you can trick someone into sending a modem command, you can influence their modem.
The classic example is the hang up command (ATH0). If I can trick someone into sending that string (preceded by three plus signs) through their modem, a vulnerable modem will hang up. This is easier than it may sound, many systems respond to ICMP echo (ping) packets, and reply to the packet with the same data. So all I have to do is send a modem user an ICMP echo packet containing an AT command and it will reply to the packet, sending the command through the modem.
This denial of service used to be very popular and the beautiful thing is: it still works! At Fox-IT we still have an analog line we use for war dialing. Today, I hooked up a modem and dialed into one of the free dialup ISPs. Using a simple ping command from the original advisory, I was able trick the modem into hanging up! A couple of sources report some modems will hang up when merely visiting a site with an AT command in it, I was not able to reproduce that behavior with my modem.
I spend about half an hour trying to inject other commands (for example to trick the modem into dialing a given number), but was unsuccessful. With other modems this might work better. In the original advisory, someone mentions it may be possible to get modems to dial 911, which would be a big deal. In today’s world, criminals would most likely use it to get modems to dial their premium-rate telephone numbers.
Fortunately, not all analog modems are vulnerable to this attack. Some modems require a pause before sending commands, which makes this attack impossible (or at least very hard). A way of ‘patching’ your modem is in the original advisory, this involves changing the default escape character (+) in your modem using an ATS2 command. It seems the escape character can only be a single byte, so it would be easy to brute force if you know someone has changed it.
Subscribe to:
Posts (Atom)