Password protected website with JavaScript - javascript

I have a quetion which may be simple/dumb or not :). In other words I have no idea if is fair enough or a completely foolish idea. Just some free thoughts.
What if I make my login via JavaScript with pass in it (yes I know), but pass will be hased by Secure Hash Algorithm. For instance:
I generate a pass with SHA which looks like
var = 0xc1059ed8... //etc
and paste into the code. There will be also two functions. One will compare two values (given by me with user's) and second will generate sha form user's input.
Is this could be safe theoritically or this is a horrible pattern and stupid idea? Can JS handle it?
EDIT: I didn't mean serious autentication like banking one. Just when I have my pics and want only to a few ppl to watch them and 99,9% of ppl on earth can't watch them :)
thx for responses

Sorry, no dice :) Secure authentication is not possible with client-side Javascript alone, because a positive authentication result could be faked. You will always need a server-side instance to authenticate against.

The common answer is that 'no, you can't do client side authentication' and for conventional scenarios that is correct, but I can think of at least two ways to make it work:
Use the SHA password hash to redirect to a static HTML page (0xc1059ed8...html). As long as the virtual directory doesn't allow file listing, no one will be able to guess the name of the file you want to protect. This gets clumsy really fast though.
Use an implementation of an encryption algorithm (AES, etc) in Javascript to decrypt a block of text that makes up the actual content of your page. Really only practical for one highly valuable page though.
Server side authentication is really the best, but it is incorrect to say that client side can't be done.

You cannot secure your site with Javascript alone. You will need some way to authenticate requests on the server.
Because all your javascript code is plainly visible to all consumers of your site. All a potential attacker would need to do is view souce of your website and they can bypass the password checking bit of your javascript and view the content behind it.
You need to have security implemented on the server-side, period the end. ASP.NET has a built-in way to do this called "Forms Authentication." Or you could use Session variables in a php script.

Your JS source will be visible anyway and anyone can fake it easily. You have to do a server side validation

Since the hash will reside on the user's computer (in the browser), i'd say it's a terrible idea. It will be easy to manipulate it.

You can use such a pattern to hide the password over a plaintext link and avoid https to login , but not as it stands.
The problem is that an attacker can steal the hashed password and use that to login to the server, and she does not need the real password.
This can be thwarted by a challenge response where the server sends with the page a "salt" : a big random number which is jumbled up with the password and then hashed, so the response is always different.
Unfortunately this has the effect that the server now needs to have plaintext passwords, which is a bad idea (ok, there are some tricks around this). So you might have to end up with a sending a salt, hashing your password, jumbling the hash with the salt by hashing it again and sending that to the server. The server hashes the stored hash of the password from the user db with the salt and compares both.
With security things get complicated real quickly and in complicated things opportunities lurk for the bad guys. A reason more to use well tested patterns, algorithms with a proven track record and libraries which have carefully implemented these.
And in any case it will be the server hwo has final say who can get access.

You'd be better off with no attempt at authentication at all -- at least that way you wouldn't give anybody the dangerous illusion that something involved might be secure.
Assuming you're dealing with a shared-secret situation, authentication is really pretty easy. You use a fairly simple challenge-response algorithm. Basically, the client sends a message to the server saying it wants to log in. The server responds by sending back a random number. The client encrypts that random number with the correct password, and sends it back. The server encrypts the random number itself, and compares the result to what the client sent. If they match, authentication has succeeded -- you've confirmed that the client has the right password.
The advantages of this: first, the password itself is never sent over the wire in any form, so an attacker has virtually no material to use in attempting to discover the password. Second, since the server generates a new random number for every login, an attacker cannot successfully authenticate by re-sending the packets it captured from a previous login.
Nearly any server with any sort of aspirations to security will already have something like this built in. It's purely a question of setting up your client to interact correctly with the form supported by the server(s) you care about.

Related

How to make the password in the code that should be encrypted with JS only [duplicate]

