|
| ||||||||||||||||||||||||||||
![]() Dominik Reichl's Homepage |
|
|||||||||||||||||||||||||||
|
Information about me, how to
contact me and the imprint.
Open-Source applications, free C++
classes and other free sources.
Articles, papers, publications
and other texts.
» Download demo project - 72 Kb » Download source - 18 Kb
Index:» Introduction » Features and Limitations » Using the Control » Technical Background / How It's Working » References » Version History IntroductionAlmost all Windows applications dealing somehow with passwords are using the standard Windows edit controls with the password flag set. Unfortunately, these controls aren't that secure by default. This article is an attempt to improve its security.In Windows 95 and 98, applications were able to send a WM_GETTEXT message to the edit
controls to get the password, just like getting the text out of a normal edit control.
This itself isn't bad, but Windows allowed you to send WM_GETTEXT messages to
other applications, too. You just sent such a message to all other windows
and easily got all passwords.In Windows NT/2000/XP, this bug has been fixed. You cannot use WM_GETTEXT messages
any more to get the passwords out of other applications (still working when the
application owning the control sends the message). But some people developed
new methods to get the sensitive texts. One approach for example is injecting
some code into the target process using Windows hooks. The injected code
is in the process memory of the target application then and is able to call
the WM_GETTEXT messages. The code
then can do whatever it wants with the password. For implementation details of this
method, see [1]. So, the password edit controls in Windows NT/2000/XP aren't that
secure either.In my previous article [2], I've solved this problem already. Now, the CSecureEditEx control goes one step further: process
memory protection.The Windows standard edit controls and my previous CSecureEdit control store
the passwords as plain-text in the process memory. My previous class did protect the window of
the control: WM_GETTEXT messages didn't work. Anyway, even the improved control stored
the password plainly in the memory.If Windows caches your process into the swap file, you're out of luck with these controls: the password is written plainly to the swap file, possibly lying around there for days. Of course, it's not a simple task for an attacker to find the password in the swap file, but why not making it even harder for him? The new CSecureEditEx control does this: even if Windows caches your process
to disk, the passwords aren't visible in plain-text.You'll see that the CSecureEditEx control not only introduces the new process
memory protection, but also some limitations. That's the main reason why I'm posting
a new article and not just updating the CSecureEdit control.Features and LimitationsFeatures of theCSecureEditEx control:
But since we're making password edit controls, selections aren't that required anyway. Users normally delete the whole entered text when they notice that they typed some wrong key. For this, most people use Shift-Home to select the whole text. Exactly this combination clears the whole control, so there aren't any real usability disadvantages. Using the ControlUsing theCSecureEditEx control is pretty simple. Just follow these steps:
The last step is optional. It won't lower security if you don't set this flag, but some context menu operations like copying the text are possible then (they won't work, therefore it would be just nice to show those items grayed). I recommend enabling the ES_PASSWORD
style.Now, how do you get the entered password out of the control, if the WM_GETTEXT message doesn't work
any more? DDX to CStrings doesn't work any more, too. You have to use the following member function:
LPTSTR CSecureEditEx::GetPassword()This returns the entered text as a LPTSTR pointer. Be very careful what you are doing with it! Don't just copy it to some other location, the whole security improvement would be lost then! You are of course allowed, for example, to hash the text with a one-way hash function (SHA-1) and store the hash. When you've processed the password, you need to free the pointer, i.e. securely erase and free the memory! Use the following member function to accomplish this: void CSecureEditEx::DeletePassword(LPTSTR lpPassword)Pass the LPTSTR pointer returned by the GetPassword() function to this function.
It will securely erase and free the memory. The lpPassword pointer then is invalid after
the execution of the function.Mostly you will want to set a password as default. The WM_SETTEXT message doesn't work, you need
to call the following function in order to set the current password:
void CSecureEditEx::SetPassword(LPCTSTR lpPassword)This sets the current password to the string lpPassword points to. If you pass
NULL as parameter, the edit control is cleared (i.e. simply no text).Technical Background / How It's WorkingTheCSecureEditEx internally keeps an array of pointers to single
TCHARs. These TCHARs are XORed with some fixed character that
is generated randomly in the constructor of the class. So, the characters aren't just
spreaded over the process memory, they are additionally XORed with some random
character.When the user presses a key, the control looks what has changed. If the contents of the control are shorter than before, the user has deleted something. In this case, it gets the current cursor position and calculates how many characters have been deleted. It then frees the internal memory pointers (first sets the single characters to 0) and removes them from the pointers list. If there are more characters than before, those characters are extracted and added: first allocate the memory for the characters, XOR them with the appropriate value and insert the pointer to this location to the pointers list. As you can see, the control uses the cursor position to see what happened. In order to get this working correctly, the user must not select any range of characters. If he would do this, we couldn't determine the operation and changed characters correctly. Therefore, the control prevents all selecting methods (selecting using Shift and cursor keys, selecting using the mouse, etc.) To clear the whole control, the user can just press Shift-Home or Shift-End. This clears the control. References[1] Brian Friesen: PasswordSpy - Retrieving lost passwords using Windows hooks.[2] Dominik Reichl: Secure Edit Controls - Secure Edit controls that are resistant to password revealers. Version History
|
|
||||||||||||||||||||||||||