Теория и практика восстановления паролей Internet Explorer

Классифицируем типы хранимых в Internet Explorer приватных данных, познакомимся с программами для их восстановления и посмотрим взятые из реальной жизни примеры восстановления утерянных паролей.

20.07.2007 08:47,
Страницы: Пред. 1 2 3 4 След.

Данные автозаполнения форм

Отдельной строкой следует сказать о механизме автозаполнения on-line форм, который представляет собой гибридный вариант хранения данных. При этом сами данные хранятся в PS, а URL, которому они принадлежат - в реестре пользователя. Записываемый в реестр URL хранится не открытым текстом, а в виде хэша. Вот алгоритм чтения данных автозаполнения форм IE 4 - 6: 

//Get autoform password by given URL

BOOL CAutoformDecrypter::LoadPasswords(LPCTSTR cszUrl,

CStringArray *saPasswords)

{

assert(cszUrl && saPasswords);

saPasswords->RemoveAll();

//Check if autoform passwords are present in registry

if ( EntryPresent(cszUrl) )

{

//Read PStore autoform passwords

return PStoreReadAutoformPasswords(cszUrl,saPasswords);

}

return FALSE;

}

//Check if autoform passwords are present

BOOL CAutoformDecrypter::EntryPresent(LPCTSTR cszUrl)

{

assert(cszUrl);

DWORD dwRet, dwValue, dwSize=sizeof(dwValue);
LPCTSTR cszHash=GetHash(cszUrl);

//problems computing the hash
if ( !cszHash )
return FALSE;

//Check the registry
dwRet=SHGetValue(HKCU,_T(”Software\\Microsoft\\Internet
Explorer\\IntelliForms\\SPW”),cszHash,NULL,&dwValue,&dwSize);
delete((LPTSTR)cszHash);

if ( dwRet==ERROR_SUCCESS )
return TRUE;

m_dwLastError=E_NOTFOUND;
return FALSE;
}

//retrieve hash by given URL text and translate it into hex format
LPCTSTR CAutoformDecrypter::GetHash(LPCTSTR cszUrl)
{
assert(cszUrl);

BYTE buf[0×10];
LPTSTR pRet=NULL;
int i;

if ( HashData(cszUrl,buf,sizeof(buf)) )
{
//Allocate some space
pRet=new TCHAR [sizeof(buf) * sizeof(TCHAR) + sizeof(TCHAR)];
if ( pRet)
{
for ( i=0; i<sizeof(buf); i++ )
{
// Translate it into human readable format
pRet[i]=(TCHAR) ((buf[i] & 0×3F) + 0×20);
}
pRet[i]=_T(’\′);
}
else
m_dwLastError=E_OUTOFMEMORY;
}

return pRet;
}

//DoHash wrapper
BOOL CAutoformDecrypter::HashData(LPCTSTR cszData, LPBYTE pBuf,
DWORD dwBufSize)
{
assert(cszData && pBuf);

if ( !cszData || !pBuf )
{
m_dwLastError=E_ARG;
return FALSE;
}

DoHash((LPBYTE)cszData,strlen(cszData),pBuf,dwBufSize);
return TRUE;
}

void CAutoformDecrypter::DoHash(LPBYTE pData, DWORD dwDataSize,
LPBYTE pHash, DWORD dwHashSize)
{
DWORD dw=dwHashSize, dw2;
//pre-init loop
while ( dw–>0 )
pHash[dw]=(BYTE)dw;

//actual hashing stuff
while ( dwDataSize–>0 )
{
for ( dw=dwHashSize; dw–>0; )
{
//m_pPermTable = permutation table
pHash[dw]=m_pPermTable[pHash[dw]^pData[dwDataSize]];
}
}
}

Следующее, седьмое поколение браузера, по всей видимости, собирается сделать этот механизм хранения информации пользователя главным, отказавшись от старого и доброго Protected Storage. Проще говоря, данные и пароли для автозаполнения теперь будут храниться тут.

Что же такого особенного и интересного в этом механизме, что MS решил использовать его в качестве основного? А прежде всего самой идеей шифрования, отнюдь не новой, но простой и гениальной до безобразия. Ее суть состоит в том, чтобы не хранить ключи шифрования данных, а формировать их по мере необходимости. В качестве исходного материала для таких ключей служит Web адрес html страницы.