When I want to put a login system in place, I always compare the MD5 of the given password with its value in the users table on the server side.
However, a friend of mine told me that a "clear" password could be sniffed by a network software.
So my question is: is it a good idea to hash the password on the client side? Is it better than hashing it on the server side?
Basically, your friend is right. But simply hashing the password on the client side is only just better than submitting it as plain text to the server. Someone, who can listen for your plain text passwords is certainly also able to listen for hashed passwords, and use these captured hashes him/herself to authenticate against your server.
For this matter, more secure authentication protocols usually jump through a number of hoops in order to make sure, that such a replay attack cannot work, usually, by allowing the client to select a bunch of random bits, which are hashed along with the password, and also submitted in the clear to the server.
On the server:
generate a few bits of random
send these bits (in clear text) to the client
On the client:
generate a few random bits
concatenate password, the server's random bits and the client random bits
generate hash of the above
submit random bits(in clear text) and hash to the server
As the server knows its own random information as well as the client's random bits (it got them as clear text), it can perform essentially the same transformation. This protocol makes sure, that nobody listening in this conversation can use the information later to authenticate falsely using the information recorded (unless a very weak algorithm was used...), as long as both parties generate different "noise bits" each time, the hand shake is performed.
Edit All of this is error prone and tedious and somewhat hard to get right (read: secure). If ever possible, consider using authentication protocol implementations already written by knowledgeable people (unlike me! The above is only from memory of a book I read some time ago.) You really don't want to write this yourself usually.
First of all, this does NOT improve the security of your application (assuming it is a web app).
Use SSL (Or actually TLS, which is commonly called SSL). It is free and easy to set up with Certbot.
The why to this is simple. TLS solves a problem (when used with a certificate from a certificate authority, not self signed) that is quite big in cryptography: How do I know the server I am talking to is the server I think I am talking to? TLS Certificates are a way of saying: "Me, the certificate authority, trusted by your browser, certifies that the website at [url] has this public key, with a corresponding private key, which (private key) only the server knows, look I signed my signature all over the document, if anyone altered it you can see".
Without TLS, any encryption becomes pointless, because if I sit next to you in a coffeeshop, I can make your laptop/smartphone think I am the server and MiTM (Man in The Middle) you. With TLS, your laptop/smartphone will scream "UNTRUSTED CONNECTION", because I don't have a certificate authority signed certificate that matches your site. (Encryption vs. Authentication).
Disclaimer: users tend to click right through these warnings: "Untrusted connection? What? I just want my pictures of kittens! Add Exception Click Confirm Click YAY! Kittens!"
However, if you really do not want to use a certificate, still DO implement client side Javascript hashing (and use the Stanford library (SJCL) for that, NEVER IMPLEMENT CRYPTO YOURSELF).
Why? Password reuse! I can steal your session cookie (which allows me to pretend to your server that I am you) without HTTPS easily (see Firesheep). However if you add Javascript to your login page which, before sending, hashes your password (use SHA256, or even better, use SHA256, send them a public key you generated and then encrypt hashed the password with that, you cannot use a salt with this), and then sends the hashed/encrypted password to the server. REHASH the hash on your server with a salt and compare that to what is stored in your database (store the password like this:
(SHA256(SHA256(password)+salt))
(save the salt as plaintext in the database as well)). And send your password like this:
RSA_With_Public_Key(SHA256(password))
and check your password like this:
if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok
Because, IF someone is sniffing your client, they will be able to login as your client (session hijacking) but they will NEVER see the plaintext password (unless they alter your Javascript. However, a Starbucks hacker will probably not know how or be interested in this.) So they will gain access to your webapp, but not to their email/Facebook/etc. (for which your users will likely use the same password). (The email address will either be their login name or will be found in their profile/settings on your web app).
Actually I disagree that client side hashing is more secure in this case. I think it's less secure.
The entire point of storing a hash of the password in your database as opposed to the real password (or even an encrypted password) is that it is mathematically impossible to obtain the original password from a hash (although it is theoretically possible to obtain a colliding hash input, the difficulty of which depends on the security strength of the hashing algorithm). The possible attack vector here is that if a potential attacker somehow compromised your password storage database, he/she still would not be able to obtain the original passwords of your users.
If your authentication mechanism sends a hash of the password, then in the "security breach" scenario (i.e. attacker somehow got a copy of your password database), the attacker does not need to know the real password - they just send the hashed password that they obtained from the breach and hey presto, they have access to that user's account. This completely defeats the point of storing a hashed password in the first place!
The really secure way to do it is to send the client a one-time public key for them to encrypt the password, then you decrypt and re-hash it on the server-side.
By the way, this kind of question will probably get more expert responses over on Security StackExchange.
You're likely OK not to worry about this - as Dirk mentions even if you hash the passwords a malicious user could be on a network and see the hash get sent, and could simply send the same hash themselves.
It is slightly better, in that it prevents the malicious user from knowing what the password is, but since they can still log in (or potentially reconstruct the original password), that's not that helpful.
In general, if you're concerned about the safety of your user's passwords and data (and you should be!), you'll want to use a secure SSL server. If this isn't a concern for you for whatever reason you might as well not bother with hashing; it's just security through obscurity.
Edit Aug 2014: Google is pushing more and more strongly for websites to switch to HTTPS everywhere, because securing the communication itself is the only way to prevent network sniffing attacks. Attempts at obfuscating the data transmitted will only hinder, not stop, a dedicated attacker, and can give developers a dangerous false sense of security.
Recently both GitHub and Twitter announced that passwords where stored in internal logs. I've had this happen inadvertently in bug reports and other logs that found their way into splunk etc. For twitter if Trump's password was in there log it could be a big deal for an admin to "see", for other sites probably not as big of a deal as the administrators wouldn't have much use for it. Regardless as admins we don't like seeing the passwords do we.
So the question is really if the hashing should happen client side for security, but how can we protect the password before it ultimately gets hashed and compared by the server side so it doesn't get logged somehow.
Encryption is not a bad idea because the developers at least have to jump through some hoops, and if you find that passwords got into logs you can just change the encryption key, destroy the original, and that data becomes useless. Better yet rotate the keys nightly and it could reduce the windows greatly.
You could also hash a hash in your user record. The leaked passwords would be hashed plain text passwords. The server would store a hashed version of the hash. Sure the hash becomes the password, but unless you've got a photographic memory you are not going to remember a 60 char bcyrpt. Salt with the username. If you could gather something about the user during the login process (while not exposing that the user record exists ) you can salt with that as well creating a more robust hash that couldn't be shared between sites. No man in the middle would be able to just cut and paste the captured hash between sites.
Combine with a cookie that doesn't get submitted back to the server and you might be onto something. On first request submit a cookie to the client with a key, then make sure that cookie doesn't make its way back to the login service so little chance of it being logged. Store the key in a session store, and then delete it right after login occurs or when session expired... this requires state for you JWT guys, but maybe just use a nosql service for it.
So down the road an admin comes across one of these hashed and encrypted passwords in splunk or a bug reporting tool. It should be useless to them as they can't find the encryption key anymore, and even if they did they then have to brute force a hash. In addition the end user didn't send anything plaintext along the line so any man in the middle at least has a harder time of it and you can't just hop to another site and login.
Note that keeping passwords secure against third parties parties is not all there is to it.
As soon as privacy is involved (and when ever is it not, these days?) you don't want to know the password. You can't abuse or leak what you don't have, so both you and your clients can sleep better if you never ever see their clear-text passwords.
Therefore, hashing/encrypting client-side makes sense.
It depends, you can use client side hashing, but server side salt will not be possible.
have a look at the link
Password encryption at client side
This idea of client side hashing is to protect the user, not your site. As mentioned many times already, plain text or hashed passwords both have access to your site equally. You don't get a security benefit.
But your users actual, plain text, password should only be known by them. Knowing what they chose as a password is information that can be used against them on other sites and systems. You are being a customer-focused site by protecting them from having their password choice discovered by your server devs or by third parties.
I've been doing a lot of work on this recently, IRL there are two issues with client side hash / symmetric encryption with really kill the idea:
1. You have to get the salt back to the server SOMEHOW...and to encrypt it client side you'd need a password...which defeats the purpose.
2. You expose your hashing implementation (not a HUGE deal as most sites use one of 3 or 4 hashing algos) which makes the attack easier (as just need to try one rather than n).
What I eventually went to was asymmetric encryption on the client using OpenPGP.js or similar...
This relies on an imported or client side generated key on the client and the server sending it's public key. Only the client's public key may be sent back to the server.
This protects against MIM attacks and is as secure as the device (I currently store client's private key by default in localStore, it's a demo).
The MAJOR advantage of this is that I never have to have users data stored / even in memory unencrypted on my server / data store (and my server's private key is physically separate)
The basis of this was to provide people a way to communicate securely where HTTPS was restricted (e.g., Iran / N. Korea atc...) and also just a fun experiment.
I'm FAR from the first to think of this, http://www.mailvelope.com/ uses this
If someone can see the data in and out on your connection then authentication will not save you.
Instead I would do the following for super secret stuff.
Passwords prehashed on client side before sent to server.
(Server stores another hashed and salted value of that hash sent from the browser).
So a middle man attack could allow them to send the same hashed value to login as them, but the users password would not be known. This would stop them trying other services with the same credentials to login elsewhere.
Users data is encrypted on the browser side too.
Ah, so a middle man attack would get the encrypted data, but would not be able to decrypt it without the actual password used to login. (users password stored in the DOM on the browser when they logged in).
So the real user would see the decrypted contents but the middle man could not.
This also means any NSA or other agency would not be able to request you/company/hosting provider to decrypt this data as it would be impossible for them to do so as well.
Some small examples of both of these methods are on my blog
http://glynrob.com/javascript/client-side-hashing-and-encryption/
Consider this:-
Client sends request to server "I have a password to validate".
Server sends client a one-time only random string. R$
Client embeds the user's password in this string (based on any (variable) rules you wish to apply).
Client sends the string to the server and if password OK, server logs user in.
Should server receive another login request using R$, user is logged out and the account is frozen pending investigation.
Obviously all other (normal) security precautions would be taken.
The method that I have come up with is to use SHA-256 with multiple rounds and a random salt...
salt = generate random salt
hash = sha256(password)
for (i = 0 to rounds)
hash = sha256(hash + salt)
This encrypts the password in such a way that only the user knows what the password is. Both salt and hash are stored in the database. I have also implemented this on the client side using a server generated random string.
server_data = {
algorithm,
rounds,
salt,
string
}
hash = hash(server_data.algorithm, password)
for (i = 0 to server_data.rounds)
hash = hash(server_data.algorithm, hash + salt)
hash = hash(server_data.algorithm, hash + server_data.string)
In crypto class, we were taught that the attacker can know the algorithm, salt, rounds, etc.... But in this case, the actual hashed password is never sent. The server knows what the random string that it sent was, so the full hash is generated on the client, and the final piece is to hash that result with the random string. That's the result that's sent to the server. The result is effectively a one-time password that is useless on replay attacks. The user's password is never sent in the clear, and if the attacker gained the password hash, it would be useless to them because the server will not accept it in that form. The hacker MAY be able to compute a rainbow table for the salt and the number of rounds to try and brute force the password, but any sufficintly complex password using ASCII symbols 32-126 of at least 8 characters long will usually take a long time to crack...and that's for EACH password. The sites that I write for can have passwords up to 128 characters in length.
As for session hijacking, that risk can be reasonably mitigated by regenerating the session ID every 30 seconds or so. I also include a token that's embedded in the HTML of the page itself. On the server side, some of the client information such as the client's IP address and user agent string are hashed as well and stored in the user's session data.
So on each request, the server gets the cookie session ID and the token. The token is compared to what is in the session data. The other information such as the IP address and user agent are hashed and compared to what's in the session as well. If it all matches, then there's a very high probability that this is the real user and not an intruder.
The only way that I can see this happening is if the attacker has the embedded token, the same IP address, and the same user agent. It's all about probabilities. Besides, any time you are dealing with crypto, it can be hard to get right. So as others have said, don't do it yourself.
It's 2022 now. As hacker attacks are getting more sophisticated, luckily also have browser standards. The defacto transmission protocol is encrypted (https) and cross site scripting or replay attacks systematically are more difficult with content security policies and CORS.
I believe your time will be well spend familiarising yourself with these technologies.
I'm not a security expert and leave that in the hands of more capable engineers.

Is it O.K to send a password hash to the client?

I use a secure one way hash to store passwords on the server. Can I send this same hash to the client to use as a token.
It is supposed to be an unbreakable one way hash (SHA-256 or similar), plus there is noway to tell that it came from the user password or to even know it is there unless you poke around.
Looking for verification if this is O.K. ?
If it's truly one way then I assume your server validates logins using the hash and not the plaintext. Therefore, sending the password hash is effectively the same as sending the key to the inner door of your home. There's still an outer door but why send more than you need/risk it.
You should strongly consider OpenID Connect for securing applications.
https://www.scottbrady91.com/OpenID-Connect/OpenID-Connect-Flows
OpenID Connect promotes time-bound authorization codes for web applications. If you're curious why all the indirection and layers, this SO answer is valuable:
What is the difference between the 2 workflows? When to use Authorization Code flow?
In summary, no this is a bad idea.
No. The severity of the issue depends on other details of your system, but in any case it is a bad idea.
If it is a salted hash, properly implemented (salt before hashing, unique random salt per user), then the hash alone will not expose the password. However, passwords are rarely changed, so the hash of the password would rarely change, so anyone who intercepted this hash would be able to use it to impersonate the user for an indefinitely long period of time.
If this hash is not salted, the problem gets a lot worse. A bad actor who intercepts such a hash would have a significant chance of being able to crack the actual password from it. It doesn't matter how technically irreversible the hashing algorithm is, there are huge databases of common passwords and their hashes and for a lot of users cracking an unsalted hash is a simple matter of a database lookup. If the user happens to use this password on many sites, as is common, this could turn into full blown identity theft.
The one part of your idea that is ok is using a token for authentication. That token should be purely random and strictly time-limited, however, with a new one generated each time a user logs in.
This is a no no for various reasons as pointed out by Douglas. Also should your users discover this you would greatly lose their trust in you and your product, and might hurt you legally which I'm pretty sure is not a desirable :).
I would recommend generating a separate token, that probably expires over time, and sending them this instead.
Plus it's fairly simple to implement, therefore no harm in being cautious.

Is my authentication system secured?

I want to implement an authentication system by following good practices, i want it as simple as possible and secured (im not going to implement some magic hashing function or something to feel a hero..) just wanting to use already known hash but not sure the right way of using it.
I read some articles on how Lastpass (a password management company) mange to handle their authentication and i loved their idea.So i wanted to implement my own authentication based on it.
Basically im creating an authentication key from the password on the client side (so the password is never sent as a plan text to the server).
that authentication key im sending to the server than do some hashing operations also in the server side and compare the result to the one inside the database.
On my client side:
auth_key = PBKDF2(SHA256, password+username, last_login_fe_salt, fe_rounds)
explanation - hashing password+username+last_login_fe_salt text fe_rounds times
last_login_fe_salt -> a random salt sent to the user once he/she input their username in text field -
To be honest, not sure how this last_login_fe_salt is efficent for the cryptography against Dictionary attacks but atleast two people having the same password will send different hashes on their network.
any hacker can get this data by asking from the server, i can add server side limitations (req/s if it makes some difference etc.. let me know what you think) also adding captcha might be a good idea. When a user logged in successfuly the server generates a new random string and saves in into the database.
*I didnt see any explanation which salt Lastpass uses on their client side hashing, they are using PBKDF2 algorithm that needs a salt parameter.
fe_rounds -> number of rounds given by the server when typing username -
its fixed for everybody and configurable by the server, also in articles i read about Lastpass they dont explain from where they receive the client side number of rounds...
so now we send auth_key as is to the server...
On my server side
now we are creating a new hash to compare the one inside the db.
Why another hash? if i understand correctly we bind the hash for server side data, like a combination of a password (that only the user knows) and server data.
db_auth=PBKDF2(SHA256, auth_key, user_be_salt, 100,000+user_configurable_rounds)
user_be_salt -> a random number that saved in db known only to the server and the ones who obtain the database, this changes on every successful login.
user_configurable_rounds -> number of iterations, every user can choose the amount of iterations (like in Lastpass) so attacker need also to guess the number or iterations?
I would be happy to hear what do you think about this authentication system, if its wrong than explain to me why and tell me what Lastpass do because i did not understand their entire authentication flow.
Most of what you're doing is useless from a security perspective. Lastpass has unusual security requirements -- don't treat them as a source of best practices.
If the client is responsible for hashing, and all of the parameters to that hashing are fixed, the hash effectively becomes the password. An attacker doesn't need to know the original password; they can simply pass the hash to the server.
Generally speaking, there is no way to verify a password over a network without either sending the password across the network (for traditional password authentication protocols), or having the server store the password in plaintext (for less commonly used protocols like SRP). Of the two, the former is preferable, as it's possible to secure the password in transit using protocols like SSL/TLS, whereas protocols like SRP require the plaintext of the password to operate.
Tweaking the PBKDF round count, either on the client or server side, is pointless. Set a fixed round count that makes the hash slow, but not so slow that it will place an undue load on the client or server. (100,000 rounds is probably excessive for a server-side hash. It takes roughly half a second to verify a password with those settings, so just two login requests per second would use 100% of one core on your server!)

How to enhance HTTP authentication security?

I got some of my nifty rails apps working, and its all jiffy and peaceful. I want to secure one tiny part that just feels wrong doing the way it is now - my sign-in procedure, where I use the form_tag with the remote option to send the content of a text and password field for obvious reasons using POST.
Sending a password just plain over HTTP makes me feel dirty. From where I can see, I have the following options:
learn to live with it and hope for the best
learn something awesome to have my controller doing magic through a rails-helper-i-dunno-about trick
build a separate app that runs on HTTPS and make life a living hell by going back to square one.
use JavaScript encryption
Somehow I think my best option is 4 - JavaScript encryption.
However, if the user types in his/her password and it gets encrypted with a part that is server-generated, it should be secure (in relation of solving the problem of sending it in plain text over HTTP) and solve my problem I guess. But on the rails side, to get that to work is to keep (yes, i have many things to cover, still) plain passwords in my database.
I need some help here - some pointers.
Why you should not use option 4: The risk of implementing something wrongly and putting your users at risk is much higher than when using something which already exists.
What you should do instead: Secure your users data by transferring it via https. Put
config.force_ssl = true
into config/environment/production.rb and you are ready to go. (Well and tell the webserver where appropriate certificates areā€¦)

How to assure client side data integrity

For our web application, we want the client to be as thick as possible, and keep our server as thin as possible. The idea is to give the client all the necessary data, let the user interact with that data in a snappy Javascript application (currently GWT, but we are considering moving to Angular or Backbone). We would like to make the server completely stateless, which improves scalability and memory usage.
A fundamental problem of course is that there is some data a user is not allowed to alter. For example, when doing a password reset procedure, the user cannot change his username, because then he could alter somebody elses password. There is also a boolean that indicates if the user has passed the captcha, we cannot allow him to set that to true. And many other examples can be thought of.
The solution we thought of is the following: Together with these strings that a user cannot touch (we call them the priviledged information), we also add a signature. This is simply the concatenation of the priviledeg info, HMAC signed on the server with an AES key. When the data from the client returns we concatenate and sign the info again, and if the signatures are identical, we know that the client has not touched our info.
My questions: Does anybody see any weaknesses in this scheme, and can anybody point to resources (books, blogs) where more info about this subject can be found?
For anyone finding this question after several years: The thing I suggested was basically the same as Json Web Tokens (https://en.wikipedia.org/wiki/JSON_Web_Token). The idea I suggested was correct, but of course you should use established libraries instead of rolling your own.

Categories

Resources