How secure should an account activation be? - django

I'm writing an account activation process from the ground up in Django, and here was my basic thought process:
Create a model like:
class UserAccountActivation(models.Model):
lock = models.CharField(max_length=16)
key = models.CharField(max_length=16)
Generate lock and key values when necessary using a function like this:
def generate_entry():
"""Generate a random alphanumeric string between 8 and 16 characters long."""
''.join(random.choice(string.ascii_lowercase + string.digits) for x in range(random.randint(8,16))
Compose a link like this:
r'^activate/(?P<lock>\w{8,16})/(?P<key>\w{8,16})/?$'
And send it out. When they hit the link, I activate the account and disable the activation key.
I was originally thinking of hashing the random strings as an extra precaution, but this seems unnecessary and it'd be pretty long to have two 32-length keys in my URL:
account/12345678/12345678
or
account/12345678901234567890123456789012/12345678901234567890123456789012
Is this a safe and recommended way of handling account activation? Is it necessary to even have the random length on the strings?

Well, to answer that question you have to consider why you have protection on your account activation. Likely it is to prevent people from guessing the activation code, so they would be able to use a false email address. As email addresses are very easy to get anyway, the activation process doesn't need to be much harder than it would take to register an email account somewhere on the web. Anything more is wasted effort, as the attacker will simply shift the attack to another weak point.
Using random strings is perfectly fine for this.
If you need more security you can consider putting a hashed account id in there, so you can count and then stop multiple failed attempts to guess the activation code.

It is a good thing to have variable length, lest it is susceptible to timing attacks.
Also, python's inbuilt random is not really cryptographicaly safe, so it is always preferable to use sha from hashlib or the system random generated via linux which you can obtain by making a sys call.

Related

Are all URLs discoverable? Can you hide information safely in a random URL?

I've been wondering about this for a while.
Let's say I have a web application at
www.example.com
If there are n users of the application, could each person login simply using a URL?
E.g. For user 1 to access their part of the application, they would visit
www.example.com/user/1
In this above case, the URL scheme is easily guessed.
But what if it can't be easily guessed?
E.g. For user 1 to access their part of the application, they would visit
www.example.com/user/[random string]
Are these random URLs discover-able?
What I mean by random URL is a URL containing a very long string of random characters. If one used this URL as a password, it would be very difficult to guess.
And secondly, a more practical question--
Can one assume that no one else has access to their part of the application?
Or another way of asking, is guessing a random string the only way of accessing someone's part of the application?
The motivation for designing an application this way is that there would be no login/logout required.
Thanks
Even if you put a random string in place of a user id, the same problem still exists. If someone guesses or somehow retrieves the random number of another user, he or she will still be able to access it.
What you are attempting is called security through obscurity. It is not a good plan to have your overall security based on hiding or obscuring sensitive data only.
Are these random URLs discover-able?
Discoverable by search engine? That depends on your website settings.
Accessible? Yes.
Can one assume that no one else has access to their part of the application?
I am not sure what you meant by this, you will have clarify this part.

Login - pass user data to new windows / store it as static information? [Desktop App]

I'm trying to make a desktop C++ application (using Qt, if it matters for this problem) that features an authentication system. It can be used by ONE user at a time. When the application starts, a log in form will allow the user to type his username and password. After logging in, a new window will be displayed. My question is: should I pass the user's ID and/or username to the next window [as a constructor parameter?] (and use such system for other windows as well) OR would it be ok (I'd much rather prefer this) to store this data in the static fields of a class and access it from everywhere? [doesn't sound too bad since I only allow ONE user to be logged in at any time]. I should also mention that I'll be trying to use the Model-View-Controller pattern.
Do you need to store it? I mean, once user clicks "Login" on your login dialog, it checks whether entered name/password combination is authorized to use the app and than the rest of the app starts, knowing user is authorized and without any other checks/using of credentials.
In case you do need to store username (for example you display somewhere in header that user is logged in as XXX or you use it for some other reason) I would recommend to save it statically somewhere. The other way (passing it all over the place) means that you would have to store copies userID/name all over the rest of your app.
Also, if you have more user-releated information (like selected theme, some configs, user specific file paths or something) keep it in one place (create struct/object with all this in it)
Pro tip #1:
Do not store password in that struct. Once you check whether user is authorized or not dump it. And by that I mean don't just stop using it/forget pointer but overwrite all places in memory where the password was stored to prevent some RAM reading attacks.
// Example
char *password = getPasswordFromLoginDialog();
// Do some stuff (check it)
while (*password) { // while we are not at the end of 0 terminated string
*password = 0; // zero it
password ++; // move on
}
Pro tip #2:
Usual way to compare 2 strings is to go char by char and once they are not the same tell that 2 strings differ and thus password is not accepted. However, it takes marginally longer time to find char missmatch at say 7th position than at 1st. Attacker can exploit that using brute-force and statistics and work out password one char by one.
Easy way to defeat this: After user tries to login wait random period of time and after that start checking if the password is correct or not. This way it will disrupt this time based brute-force attack
More proper way how to check whether password is correct or not: Don't check actual password, but hash it first using some crypto-secure hash like SHA256 and then compare hashes. Preferably hash the hash and hash the hash of hash and so on, about 1000 times, so it takes much longer to bruteforce if attacker gets raw hash of password.
Pro tip #3:
Never ever hardcode usernames/passwords into your application. It is pretty easy to decompile and pull these pairs from it. I don't know exactly what you are working on, but I would suggest querying 1000 times hashed hashes of password from some SQL database or something like that. If you have to use hardcoded passwords, dont use raw string, but those hashes
Pro tip #4:
Use salt (Salt - wiki). That is pretty much some random data you put before/after password before you hash it. For additional security it is better to assign each user different salt.
Reason for salts is that same passwords have same hashes. When you have lookup table of common passwords and hashes, you can de-hash password very easily. Not using different salt for each user (or not using it at all) has some consequences: when there is a leak of password(hashes) database attacker instantly knows which users have same password
Pro tip #5:
If you are using some sort of client-server authorization system, make sure you salt-hash password client side (before sending it over network) and also on server side (before storing to db/comparing against db). This way when there is a leak of db attacker can't use those stored hashes to authorize himself, because they get hashed (once) more on server side before actual authorization process.
Keep in mind, that if attacker intercepts salt-hashed password when client is sending it to server he CAN use it to authorize himself. However, when using network, you should encapsulate all your traffic in some sort of encrypted tunnel (have a look at TLS)
Hope this helps

Is it necessary to encrypt cookie data if it just stores user preferences?

I am creating basic website which customizes the look of website based on user preference data stored in cookies. The data in cookie is stored like this:
country,option1,option2...and so on.
I read this data from the cookies directly and act on it. Is there a reason why I should encrypt it because I don't think this poses any security threat.
The answer is a bit more nuanced than what you'd expect ...
Encryption would make the data unreadable, but that's the only thing that bare encryption does; it doesn't actually prevent the data from being modified. What you'd want instead (or in addition to encryption) is message authentication.
These two techniques are often used together (and if you do encryption, you surely do have to do authentication as well), but are slightly different in what they do.
If you don't store any private, sensitive information in the cookie, then you'd probably be fine without hiding (encrypting) it from the user. However, you absolutely MUST implement a message authentication mechanism.
Even if you don't think it is currently a security threat, that might be because you haven't considered all possible attack vectors or you're not actually aware of all of them. And even if it is safe now, that doesn't mean it will be in the future when you or your colleagues add more features or otherwise alter the application's logic.
Therefore, you must never trust unvalidated user input, no matter how, where, when it got into the system or how harmless it may seem at first.
Edit note: Your question doesn't reference PHP, but I assume it as the most popular language for web application development. And I do need some language to produce an example. :)
The easiest way to implement message authentication in PHP is by using the hash_hmac() function, which takes your data, a key and a cryptographic hash function name in order to produce a Hash-based Message Authentication Code (HMAC):
$hmac = hash_hmac('sha256', $stringCookieData, $key);
You can then append (or prepend) the resulting HMAC to your cookie data, which is effectively your "signature" for it:
$stringCookieData = $hmac.$stringCookieData;
And then of course, you'll need to verify that signature when you receive the cookie. In order to do that, you need to re-create the HMAC using the data that you received in the cookie and the same secret key, and finally compare the two hashes:
// 64 is the length of a hex-encoded SHA-256 hash
$hmacReceived = substr($_COOKIE['cookieName'], 0, 64);
$dataReceived = substr($_COOKIE['cookieName'], 64);
$hmacComputed = hash_hmac('sha256', $dataReceived, $key);
if (hash_equals($hmacComputed, $hmacReceived))
{
// All is fine
}
else
{
// ERROR: The received data has been modified outside of the application
}
There are two details here that you need to note here:
Just as with encryption, the key is NOT a password and it must be random, unpredictable (and that does NOT mean hashing the current timestamp). Always use random_bytes() (PHP7) or random_compat to generate a key. You need 32 bytes of random data for SHA-256.
Do NOT replace hash_equals() with a simple comparison operator. This function is specifically designed to prevent timing attacks, which could be used to break your key.
That's probably a lot of info to digest, but unfortunately, implementing secure applications today is very complicated. Trust me, I really did try to make it as short as possible - it is important that you understand all of the above.
If you are fine with
the user being able to see it
the user being able to change it
then you do not need to encrypt it.
I read this data from the cookies directly and act on it
Make sure you have proper validations in place. Don't trust the cookie to not be tampered with.

Django Caching - How to generate custom key names?

Right now, I am retrieving information from an API, and I would like to cache the information I get back, so I do not have to constantly hit their server and use up my max API call requests. Right now, a user can search up a particular keyword, like "grapes", I would like to cache the retrieved string by calling "cache.set(search_result, info_retrieved, 600)" where "search_result" is the user's search result, in this case, "grapes". I want the key to be the user's search result, which is "grapes". I cannot do this since the cache requires the key to be a string. How can I get around this? I cannot use a database because the information updates too often.
I could use a database, but I would be writing information to it, then deleting it after a few minutes, which seems impractical. So, I just want to cache it temporarily.
As Shawn Chin mentioned, you should already have a string "version" of your search query, which would work just fine as a cache key.
One limitation with memcached (not sure about other backends) is that certain characters (notably, spaces) are not allowed in keys. The easiest way to get around this is to hash your string key into a hex digest and use that as a key:
from hashlib import sha1
key = sha1('grapes').hexdigest() # '35c4cdb50a9a6b4475da4a66d955ef2a9e1acc39'
If you might have different results for different users (or based on whatever criteria), you can tag/salt/flavor the key with a string representation of that information:
from hashlib import sha1
key = sha1('%s:%s:%s' % (user.id, session.sessionid, 'grapes')).hexdigest()
You could also use django-newcache:
Newcache is an improved memcached cache backend for Django. It provides four major advantages over Django's built-in cache backend:
It supports pylibmc.
It allows for a function to be run on each key before it's sent to memcached.
It supports setting cache keys with infinite timeouts.
It mitigates the thundering herd problem.
It also has some pretty nice defaults. By default, the function that's run on each key is one that hashes, versions, and flavors the key. More on that later.

Saving passwords inside an application

I am writing an application that needs to read a user name and password and store them so that the program can read them again later. Storing it in some variables sounds like a stupid idea.
Found that KDE library, but it has too huge dependency, and I am too newbie programmer to understand how to use it.
What are the common Methods to storing passwords, and how I can solve my problem?
It depends on what you are going to do with the information.
If you are going to use the name and password to access some external service (but the user will have to reenter the information the next time the program is run), then storing them in some variables is OK. It might be wise to store them encrypted (at least, store the password encrypted) so that it is not visible in core dumps or the equivalent. When the password is needed, you decrypt it, use it, and then write over where the decrypted version was stored (zapping it). (Note: hashing is not appropriate in this context; you need to be able to see the password, and you can't undo a hash.) You could decide to store the information outside the program (in a disk file), but it doesn't seem necessary. Note that the binary will still contain the encryption key (and encryption algorithm), and encrypted data is more random than the average contents of your program, so to really conceal the encrypted password is actually very difficult (verging on impossible). However, you can make it hard enough that it will stop all but the most determined attackers.
If you are going to store the username and password as a permanent record so that you can validate that the same user is accessing the information in the future, then you must use storage external to the program; you will use a simple database, which might be as simple as a plain text file if you ensure you resolve any concurrency issues. In this case, you will hash the password with some salt, and you'll store the username, salt and hashed password in such a way that given the username, you can easily find the other two values.
Night Walker comments:
I use that password to access some web database, so I need it stored in my application after it is entered for the first time. Are you sure a plain text file is that smart an idea?
It depends on how you conceive 'stored in my application'. You can't modify the executable, or at least shouldn't try to do so. So, you need to look on it as a permanent record stored in some sort of file separate from the application executable. On the other hand, you do face a different problem from what I outlined - you are not authenticating the user with the information; you need to decrypt the information on demand to send on to other applications.
First off, that means that salts and hashes are not relevant; you need to reverse the masking operation, and you can't reverse a hash.
Next, you need to decide how you will identify the user of your application upon reappearance. Will the user be obliged to enter some password to get to their own data, or will you simply rely on the operating system privileges, or some other scheme.
If the user must enter some password into your application to get going, then you can consider using that password (or a hash of it, distinct from the password hash used to recognize the password to the application) to encrypt the username/password combination for the external application. You can then store the username and, for sake of argument, a Base-64 encoded version of the encrypted password into a text file; this is as safe as the application password, which is stored in the original salted hash format. When the user returns, they have to supply their application username and password, and you can validate that combination against the stored values, and then use the password to decrypt the password to the external application.
If the user does not enter a password, then you are more restricted in what you can do. You have to be able to determine a key somehow from the information available to you that can be used to store the user's encrypted password in a file in a restricted location such as a sub-directory underneath their home directory with no group or public access:
mkdir ~/.appname
chmod 700 ~/.appname
cp /dev/null ~/.appname/app.key
...store the encrypted information...
chmod 500 ~/.appname
chmod 400 ~/.appname/app.key
This is less satisfactory because even if you combine a fixed key with the user's name, say, the chances are that someone can work out what that key is (and the encryption technology) and reverse engineer it. (The secrecy of encrypted data depends on the keys; when the key is determinable by the program, it is also determinable by a determined attacker. It is best, by far, to rely on the user to provide the key (or a password or pass phrase) at run-time; then the application does not store anything that an attacker can use offline.
Usually you store the username and a hashed version of the password. See this wikipedia article: hash functions, and this question.
Common method to store passwords for later use is to store them in some encrypted cache. That cache is encrypted using some master password. User should enter master password each time you need password from cache. KeePassX is a small open source application that uses master password to store personal data (user names, passwords, etc.) It has a light interface, is cross platform and published under the terms of the GNU General Public License. You could check it as sample and use some parts of it.
What about MySQL or SQLite? Hash the password and store them in a persistent database, no?
I would suggest storing a hashed password in SQLite. Then whenever you need to check a password, hash it and then compare it against the stored value. This keeps the stored passwords secure so no one (not even you) know what they are.
what kind of application is it? There are many methods but if its ASP.Net it's common to encrypt in the web.config file.
At spotep.com we only store the username and a hashcode of the username combined with the password. The benefit of this is that similair (often trivial) passwords wont result in the same hashcode (which is stored in a cookie, and therefore very unsafe).
You could try QSettings which provides persistent platform-independent application settings. Solutions like mysql would be overkill unless you have hundreds of passwords to store.