
Introduction
Automated and Dictionary attacks to login is a security threat that every IT is quite aware of. There are many techniques that help address this problem, one of which is the CAPTCHA - an image that contains characters and/or numbers that presumably only humans can read; its value is then entered by the user manually. This helps filter out automated logins. However, this technique can be quite difficult to implement and also costly because you would have to generate image on the fly. Further, some software are designed to figure out the value on the image using technologies similar to OCR scanning. Although CAPTCHA may work most of the time, like I said, it is difficult, expensive, and does not work all the time, plus, requires your user to enter yet another value from an already difficult to read text.
Background
I began thinking about this problem and wanted to come up with a solution that...
- Is easy to implement
- Cost effective (needs no image generation on the fly)
- Does not require user to read and input another text box
- Works! (Of course, there is no such thing as 100% secure or unbreakable)
Suddenly, it dawned upon me when I started thinking like a hacker that if I wanted to automatically try to login using brute force, I would have to continuously generate different user ID and password combinations until I find the one that will get me through, but what is common in this? The keys! Let me explain... for example, if the login page contains two text boxes, one named "userid" and the other "password", all I have to do is submit values to these fields, something like http://address/loginpagename.aspx?userid=John&password=cool, and keep on changing the values "John" and "cool" until I find the right combination and I will get in. The keys that are common in this scenario are "userid" and "password". What if these keep changing every time you make a submit attempt? You would never know which key to provide the value to, hence cripple the key-value combination attack altogether!
Using the code
The basic idea in accomplishing this is to assign a different name to the userID text box and password text box every time the page is loaded, either by first loading or a postback is triggered. To make sure that the keys (the names assigned to the userID textbox and password textbox) are unpredictable, I elected to use GUID. There are four parts to this technique.
Part 1: UserIDKey and PwdKey private properties. (I use ViewState to store the assigned key instead of Session so that if the user spawns another instance of login page, each page would have its own keys.)
private string UserIDKey
{
get
{
if(ViewState["UserIDKey"] == null)
ViewState["UserIDKey"] = Guid.NewGuid().ToString();
return (string) ViewState["UserIDKey"];
}
set
{
ViewState["UserIDKey"] = value;
}
}
private string PwdKey
{
get
{
if(ViewState["PwdKey"] == null)
ViewState["PwdKey"] = Guid.NewGuid().ToString();
return (string) ViewState["PwdKey"];
}
set
{
ViewState["PwdKey"] = value;
}
}
Part 2: Assign new names to the text boxes when the page is first loaded.
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
MakeFieldNamesSecret();
}
}
private void MakeFieldNamesSecret()
{
txtPwd.ID = PwdKey;
txtUserID.ID = UserIDKey;
}
Part 3: Validation. When the Submit button is clicked, retrieve the values of the two text boxes to validate.
private void btnLogin_Click(object sender, System.EventArgs e)
{
string userID = Request.Form[UserIDKey];
string pwd = Request.Form[PwdKey];
if(userID == "John" && pwd == "cool")
Server.Transfer("PostLoginPage.aspx");
else
lblErr.Text = "Invalid UserID or Password";
}
Part 4: Change the names of the text boxes on postback. This is what really prevents the key-value attack!
private void LoginPage_PreRender(object sender, System.EventArgs e)
{
if(IsPostBack)
{
UserIDKey = null;
PwdKey = null;
MakeFieldNamesSecret();
}
}
Points of Interest
What I found to be very interesting is the magic of thinking outside the box. What most people are doing trying to solve this problem is how to make the input values more difficult to automate, but few, perhaps thought about changing the variable that takes the value. With this very simple technique, I think I have solved a real problem. What do you think?
History
First revision: January 5, 2005.
|
|
 |
 | My vote of 1 small_programmer | 21:27 1 Nov '09 |
|
|
 |
 | Doesn't work delucia | 11:19 25 Sep '06 |
|
 |
The scripter and get the page first, find the read the generated IDs and then do a post with them.
|
|
|
|
 |
 | Download page once, use many times Vladimir_Davidov | 4:41 1 Apr '05 |
|
 |
Well actually this aproach is not very good to my mind, coz a hacker or whoever it will be, can download the page once (with all the keys in the viewstate) and then, after developing quite a simple programm, submit the page with the non changeable viewstate to the server as many times as one wants (as for example Application Center Test does that). Correct me if I'm wrong.
|
|
|
|
 |
 | Great Script infecting | 20:08 20 Feb '05 |
|
 |
