ASP Classic user login system password security considerations? - security

All,
I'm currently designing a user account system in ASP classic...don't judge, it's what I'm comfortable with ;). I have several of the components built already, including the UI, database table, CRUD database ASP pages and a generic mailer. I'm curious as to some of the best practices for implementing secure login systems for ASP. Searching the web yields a ton of "simple ASP security" solutions, which I've used before, but this is my first time time building a robust and truly secure solution. The final implementation will be used for a job application system, so it definitely needs to be secure due to the content.
So far, I have:
Password recovery/reset goes only to the e-mail account on file
Hash stored passwords in the database
Do not set an expiration on session cookies so they are only stored in memory (read this somewhere today)
Get a certificate for the server and use https
A couple general questions that I have...
Submitting the password in a form passes it through the query string. Do I need to hash this somehow prior to submitting the form?
On a related note... If I am using https, since it is already secure, can I do the hash on the ASP page that handles the write to the database? I'm using AJAX to parse the query string from the sending form and pass it to the ASP page which connects to the database and does the CRUD operations.

Password recovery/reset goes only to the e-mail account on file
Make sure your send a reset link expires after a certain time or after it has been used whichever comes first
Hash stored passwords in the database
Use salts instead of plain hashes. Hashes of most common passwords are as simple to break as a google search.
Do not set an expiration on session cookies so they are only stored in
memory (read this somewhere today)
This will make sure that the cookies are wiped out when the user closes the browser. In addition to this, also consider a timeout on the session cookie on the server side which will timeout the user session after x minutes of inactivity.
Get a certificate for the server and use https
At the minimum, the login credentials absolutely need to be passed over SSL. It will also help to have the entire website on https instead of just the login page. SSL is no longer computationally expensive anymore. Having the entire site over SSL prevents any sslstrip attacks. Make sure your server doesn't support SSLv3 to prevent the recent poodle attack.
Submitting the password in a form passes it through the query string.
Do I need to hash this somehow prior to submitting the form?
Please don't pass credentials over querystring. Login form should always be POSTed. It'll get cached in server logs (and any proxy logs) if tacked to the URL as a querystring.
If you are posting the form over https (which you absolutely should), you do not need to hash before submitting the form. If you are not using https, there is no way to pass the credentials to server securely.
On a related note... If I am using https, since it is already secure,
can I do the hash on the ASP page that handles the write to the
database? I'm using AJAX to parse the query string from the sending
form and pass it to the ASP page which connects to the database and
does the CRUD operations.
Hashing should ALWAYS be done on the server side. If you hash the password on the client side and send it in plain text over http, a MITM might not be able to reverse the password from the hash, but he can always use the same hash to log on to the user's account. The hash essentially becomes the plain text password of the user in this case.