Давайте посмотрим, как все это реализовано на практике. Ниже представлен упрощенный алгоритм работы IE7 при сохранении данных или паролей автозаполнения:

  1. Запоминаем адрес Web страницы. В дальнейшем этот адрес будет использоваться в качестве ключа шифрования (EncryptionKey).
  2. Получаем ключ записи RecordKey. RecordKey = SHA(EncryptionKey).
  3. Подсчитываем контрольную сумму RecordKey для проверки целостности ключа записи (целостность самих данных нам будет гарантировать DPAPI). RecordKeyCrc = CRC(RecordKey).
  4. Шифруем данные ключом шифрования EncryptedData = DPAPI_Encrypt(Data, EncryptionKey).
  5. Сохраняем в реестре RecordKeyCrc + RecordKey + EncryptedData.
  6. “Забываем” EncryptionKey.

Без знания оригинального адреса Web страницы, восстановить пароль очень и очень сложно. Расшифровка выглядит довольно тривиально:

  • При посещении оригинальной Web страницы, берем ее адрес (EncryptionKey) и получаем ключ записи RecordKey = SHA(EncryptionKey).
  • Проходим по списку всех ключей записи в поиске RecordKey.
  • Если RecordKey найден, расшифровываем данные, которые хранятся вместе с этим ключом, с помощью EncryptionKey. Data = DPAPI_Decrypt(EncryptedData, EncryptionKey).

Не смотря на свою кажущуюся простоту, этот алгоритм шифрования Web паролей является одним из самых сильных на сегодняшний день. Но у него есть один существенный недостаток (или достоинство, смотря с какой стороны посмотреть). Если изменить или забыть оригинальный адрес Web страницы, то восстановить пароль к ней будет невозможно.

Пароль Content Advisor

Последний в нашем списке - пароль Content Advisor (пароль-допуск в Русской нотации). Изначально Content Advisor разрабатывался как средство разграничения доступа к сайтам. Но почему-то стал нелюбим многими пользователями (можете с этим не согласиться). Если вы однажды включили Content Advisor, ввели пароль, а потом забыли его, то не получите доступа к большинству сайтов интернета. К счастью или несчастью это легко исправить.

Сам пароль Content Advisor не хранится в явном виде. Вместо этого, подсчитывается его MD5 хэш и записывается в реестре Windows. При проверке, введенный пароль хэшируется и полученный хэш сравнивается с тем, что хранится в реестре. Посмотрите исходный текст проверки пароля Content Advisor, взятый из программы PIEPR: 

void CContentAdvisorDlg::CheckPassword()

{

CRegistry registry;

//read the registry

registry.SetKey(HKLM,

“SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\Ratings”);

BYTE pKey[MD5_DIGESTSIZE], pCheck[MD5_DIGESTSIZE];

if ( !registry.GetBinaryData(”Key”,pKey,MD5_DIGESTSIZE) )

{

MessageBox(MB_ERR,”Can’t read the password.”);

return;

}

//Get one set by user

CString cs;

m_wndEditPassword.GetWindowText(cs);

MD5Init();

MD5Update((LPBYTE)(LPCTSTR)cs,cs.GetLength()+1);

MD5Final(pCheck);

//Check hashes

if ( memcmp(pKey,pCheck,MD5_DIGESTSIZE)==0 )

MessageBox(MB_OK,”The password is correct!”);

else

MessageBox(MB_OK,”Wrong password.”);

}

}

Первая мысль, которая может возникнуть, это попытаться подобрать пароль путем атаки перебором или по словарю. Однако есть более элегантный способ. Можно просто удалить хэш из реестра. И все… Еще лучше не удалять его совсем, а переименовывать. Чтобы при случае можно было восстановить обратно. Некоторые программы позволяют также делать проверку пароля Content Advisor, вытаскивать подсказку о пароле, включать/отключать его непосредственно и т.д.

Страницы: Пред. 1 2 3 4 След.
Оцените материал:  
(Голосов: 7, Рейтинг: 3.07)

Каждый вечер мы будем присылать вам одно письмо со всеми опубликованными за день материалами. Нет материалов - нет писем, просто и удобно (другие варианты).

Материалы по теме


Комментарии (0)