To: Oblacek Why would you want the browser to repeatedly remember your username and password? You will only login once or you love to test the login system so much or logout so frequently that you want the browser to 'remember'. I guess 'that' really is a pain in the ass. Well, I sort of know what you are asking, but Real-World usage is that legitimate user will probably login once only. So to improve on security, let make it a pain in your ass, okay? Okay.
To: MorgP Microsoft has no intention to hide the true value of ViewState, hacker can hack all they want. But true hacker won't be terribly interested in ViewState either. So guess what!! You are right, err Nothing is Gained. Cool.
To: _BOFH_ Nobody says it is easy! But it is no dead end either. 3 times automatic logout is a requirement from the client, not a requirement from the code. This script won't address this issue and yup, CAPTCHA!!?? I really never saw it in login page.
To: Anonymous What the heck are you talking? Search for text called "User name", use "Username/Password" image?? And with random names?? Well you mean unique GUID which JohnnyUSA has so randomly...err sorry uniquely generated? Care to really re-phrase? The only real problem you are addressing is the JavaScript access to form using indexing, but well that is being address by other user...boring
To: Tom Celuszak Nothing to say
To: Phan Dung The ViewState is really just that, a state for every public to view. It is free. Just, you know encoded in a way to compact the state information and also to make it look cool and nice. And I agreed with you that this script is quite cool...
To: Yitzhak Gootvilig Yup and you should encrypt your HTML also. And dun forget the JavaScript. Encrypting ViewState is plain silly. Common!! you have a GUID generated field called "f5e67052-e906-4bee-a16a-8dd92060bdc6" and that is supposed to represent UserID. We encrypt this GUID and then stored it in ViewState, let's say the encrypted ViewState is now "hehehaha456". Does this encrypted ViewState represent the field name?? DOES IT?? What the hell. It does and you want to encrypt it for WHAT!!! Well encryption do make ViewState more secure, but isn't tamper-proofing's what we want here?
To: DejaVudew Damn! the Back Button is truly evil. Well, this script is used to combat automated software from repeatedly injecting dictionary data into the form page assuming the field name is the same throughout. With the Back Button, then i guess a simple JavaScript can always be customized to automate that process. sh*t ME!! Please tell me I still can use this script!!
To: POMARC The attacker has to get the correct authenticated cookie, modify the ViewState correctly as to not trigger tampering protection, and POST the data and hope that the Page_Load() is well sleeping and not doing its duty!!
To: Uwe Keim So how do we sovle the damn DOM and JavaScript accessibility problem..those index...
To: Johnny USA Way to go. A Great Idea. Cool...and please improve on it and post again.. Really how would you solve the DOM/JavaScript Index problem man....
To: Anonymous THIS WILL WORK!!! You just need to.. you know "think out of your #$%ing Brain-Box".
|
|
|
|
 |
 | Stored usernames Oblacek | 1:10 23 Jan '05 |
|
 |
With this techique, the user's web brower can't store and remember the username and the password for the next use, so the user must type his username and password each time. This is a pain in the ass, if you ask me.
|
|
|
|
 |
 | Nothing is gained. MorgP | 11:18 16 Jan '05 |
|
 |
The viewstate is a simple base64-encoded string which is accessible from the client so its a simple call to System.Convert.FromBase64String to get the real string.
|
|
|
|
 |
 | This is going to be difficult indeed _BOFH_ | 22:08 14 Jan '05 |
|
 |
Very interesting idea, but I'm afraid you are in a dead end. Implementing client side security is not very safe. Would'nt it be much easier to implement a solution that works on the server side. If a user has provided a wrong password a configurable number of times in a configuramble ammount of time, lets say 5 times in 5 minutes then that account will be locked for another configurable ammount of time - say 2 hours.
In this approach, given the above parameters, a hacker cannot check for more than approximately 60 passwords in a day.
But is this really the intent for CAPTCHA? When I see CAPTCHA images it is more often when I wish to create an account or when trying to retrieve one of my forgotten passwords to my own email address. I have never seen CAPTCHA images when I try to log in.
My two cents...
|
|
|
|
 |
 | Won't work Anonymous | 5:16 14 Jan '05 |
|
 |
the bad guy just has to parse the HTML DOM and search for the text "User name" that you render in HTML to the user. You need to make the Username/Password image elements which have random names. Also as another user stated, field order is predictable, so you are hosed as again if you parse the HTML DOM, you can predict stuff.
|
|
|
|
 |
 | Switch off/on for stress testing? Tom Celuszak | 7:05 13 Jan '05 |
|
 |
You'd want to consider that stress testing tools need to know the field names, so perhaps a switch to turn this feature off and on would be helpful.
|
|
|
|
 |
 | Interesting approach Phan Dung | 16:18 12 Jan '05 |
|
 |
Creative solution! There is a suggestion: the ViewState for userID & password is stored in a hidden field in the webform. What happen if the hacker uses the content of these hidden fields & post them back each time he attempt to guest the userid and password?
:-DAnyway, this approach is very interesting.
|
|
|
|
 |
 | Encrypt Yitzhak Gootvilig | 6:37 10 Jan '05 |
|
|
 |
 | Back button DejaVudew | 4:09 10 Jan '05 |
|
 |
Couldn't I just use the back button and use the same keys again?
|
|
|
|
 |
 | just a get away? POMARC | 1:34 10 Jan '05 |
|
 |
Your approach is indeed interesting, but tell me if I got it wrong. An attacker could get the page, parse it to understand the keys and then do the post. If I am right your technique just added one get for each try. Right?
|
|
|
|
 |
 | The Order is constant Uwe Keim | 21:17 9 Jan '05 |
|
 |
Very interessting approach.
Yet, even if the names change, the order of the controls is constant. I.e. if I would need a script, I do not access by name, but by index.
To accomplish this, you could add additional, unused text boxes, maybe hidden by HTML or JavaScript or something like that (just an idea).
-- Affordable Windows-based CMS: www.zeta-producer.com
|
|
|
|
 |
|
 |
Thank you for your feedback. I have indeed thought of that and will be working on it, and a few other glitches, when I upgrade this into a web control.
JohnnyUSA
|
|
|
|
 |
|
 |
The viewstate is hackable so this will never work.
|
|
|
|
 |
|
 |
That's a big mistake, if you don't read the form fields by name, the hacker can post it's value by any name! Although this solution doesn't work as other user mentioned the hacker can read the fields many times and post them... but it was a nice try and these tries are good
|
|
|
|
 |
|
|
Last Updated 9 Jan 2005 |
Advertise |
Privacy |
Terms of Use |
Copyright ©
CodeProject, 1999-2010