Is it safe to use a javascript sha1? - javascript

I need to do a SHA1 hash, the only option is to use Javascript (due to my client using a 3rd party product)
An SHA1 is required to pass some information to a payment gateway. so the following info will need to be passed to a SHA1 to convert to a hash (username, password, amount), then passed to a payment gateway
My question is is it safe? ie can't people just view source and see the things I am hashing? is that recommended? is there any other way to do it?
thanks

Regardless of the hashing algorithm used, with browser-side Javascript, your users will always be able to view the page source and see the things you are hashing.
If you're hashing on the server-side, then the source text is not revealed to the browser. It's extremely difficult to "reverse" a SHA-1 hash, but not "impossible" - with enough brute-force power, you could at least find a hash collision (another string which produces the same hash).
SHA-1 is considered secure enough for most purposes. However, it is not considered secure against major, well-funded opponents - with a few million dollars one can hire enough cloud computing resources to break a SHA-1 hash relatively quickly, and this will become progressively cheaper as computing power increases.
If passwords are involved, you should look into BCrypt.

No, don't do this!
Password hashing is supposed to make somebody who copies your database unable to use the login information. By hashing on the client side you have exactly the value in the database, that needs to be sent in the request. So an attacker would just disable the hashing and use the database value as the password.
Quick overview of password hashing:
Each user has a password, that your service knows. They use it to login. Imagine you stored those in plain text. That would be bad in case someone copies your database. So you hash each password with an algorithm like md5 or sha1. The hash can not be used to recreate the password, but you can check a password if it's valid. Problem solved?
Not quite. It's simple to create a rainbow table for a hashing algorithm. This way you can quickly look up possible input values for each hash. So you salt. This means that each user has a random string that gets appended to the password before hashing, creating a unique hashing function per user. Perfect solution?
Again not quite. If your database is copied, with enough computing power this can be cracked. So your last step is using iterations. You don't just append the salt and hash, but you take that result, append the salt again and hash again. You do this a couple hundred times. This way it becomes more expensive for an attacker to brute force attacks. This is what bcrypt does. Over time computing power increases, so you should increase the number of iterations.

Related

Encrypting and decrypting data on client side using cryptojs

I am working on chrome extension to save some user data to local storage. I encode data with crypto-js.
However I am facing one minor issue/dilemma - if I encode user data using secret key abc123 I get something like this 2FsdGVkX19v0LNG0FKFv1SxAQj4AqdNvWWMGyi9yVI=. However if I decrypt it using another secret key like abc I get empty string. Only the correct secret key return non empty string.
So my question how do I need to encode data, if decoding with wrong key it would still return some string? Is there some configuration for this or different encoding?
If I am a hacker and I am using brute force to crack data it looks pretty obvious, what secret key user is using to encode data.
Fidller to fiddle with configuration.
Since you're using Crypto.js you're limited to popular and battle-tested algorithms. Let's say that you're using AES-256-CBC with a key derived from a password ("abc123").
If you encrypt something that a human uses then it likely has low entropy and therefore some structure to it. Think about some JSON string that you're encrypting. If the attacker tries to decrypt the ciphertext with some random key they might get random bytes. If they know they have to get JSON back, they have an oracle whether the decryption worked. They try again with a different key and get different random bytes. They repeat this until they find a plaintext that has a valid JSON structure. Even when they don't know that it is JSON, they might utilize statistical methods in order to deduce whether they got the right key.
You might need to use gzip before encryption in order to make that deduction harder but then the attacker might just incorporate an ungzip procedure in their bruteforcer and just do the statistical analysis.
AES is a block cipher where changing a single bit in the key changes roughly half the bits in the ciphertext with a constant plaintext. That means the attacker will not be able to see that they are getting closer to the correct key. They will have to try all of them.
The usual way of making it harder for an attacker is to increase the work factor. Crypto.js uses by default EVP_bytestokey with a single iteration of a MD5 hash of the password in order to produce the key. This operation is quite fast. You could change that to something like PBKDF2 with a million iterations but today's computers are so fast that this doesn't solve your problem...
The main issue is that your password is too short. "abc123" is a password that can be bruteforced in milliseconds when using Crypto.js defaults (1xMD5) and maybe minutes when using PBKDF2 with a million iterations. Adding a single character to a password multiplies the bruteforce effort by at least 50 (depending on class: upper, lower, digits, special).
Now you can calculate how long your password should be in order interfere with an attacker that corresponds to your risk appetite.
Note that just having encryption doesn't solve all your problems. Usually, the threat still exists.
You only can decrypt your data with the encryption key.
I personally wouldn't encrypt data in a frontend application.
Maybe you should have a look at the documentation:
https://cryptojs.gitbook.io/docs/

Security of Seeded PRNGs