Always use HTTP POST with SSL for sure.
Protect your asp code against sql injections.
Storing a local cookie with an encrypted token to keep your users logged in after they close the session/browser - or use asp sessions for a single login that could expire in 20 minutes after last request or when closing the browser.
Protect your cookies for cookie/session hijacking. (http://en.wikipedia.org/wiki/Session_hijacking)
Also, you can use finger prints of your users by requesting/storing/validating the server variables like (a part of) the user agent.

Related

Safe password transfer between client and server [duplicate]

This question already has answers here:
Is it worth hashing passwords on the client side
(13 answers)
Closed 2 years ago.
I'm reading a lot about security lately and something really bothers me.
I'm using Node.JS and I wanna store user data in the database. I currently hash the password on the server and then I save it to DB. But when the user sends data to the server he sends just plain text. I think that is the wrong approach. I'm using Bcrypt btw.
The method that I wanna use is: when a user need's to sign in I hash the password on the client, and then I send a hashed password with a salt to the server. The server then hashes the password again and stores the result in DB alongside with the first salt, that the user has passed. That means I have serverHash(userHash(userPassword)) and userSalt.
When the user then does log in, I wanna fetch him a userSalt from DB and hash his userPassword using that salt. Then I send userHash(userPassword) to the server and then compare userHash(userPassword) and serverHash(userHash(userPassword)).
Is this method good and secure, or is there a better way to do this, can I maybe use some third-party library or I can get away with this approach?
EDIT:
If someone bumps into this, don't do this, TLS will probably do the job, if not there are certificates that will help I think, I'm not 100% sure, but don't take my word for it but.
Purpose of Database Hashing Password
hashing password in server solve worries about accidental access to database.
where we consider server script are executing in a safe environment.
Authorized User can leak any data without protection
when a user login using username/password we will give him/her Authorization to Actions and view some Data .
if any crackers intrudes:
our server script
client browser or
intermediate media (network interception)
our goal (protect authorization) will be ruined.
so hashing the password on client-side dosen't solve any issue, if a
cracker can access to client-side area or intercept the traffic
data.
for example : an authorized admin, with heavy password protection mechanism,
can leak html data which tends to be admin-only viewable, if a cracker just intercepts network traffic.
Solution : Traffic Encryption
instead of sending hashed-password to server-side, The connection should get Encrypted like with SSL.
Todays Web Development
in Web Development its a good practice to to use HTTPS (Http+Ssl) when dealing with sensitive Data and Actions (scenarios which includes logins)
even in modern browsers, they show a Warning when dealing with html <input type='password'/> and not using Https.

Trying to understand login systems and sessions

Im trying to understand how a user can keep logged (i'm trying to implement this on Node without frameworks, for learning). Just a couple of questions based on what i think i understand:
(1) When the user tries to login, it sends the user and password in an HTTP request body
(2) When data arrives to the server, it checks everything needed like if the user exists and if the password is correct
And here comes, i think, my problem: How can the user keep logged? The third step would be something like:
(3) The server create all the session data needed, encrypts and send it to the client?
(4) The clients store the encrypted data in the localstorage
(5) The credentials are sended with every request to the server, and the server decrypts it and check it before processing every user's action.
That's what i understand. But i find this very extrange. I feel i missing a lot... storing data in client side doesn't seems (at least for me) secure. Should the session data be stored on server-side? And how the username and password should be sended securely? It must be encrypted client-side? Is this secure? I think im looking for some pattern or i don't know. I feel lost.
Yeah, and sorry my bad english and poor knowledge. Im not asking for code and i will also appreciate any hint (like what to search in google, or a interesting blog) :)
Thank you, y un abrazo :)
--- EDIT ---
Well, finally i founded some usefull links and solved great part of my doubts :)
[http://stackoverflow.com/questions/6922145/what-is-the-difference-between-server-side-cookie-and-client-side-cookie][1]
[http://blog.codinghorror.com/protecting-your-cookies-httponly/][2]
[http://www.cse.msu.edu/~alexliu/publications/Cookie/cookie.pdf][3]
[https://es.wikipedia.org/wiki/Cookie_(inform%C3%A1tica)][4]
[https://newspaint.wordpress.com/2015/09/06/how-to-get-cookies-from-node-js-http-response/][5]
1 and 2 are correct.
Sessions are usually implemented using cookies, not client-side local storage, because cookies are automatically sent to the server with each request. The cookie will often contain just a long randomly generated ID which refers to data stored on the server side, e.g. in a database. This data will identify the user and possibly store other session-level settings.
It is also possible to use a cookie with signed (and possibly encrypted) user information - for instance ASP.NET does this by default. This has the benefit that no storage is required for the session. The downside is that sessions cannot easily be destroyed from the server side. Therefore e.g. a feature that shows the user their currently active sessions (from other devices) and allows them to log them out couldn't be implemented.
Sending the username and password over the Internet should preferably be done securely, by using HTTPS. Do not implement your own encryption on the client-side. It will likely not work, plus the cookies themselves are viable to be stolen if the connection is not properly encrypted and authenticated.

Authentication system - is my one secure?

I want to authenticate my users based entirely on cookies and sql db.
What I do is:
1. Once they login, I generate a random string, create a hash from it, save it in the database along with the user id and his IP.
2. I send the hash to the user as cookie
3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
4. (As pointed by Akhil) If he clears his browser cookies or anything does not match the information on the database, I clear all the rows with his username and log him out.
Note: I use a session cookie for storing the random hash, which again is generated using the timestamp, and as long as time doesn't repeat itself(I believe), its random in the corect way.
Is this fine? How can I make it better?
Once they login, I generate a random string
Make sure you use a cryptographically secure method to generate the random string. Do not use mt_rand use something such as openssl_random_pseudo_bytes.
create a hash from it,
Make sure to use a secure hashing algorithm (not MD5, and at least SHA-2).
save it in the database along with the user id and his IP.
One thing to bear in mind is that some internet connections share IP addresses or will sometimes change the client IP address (e.g. AOL or mobile).
I send the hash to the user as cookie 3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
It sounds like a good way of doing it and there are no flaws in itself. I would implement a session timeout mechanism. For example, store the date last used in the DB for a sliding expiration and the query will only query records that have not expired. You could have a background process that runs to clear out old, expired records.
Also, use HTTPS and set the Secure and HttpOnly flags on the cookie. This will prevent them being leaked over HTTP, but I would not go as far as disabling HTTP on your system as there are workarounds for an attacker if it is anyway.
I would not be concerned with the cookie being stolen by another user on the same machine. If the cookie can be stolen in this way then the user's machine is probably compromised anyway and you cannot make your system protect data that is outside of your control. You could however renew the token (random string) on a periodic basis giving the user a rolling cookie. You would have to ensure only one user can be logged in at once under the same account though for this to be effective.
Your method only makes sure that the user possess the random string you generated and is using the same external IP address. There exists several way of abusing this system:
if your website doesn't enforce HTTPS then a user connecting using an unsecured public WiFi network could be at risk: if another user of the WiFi network is listening to all the packets being sent on the network, he could intercept your cookie and use it to access the website as your legitimate user. Your server would be unable to differentiate them because they'll both use the same IP address... (There is a Firefox extension available which enable anyone to intercept such login cookie easily: http://en.wikipedia.org/wiki/Firesheep)
This system is also more generally vulnerable to man in the middle attacks (without HTTPS)
If your cookie is stored on the user computer's hard drive it could be reused by another user.
So to answer your question, your system can be deemed as secured provided a few conditions:
you enforce the use of HTTPS on your website (unencrypted HTTP connections should be refused)
your random string is truly random (there exist right and wrong ways of generating random strings in PHP)
your cookie has a short expiry and preferably is set as a session cookie.
You should take a look at the following related question providing details about the proper way of doing what you want to do: How to secure an authentication cookie without SSL
One cannot say this is "bad". But in Web Development, and specifically in its security domain relativity talks. I recommend you to download a CodeIgniter (google it for more info) Session Class (standalone version) and use it. The basic idea is the same as yours, but it is properly more mature since it is developed in such a famous php framework. You can do your DB operations within that class too, since it allows session saving to DB.

How to resolve password hash complexity with HTTP basic auth?

Password hashes are stored as PBKDF2 with 512bits with 16384 rounds. This takes its time on my small server. Users are authorized with HTTP basic auth over SSL/TLS. With this setup every request requires to calculate the hash which puts a load on the server.
Current solution: After the first successful login I store a session cookie at client.
Pro: Minimal complexity that reduces time for hash calculation, still works for clients that do not store cookies
Cons: Clients that do not accepts cookies still create load.
Other ways to mitigate:
- Weaken password hash (doesn't feel right)
- Implement own/other authentication instead of basic auth (which one? adds complexity)
Priorities:
Security first, access to administration/monitoring is to be secured.
Then server load.
How to mitigate password hashing load? How to not sacrifice security? Is there an alternative to authentication without a secured channel (shared secret)?
Current solution: After the first successful login I store a session cookie at client.
This is the typical solution—either using actual stored sessions, or a signed user+timestamp token (HMAC being faster to verify than bcrypt).
It also solves the problem of HTTP Auth only being sent for pages under the same directory path as the first page that requested auth, and of the crazy browsers that don't re-send auth headers until prompted with 401 for every single request.
Cons: Clients that do not accepts cookies still create load.
Clients that don't accept cookies at all are relative rare and will break for almost all other sites that require a login, so for the common case you should generally be OK.
Implement own/other authentication instead of basic auth (which one? adds complexity)
If you are determined not to rely on cookies, the only other mechanisms I can think of with native browser support are Digest Auth (doesn't really solve the problem as it is still password-based) and HTTPS client certificates (may be an acceptable/convenient option depending on who your userbase are).

Username and password in https url

Consider the URL:
https://foo:password#example.com
Does the username/password portion in the above example qualify as a "URL parameter", as defined in this question?
When you put the username and password in front of the host, this data is not sent that way to the server. It is instead transformed to a request header depending on the authentication schema used. Most of the time this is going to be Basic Auth which I describe below. A similar (but significantly less often used) authentication scheme is Digest Auth which nowadays provides comparable security features.
With Basic Auth, the HTTP request from the question will look something like this:
GET / HTTP/1.1
Host: example.com
Authorization: Basic Zm9vOnBhc3N3b3Jk
The hash like string you see there is created by the browser like this: base64_encode(username + ":" + password).
To outsiders of the HTTPS transfer, this information is hidden (as everything else on the HTTP level). You should take care of logging on the client and all intermediate servers though. The username will normally be shown in server logs, but the password won't. This is not guaranteed though. When you call that URL on the client with e.g. curl, the username and password will be clearly visible on the process list and might turn up in the bash history file.
When you send passwords in a GET request as e.g. http://example.com/login.php?username=me&password=secure the username and password will always turn up in server logs of your webserver, application server, caches, ... unless you specifically configure your servers to not log it. This only applies to servers being able to read the unencrypted http data, like your application server or any middleboxes such as loadbalancers, CDNs, proxies, etc. though.
Basic auth is standardized and implemented by browsers by showing this little username/password popup you might have seen already. When you put the username/password into an HTML form sent via GET or POST, you have to implement all the login/logout logic yourself (which might be an advantage and allows you to more control over the login/logout flow for the added "cost" of having to implement this securely again). But you should never transfer usernames and passwords by GET parameters. If you have to, use POST instead. The prevents the logging of this data by default.
When implementing an authentication mechanism with a user/password entry form and a subsequent cookie-based session as it is commonly used today, you have to make sure that the password is either transported with POST requests or one of the standardized authentication schemes above only.
Concluding I could say, that transfering data that way over HTTPS is likely safe, as long as you take care that the password does not turn up in unexpected places. But that advice applies to every transfer of any password in any way.

Resources