How to Verify the Validity of IIS Certificates on Remote Servers Using ABO
Nawal Kishore Gupta here. I am a developer on the Information Security Tools team focused on building host security assessment tools.
IIS: Admin Base Objects (ABO)
ABO is the most powerful way to control the IIS meta-base settings on different IIS Versions (above Windows 2000). Still using the ABO is a hidden art and very less technical document has been written on it.
One of the easy way is to read IIS Settings is read metabase.xml directly but this is not uniform in different version of IIS. Some of the confidential information has been moved to the registry. If you are developing a security or audit tool for IIS settings you must be interested in ABO.
Open Connection to ABO (IMSAdminBase Interface).
Creating a remote (DCOM) ABO connection is little tricky unless you know about DCOM. I am making it easy for you. Don’t forget to change the actual remote server name*.
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
//DCOM Object IMSAdminBase
CComPtr <IMSAdminBase> pIAdminBase;
IClassFactory * pcsfFactory = NULL;
COSERVERINFO csiMachineName;
...
csiMachineName.pwszName = L”ServerName” ; //Change it*
hr = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, &csiMachineName,IID_IClassFactory, (void**) &pcsfFactory);
hr = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &pIAdminBase);
Open Root Node Handle/Other Node Handle
METADATA_HANDLE hMetaDataRoot=NULL;
METADATA_RECORD mdrRoot;
HRESULT hRes = pIAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE, TEXT("/LM"),
METADATA_PERMISSION_READ, 20, &hMetaDataRoot);
Read Node Property
Some of the key index name is not defined in ABO header files. You can use the following definitions.
#define MD_SSL_CERT_HASH 5506
#define MD_SSL_STORE_NAME 5511
METADATA_RECORD-> dwMDIdentifier is the index of the property. You only need to change this index to read different properties of a node. “W3SVC/1” is the path of first website. In this sample I am reading the SSL Store Name. Generally the output of this will be “MY” if the site is using SSL.
BYTE buffer[BUFFER_LEN];
DWORD dwReturnBufferSize=0;
CString strStoreName;
mdrRoot.dwMDAttributes = METADATA_NO_ATTRIBUTES;
mdrRoot.dwMDUserType = IIS_MD_UT_SERVER;
mdrRoot.dwMDDataType = ALL_METADATA;
mdrRoot.dwMDDataLen = BUFFER_LEN;
mdrRoot.pbMDData = buffer;
mdrRoot.dwMDIdentifier = MD_SSL_STORE_NAME; // MD_SERVER_COMMENT or so
hRes = pIAdminBase->GetData(hMetaDataRoot, L"/W3SVC/1", &mdrRoot, &dwReturnBufferSize);
if (hRes==S_OK)
{
strStoreName= (WCHAR*)mdrRoot.pbMDData;
}
Read Certificate Binary Hash Property
For reading the certificate hash dwMDIdentifier should be set as MD_SSL_CERT_HASH and dwMDDataType should be set as BINARY_METADATA.
BYTE binSSLHash[MAX_CERT_SIZE];
DWORD dwBinHashSize;
mdrRoot.dwMDAttributes = METADATA_NO_ATTRIBUTES;
mdrRoot.dwMDUserType = IIS_MD_UT_SERVER;
mdrRoot.dwMDDataType = BINARY_METADATA;
mdrRoot.dwMDDataLen = MAX_CERT_SIZE;
mdrRoot.pbMDData = (unsigned char *)&binSSLHash;
mdrRoot.dwMDIdentifier = MD_SSL_CERT_HASH ;
//Read the first web site
hRes = pIAdminBase->GetData(hMetaDataRoot,L"/W3SVC/1", &mdrRoot, &dwBinHashSize);
if (!SUCCEEDED(hRes))
{
return hRes;
}
dwBinHashSize=mdrRoot.dwMDDataLen;
Now we have both the SSLStoreName and SSLCertHash. We can use this values to read the certificate from certificate store which I will cover in my next blog post!
Comments
Anonymous
June 01, 2009
PingBack from http://www.anith.com/?p=43374Anonymous
June 03, 2009
Mark Curphey here (Follow me using @curphey on Twitter ). June is a busy time of year around MSFT. ForAnonymous
June 21, 2009
pls making a easy code for me.