[TOOL] SSL Key Password Retrieval Tool

From: support@securiteam.com
Date: 01/15/02


From: support@securiteam.com
To: list@securiteam.com
Date: Tue, 15 Jan 2002 09:30:22 +0100 (CET)

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -

  SSL Key Password Retrieval Tool
------------------------------------------------------------------------

DETAILS

Administrators can now retrieve that password that IIS 4.0 requires you to
use to create a certificate signing request, and then later to install the
certificate. Not only is this password pointless, but it is stored in
plain text in the IIS 4.0 metabase.

The program will display the key common name and password tab delimited to
STDOUT.

Tool source code:
/*
SSL Key Password Retrieval Tool
Extract the passwords used to generate
SSL Keys for IIS 4.0.
Author: Casey Zacek
Date: 01-09-02
Version: 1.0
Documentation/Instigator: Floyd Russell
Contact: floyd@floydsoft.com

Copyright 2002 Floyd Russell. All rights reserved.
It may be used and modified freely, but I do request that this copyright
notice remain attached to the file. You may modify this program as you
wish, but if you redistribute a modified version, please attach a note
listing the modifications you have made. And if it breaks anything
you can't sue me.

The most recent version and complete docs are available at:
  http://www.floydsoft.com

*/
#define UNICODE
#define INITGUID
#include <windows.h>
#include <wchar.h>
#include <objbase.h>
#include <ks.h>
#include <stdio.h>
#include <iadmw.h> // COM Interface header file.
#include <iiscnfg.h> // MD_ & IIS_MD_ #defines header file.
#include <atlBase.h> // ATL support header file.

#define ORIGINAL_BUFFER_SIZE 65536

#define HTAB_SIZE 517

typedef struct htab_elt {
    WCHAR *name; // SSL Key Name
    char *pass; // SSL Key Password
    struct htab_elt *next; // Pointer to next struct
} HTAB_ELT;

struct htab_elt *htab[HTAB_SIZE];

// Hash Key Names
int hash( WCHAR *key ) {
    int res = 0;

    while( *key ) {
        res += *key++;
    }
    res %= HTAB_SIZE;
    return res;
}

// Store Key Name/Password pair in hash table
void store( WCHAR *key, char *data ) {
    struct htab_elt *e;
    int h = hash( key );

    if( htab[h] == NULL ) {
        htab[h] = e = (struct htab_elt *)malloc( sizeof(struct htab_elt)
);
    } else {
        e = htab[h];
        while( 1 ) {
            // Prevent storing a key multiple times (if it has multiple
bindings)
            if( wcscmp( e->name, key ) == 0 ) {
                return;
            }
            if( e->next == NULL ) {
                break;
            } else {
                e = e->next;
            }
        }
        e->next = (struct htab_elt *)malloc( sizeof(struct htab_elt) );
        e = e->next;
    }

    int len = wcslen( key );
    e->name = (WCHAR *)malloc( (len+1) * sizeof(WCHAR) );
    wcscpy( e->name, (const WCHAR *)key );

    len = strlen(data);
    e->pass = (char *)malloc( (len+1) * sizeof(char) );
    strcpy( e->pass, (const char *)data );

    e->next = NULL;
}

// Initialize hash table
void init_htab() {
    int i;
    for( i = HTAB_SIZE; i--; ) {
        htab[i] = NULL;
    }
}