I wanted to create an application where a login password could be the seed to a pseudo random number generator to recreate an encryption key. This encryption key would then be used to encrypt all data sent to and from the application's database, making user data out of reach of even the host.
Can this use of a PRNG even be cryptographically secure? If so, what PRNG algorithms are best for this application? Is important to enforce a decent length minimum password length? Any other concerns with this setup?
What you need is a key derivation function such as PBKDF2 (Password Based Key Derivation Function 2) which is designed to do exactly what you need.
You pass the password, a random seed from a CSPRNG and a repetition count. The random seed does not need to be secret and can be saved with the encrypted data. The count should be chosen such that the derivation takes about 100ms.

Is it safe to validate a captcha on the clientside with its hashkey?

I quite often use captcha codes to secure forms. Until now I check the user-entered captcha solution only on the server side for obvious reasons.
For all other form fields I do a javascript validation on the client since this faster and more user-friendly; (Of course I do a second check on the server-side), But for the captcha field, I just checked if it's filled out.
My question:
Would it be safe to do a client-side JavaScript validation by using the hash key (e.g. MD5) of the captcha-code? Doing it with the hash key wouldn't reveal the captcha code itself to bots and should be quite safe, right?
But maybe I am completly wrong with this idea...
Thank you for your insights!
Safe enough I'd say, but that may help OCR bots into checking whether they got it right without trying their luck on the server and risking losing the current captcha (as the server would invalidate the code if an incorrect answer was supplied and won't give you a second chance to try again using the same captcha).
Let's say an OCR bot has trouble telling whether the last letter of your captcha is a lowercase L or the "1" digit ? In a conventional captcha without client-side validation, the bot just tries its luck, if it guesses wrong the server logs the failure and resends it a totally different captcha, so the OCR has to start all over again.
Now imagine the above scenario but with client-side validation, here the bot has a way to verify whether they have the right answer without notifying the server about it, so in this case, if the bot is unsure, it tries all of the possibilities against the hash and only submits the right answer. Basically, this gives the bot the ability to make mistakes without telling the server about it and without having to start all over again.
Finally, I don't have precise numbers in mind, but even with a different salt each time, depending on the number of possibilities (like 4 alphanumeric characters, case-insensitive) it may be possible to bruteforce every single possibility in a reasonable amount of time without even making an OCR. To mitigate this you should use many iterations of the hash so that it becomes computationally difficult to try all possible answers.
Sounds doable, however you should definitely consider a long and random salt to prevent a simple attack based on precalculations.
More formally, you'd have to send the image, a long random salt and the hash value. Then, client side, you would calculate the hash of the input text concatenated with the salt and compare the result to the hash.
Because of the long random salt, the attacker's precalculated set would have to be enormously large to reflect all possible salt values.
Also, forget about MD5 as it is considered unsafe. Use a stronger hash function.
Also note that this would only be something that could possibly enhance the user experience (no need to POST the page in case of mistyped captcha) but definitely you can't do it only client-side. The actual verification must be done at the server.

Real-time password rule checker?

I am doing a bit of preliminary investigation for my school (I work for the IT department as a student). The students here have to change their passwords every 6 months, and many of them struggle with the (many) password rules that are enforced. That is, they often have to make several attempts at setting a new password.
The rules are:
Must be 8 characters or more in
length
Must contain 3 of 4 types of
characters (capital, lowercase,
number, special character)
Must not contain the user's first,
last or middle name
Must not contain the user's username
Must not match any password used
before
User must type password in twice, and
typed passwords must match exactly
I have a few questions:
Is it possible to create a web-based
password checker that provides
real-time feedback as the user types
in their new password? I am
imagining a checklist on one side of
the web-page where green checkmarks
are activated as the password meets
more criteria.
Is it possible to do perform this
checking securely and entirely
client-side?
Where would one start on such a task?
Is there a guide you can recommend?
Please keep in mind that I am not a web developer. Also, please leave any witty comments like "change the password policy" or "they're just dumb users" out of here.
Is it possible to create a web-based password checker that provides real-time feedback as the user types in their new password? I am imagining a checklist on one side of the web-page where green checkmarks are activated as the password meets more criteria.
Yes.
Is it possible to do perform this checking securely
As the lights go green, it exposes information about where in a password the requirements are met. That will leak data about the password to anyone who can see the screen.
and entirely client-side?
Yes.
Where would one start on such a task?
A list of rules in the HTML document with a FAIL image next to each one. Programatic versions of the rules in JS. Then just test each rule in turn in a loop on each keypress event on the password input and swap PASS and FAIL images depending on if the rule is followed or not.
You'll need to hit the server with an XMLHttpRequest object to check if a password has been used before. Make sure you only store hashed and salted passwords there though.
Please keep in mind that I am not a web developer.
Then I recommend you get one or become one.
Also, please leave any witty comments like "change the password policy"
Fine, leaving the wit aside and sticking to the serious issue:
If people have problems coming up with passwords that conform to the policy, then they will have problems remembering them. This will lead to an increase in people having to have them reset (more work for the IT dept) and in people writing them down (which is probably going to be less secure then a password that is easier to guess / brute force).
Most of the rules you specify can be checked in real time using javascript, more specifically using regular expressions. Checking whether the password has been used before should be done on the server side to be secure.
Is it possible to create a web-based password checker that provides real-time feedback as the user types in their new password? I am imagining a checklist on one side of the web-page where green checkmarks are activated as the password meets more criteria.
Yes, but you will need to know some javascript to do it.
Is it possible to do perform this checking securely and entirely client-side?
No, and yes, or yes and no, but not both. You can do the check entirely client-side (except for checking against previous passwords, which would need database access). But nothing, NOTHING, on the client-side is ever secure. Anything you do on the client-side should be considered a help to the user. All validation must always be made again on the server.
I don't want to be a smart-ass and tell you to change the password policy, and doing so because validation would be "hard to do" would be a bad choice, but I would like to recommend the following article to the one that has decided on the password policy: http://www.baekdal.com/tips/password-security-usability
Must not match any password used before <--that one is the only one that has to be performed server side, but can be done securely using hashes or some form or encryption, because a client side copy of said passwords would not be a good thing.
Regexp's are probably where you'd wanna start. If you're unfamiliar with regexp's in web development, I'd suggest you start here: http://www.w3schools.com/jsref/jsref_obj_regexp.asp. If you truly have no experience in web development, I'd have to ask how you got stuck with a job where you'd have to learn a new language to accomplish a relatively simple task. You'll definitely need to have an understanding of javascript to do something like this all client side. Oh, and I wouldn't recommend testing
Must not match any password used before
It's too risky to do this in a simple way client side and complicated to do it securely without bringing in help from outside libraries, etc. Hope this helps and good luck!

