Monday, September 7, 2009

Greasemonkey script to change Google url?sa=t links to direct links

Google recently decided to change the links in Google results from direct links to tracking links. So instead of getting a nice http://blog.teusink.net/ link in your results, you will be getting a http://www.google.com/url?sa=t&source=web&ct=res.. etc link which will redirect you to the correct site.

I was rather annoyed by this as I use Google a lot when pentesting and often like to copy & paste links from the search results. Instead of getting a direct link to a site, I end up with a huge google.com link. So I decided to write a little Greasemonkey script to fix this:

// ==UserScript==
// @name                Google Direct Links
// @namespace           http://blog.teusink.net/
// @description         Script that changes annoying new-style Google links to direct links
// @include             http://google.tld/search?*
// @include             http://www.google.tld/search?*
// ==/UserScript==

var allElements, thisElement;
allElements = document.evaluate('//*[@onmousedown]',document,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < allElements.snapshotLength; i++) {
 thisElement = allElements.snapshotItem(i);
 if(thisElement.nodeName.toUpperCase() == 'A'){
  thisElement.removeAttribute('onmousedown');
 }
}
This script removes the onmousedown handlers on all links in Google search results. Another way to achieve this is to disable Javascript on these pages. To use the script paste it into a text file, save it as googledirectlinks.user.js, install Greasemonkey and drag the googledirectlinks.user.js onto a Firefox window (Greasemonkey will prompt you to install the script).

Another nice extension is Adaptive Referer Remover. This add-on allows you to remove Referer headers if they contain certain patterns. So I added the following pattern to prevent sites from seeing what Google query I entered to find them (you could add rules for other Google features as well or even block it entirely):

^http://www\.google\..*search

This add-on refuses to install if you use Firefox 3.5, but it works fine in that version. You can install the Nightly Tester Tools extension, which enables you to install it anyway (or you could edit the .xpi file manually).

Thursday, August 27, 2009

Windows password filters

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.

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.

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.

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.

Saturday, August 15, 2009

RevDump v0.2 release

This is my tool to dump password stored using reversible encryption. You can download it here. Enjoy your stay at HAR.

Thursday, July 23, 2009

A common Apache .htaccess misconfiguration

If you want to restrict a directory on an Apache server to specific users, you will probably use an .htaccess/.htpasswd configuration. This allows you to add authentication to a directory or an entire site. The sad thing is, if I search for sample configurations on Google, five out of ten examples are insecure…

In fact years ago, I made the mistake of taking one of those sample configurations and used it on a site I had made. A typical .htaccess example you will find often looks like this:

AuthUserFile /var/www/.htpasswd
AuthName "My Private Files"
AuthType Basic
<limit GET POST>
require valid-user
</limit>

A rather straightforward example, so what is the problem? This configuration only partially restricts access to the ‘protected’ resource. The issue is in the <limit> tag. This tag restricts access to the resource if the request uses one of the specified HTTP methods, in this case GET and POST. Although these are the most popular methods, they certainly are not the only ones. RFC2616 (HTTP 1.1) lists eight methods: GET, POST, HEAD, OPTIONS, PUT, DELETE, CONNECT and TRACE. RFC2518 (WebDAV) adds a couple more. In other words, if you use one of the other one request methods, you can bypass the authentication. In some cases, using one of those methods will give you the protected page contents. You can also find plenty of examples (yes, the last one is nasa.gov) that don’t even limit GET and POST, but just GET, meaning a simple POST request will bypass authentication completely.

The solution? Simple, do not use the <limit> tag at all. If you omit it, all methods are restricted. If you are in a situation where you want to allow specific request methods, you should use <limitexcept>.

This is certainly not a new issue, it was documented in Apacheweek magazine in 1997. You can also find Bugtraq posts detailing instances of the issue, for example this one which describes an application that restricts only the GET method. If you want more details on this issue, Kernelpanik released a paper about it in 2004, you can find it here (pdf).

Monday, July 6, 2009

Speaking at HAR 2009

The program for HAR 2009 was publicly announced a couple of days ago and I’m on the speakers list. My talk is called 'How we break into domains' and I will go over the steps I usually take when breaking into Windows domains. I have an hour for my talk, so I should be able to cover the technical details as well. Of course, I will also be presenting some new stuff I’ve been working on.

I had a lot of fun at the two previous events (HAL 2001 and WTH 2005) and am glad I can contribute a talk this year. See you all at HAR!

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):

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.

Thursday, June 4, 2009

Slides of my OWASP talk on CSRF

Last week I gave a VAC (Vulnerability, Attack, Countermeasure) talk at an OWASP Netherlands meeting. I picked Cross-Site Request Forgery (CSRF) as a topic as it is an often misunderstood and underestimated problem.

My slides (in English) are available on the OWASP site here. I am planning on releasing another version of the slides in the OWASP template and with speaker notes for easier reuse. The last slide lists some good resources and interesting case studies (including more information on the case studies used in the presentation).