void main() {
    HRESULT hr = 0;
    HRESULT hr2 = 0;
    DWORD i = 0;
    METADATA_HANDLE hand;
    METADATA_HANDLE hand2;
    WCHAR SubKeyName[METADATA_MAX_NAME_LEN];
    WCHAR *tmp_n = NULL;
    char *tmp_p = NULL;
    struct htab_elt *e;
    CComPtr <IMSAdminBase> pIMeta;

    init_htab();
    CoInitialize( NULL );
    hr = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL,
IID_IMSAdminBase, (void **) &pIMeta);

    if( FAILED(hr) ) {
        printf( "hr = CoCreateInstance() FAILED! (hr = 0x%x)\n", hr );
        return;
    }

    // Get a handle to the local machine metabase.
    hr = pIMeta->OpenKey( METADATA_MASTER_ROOT_HANDLE, TEXT("/LM"),
      METADATA_PERMISSION_READ, 20, &hand );

    // Loop until there are no more subkeys.
    while( SUCCEEDED(hr) ) {

        // Enumerate the subkeys of the w3svc.
        hr = pIMeta->EnumKeys( hand, TEXT("/W3SVC/SSLKeys"), SubKeyName, i
);

        if( SUCCEEDED(hr) ) {
            DWORD j = 0;
            WCHAR tmp[METADATA_MAX_NAME_LEN];
            METADATA_RECORD rec;
            DWORD buflen = ORIGINAL_BUFFER_SIZE;
            PBYTE buf = new BYTE[buflen];
            buflen = 0;

            // 5500 = certificate
            // 5501 = private key
            // 5502 = password
            // 5503 = request
            // 5504 = key name
            // 5505 = expiration date?
            wsprintf( tmp, L"%s/%s", TEXT("/W3SVC/SSLKeys"), SubKeyName );
            hr2 = pIMeta->OpenKey( METADATA_MASTER_ROOT_HANDLE,
TEXT("/LM"),
              METADATA_PERMISSION_READ, 20, &hand2 );
            if( FAILED(hr2) ) {
                printf( "OpenKey(/LM/W3SVC/SSLKeys/%s) FAILED! (hr2 =
0x%x)\n", hr2, SubKeyName );
                continue;
            }
            while( SUCCEEDED(hr2) ) {
                rec.dwMDAttributes = METADATA_INHERIT;
                rec.dwMDUserType = IIS_MD_UT_SERVER;
                rec.dwMDDataType = ALL_METADATA;
                rec.dwMDDataLen = ORIGINAL_BUFFER_SIZE;
                rec.pbMDData = buf;
                hr2 = pIMeta->EnumData( hand2, tmp, &rec, j, &buflen );
                if( SUCCEEDED(hr2) ) {
                    DWORD sz = rec.dwMDDataLen;
                    DWORD id = rec.dwMDIdentifier;
                    if( id == 5502 ){
                        if( tmp_n == NULL ) {
                            int len = strlen( (const char *)rec.pbMDData
);
                            tmp_p = (char *)malloc( (len+1) * sizeof(char)
);
                            strcpy( tmp_p, (const char *)rec.pbMDData );
                        } else {
                            store( tmp_n, (char *)rec.pbMDData );
                            free( tmp_n );
                            tmp_n = NULL;
                            tmp_p = NULL;
                        }
                    } else if( id == 5504 ){
                        if( tmp_p == NULL ) {
                            int len = wcslen( (const WCHAR *)rec.pbMDData
);
                            tmp_n = (WCHAR *)malloc( (len+1) *
sizeof(WCHAR) );
                            wcscpy( tmp_n, (const WCHAR *)rec.pbMDData );
                        } else {
                            store( (WCHAR *)rec.pbMDData, tmp_p );
                            free( tmp_p );
                            tmp_n = NULL;
                            tmp_p = NULL;
                        }
                    }
                }
                j++;
            }
        }

        // Increment the index.
        i++;
    }

    // Release the handle to the local machine metabase.
    pIMeta->CloseKey( hand );
    // Print results as keyname tab password
    for( i = 0; i < HTAB_SIZE; i++ ) {
        e = htab[i];
        while( e != NULL ) {
            wprintf( L"%s\t", e->name );
            printf( "%s\n", e->pass );
            e = e->next;
        }
    }
    fflush(stdout);
}

ADDITIONAL INFORMATION

The information has been provided by Casey Zacek and
<mailto:floyd@NEOSPIRE.NET> Floyd Russell.

========================================

This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • Re: hash table idea good or no good?
    ... > want to store an item, and the tables 1..k are already full. ... not Oas expected from the hash map. ... hashmap_put(struct hashmap *h, void *key, void *data) ...
    (comp.programming)
  • Re: Lock method for 1 million items
    ... If two objects hash to the same rwlock then you only have to take ... Just imagine what happens in case of a hash collision when you use a set... ... void add{ ... has the effect of making the rwlock table only hold 2 locks. ...
    (comp.programming.threads)
  • Re: manipulating void* in array
    ... >> A question about void*. ... I have a hash library where the hash create ... >> is always of the same pointer type ... I think the array of void* has to be adressed as void*; ...
    (comp.lang.c)
  • Re: hash table idea good or no good?
    ... > The key is a void * that will be passed to a user defined hash function ... > for generating the hash value. ... >>will end up with the table full with 17 entries. ...
    (comp.programming)
  • Re: GCC 4.x random code generator for x86_64 ?
    ... to a header file results in something which is beyond me. ... uids and there is a bunch of places in gcc where hash tables are traversed ... of tables hashed by decl uids are far less severe - gcc makes no promises ...
    (Linux-Kernel)