javascript securty: an AJAX call to record the user's screen resolution, is it possible to prevent fake numbers?

This is a javascript security question: suppose a page finds out the screen resolution of the computer, such as 1024 x 768, and want to use an AJAX call to log this data into the DB.
Is there a way to actually prevent fake data from being entered into the DB? I think whatever the HTML or Javascript does, the user can reverse engineer the code so that some fake numbers get entered into the DB, or is there a way prevent it from happening totally? (100% secure).
Update: or in a similar situation... if i write a simple javascript game... is there a way for the user to send back the score by AJAX and lie about their score?
If you start with the assumption that the user you are communicating with is malicious, then no; there is nothing you can do to control what data they pass you. Certainly not with 100% certainty - in the worst case, they can use network tools to rewrite or replace any "correct" content with whatever they want.
If you just want to prevent casual maliciousness, you could obfuscate or encrypt your code and/or data. This will not deter a determined attacker.
If you actually trust the real user, but suspect that others might try to impersonate them, you can use other techniques like a dynamic canary: send the user a random number, and if they return that same number to you, you know that it really came from them. (Or you're being hit by a man-in-the-middle attack, but hey; that's what SSL is for.)
It's not possible to stop users from sending any numbers they like back from JavaScript.
I think the best you could do is do some sort of check on the server-side to make sure the numbers sent back look like a realistic resolution.
I'm not sure why someone would spend the time to spoof those numbers in the first place though.
Yes, you are correct. Since you're using client-side code, you have to tell the
user's computer (and thus the user) in one way or another, whatever encryption or obfuscation you're using. There's no way around it.
For the resolution, it would basically be impossible to determine if it's valid resolution. My resolution is usually sent to the server as 5120 x 1600, which seems pretty unrealistic, but it's because the 2 screens are often sent as 1. Otherwise, there is a such a huge variety of possibilities in screen resolutions and screen configurations, you'd probably remove a lot of valid ones, although they might be few.
For the game score, you could do additional checks that make it more complicated to check. Things like sending multiple notices of the score throughout the game and requiring X number to ensure that the score received is valid. (IE, must receive one between 200-300, 400-500, 700-800 and then the final score of 1000.) With the final score, you could also have some kind of encrypted value that can only be used once or that contains some data with a CRC on it. Basically, in the end, require receiving other data than just the score, especially for higher scores.
To attempt an answer by elaborating on comments made by Dok, and yourself, there is a clear distinction between manipulating an application to 'cheat' it out of something, whether it be an online business to get something cheaper or a MMPORG to get more experience, than manipulating it in such a way that it renders the interface incorrectly and diminishes the overall user experience for that particular (hacker?) user.
Your time would be better spent focusing on other aspects of your site. I don't recommend the users of my site manipulate the HTML to make it look funny on their machines, but I'm not going to go all out and obfuscate my server output to stop them from hurting themselves. In your case, range checking against pre-defined safe values, making use of the DB, to ensure the user is viewing with an 'allowed' resolution puts unnecessary burden on your application, and takes time to do.

Categories

Resources