First of all, the TextBox
control is not a secure way to hold passwords - so don't use it as it is by default. Even with a PasswordChar
, the real password is still visible if you use a tool like Spy++.
The Flaw (Explained)
As an example, take a simple TextBox
with PasswordChar = '*'
.
Now, if you use Spy++ and inspect this application, you can get the password.
But...why does this happen?
Spy++ sends the message WM_GETTEXT (0x000D)
to the TextBox
, and the control just returns its value. It's actually working as intended and it reacts just like any other control, that obeys any message received.
Fixing this Issue...
I found a way to solve this by not allowing the TextBox
to process the 'malicious' messages. So the solution consists in blocking any WM_GETTEXT
message unless it was sent by the Text
property.
If the Text property is called, it will send an WM_GETTEXT
message, so it will surely be an internal (safe) call. But if that message is received and the Text
property wasn't called, then it might be risky to return the password, so we'll not process that message.
I wrote a "safer" TextBox
here, just to show you the idea, feel free to write your own or simply improve this one.
class ProtectedTextBox : TextBox
{
private const int WM_GETTEXT = 0x000D;
bool allowAccess { get; set; }
public override string Text
{
get
{
allowAccess = true;
return base.Text;
}
set
{
base.Text = value;
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_GETTEXT)
{
if (allowAccess)
{
allowAccess = false;
base.WndProc(ref m);
}
}
else
base.WndProc(ref m);
}
}