I had a quick question about cookie security that I wanted to run by the stackoverflow community before I got too far into implementing it. This will be my first time implementing user sign-in on a site and I wanted to be extremely cautious about security so-as not to have to worry about accounts being compromised down the line.
Here's my hypothetical security solution:
User signs up for site (through either email registration, login with Facebook, etc.) and is assigned a User ID number. This number is public and can be used to access the profile of the user, refer to them in posts, and so on.
At registration, the user is also assigned a randomly generated ROWID as their information is stored in a database (hosted on Google Fusion Tables). This ROWID number is kept hidden from the user and is never revealed.
The User ID is encrypted against the ROWID number and this number is stored in a cookie on the user's computer. It isn't ever visible to other users and, in theory, this could only be viewed by the user.
This solution would allow for a "secret" key (the ROWID number), a "consumer" key (saved in the cookie), and a public reference ID (the User ID). All of these are, of course, rolled up into a database where the site can quickly access them. Does this sound like a plan that would provide the proper level of security or is there something else that I should consider?
For additional protection against cookie theft through something like XSS, you might want to consider issuing unique cookies per IP address, and then making sure that the cookies are only useable from that IP address.
If you're storing your cookies in the database, things can get complicated, as you now have multiple cookies mapping to the same user.
Here's how to avoid those problems:
Set-Cookie: userName=Alice; authCode=eeba95a4...
Where: authCode=HMAC(ROWID, userName + ipAddr)
When you receive this cookie, look up the user in the database, recompute/verify the authCode in the cookie, using ROWID and ip address of the request. No need to store cookies in the database.
For extra crypto points, throw a salt parameter into the mix:
Set-Cookie: userName=Alice; salt=59843...; authCode=eeba9...
Where: authCode=HMAC(ROWID, userName + ipAddr + salt)
Salt value is generated randomly for every cookie you produce. There's no need to keep it a secret.
This is a good question, and since you have no answers yet I will give it a go. As far as I can see (I'm not a cryptographic expert) this seems reasonable, at least in theory.
I see one problem, that is if a malicious user get the consumer key (and this is not protected in any way) he could try to brute force the ROWID since he already know the User ID. So at least some kind of salt should be added to the User ID before encrypting. Also the "consumer" key ccokie should be passed as secure only, making sure it never travels on an unencrypted connection.
But it all depends on what you are planing to use the different keys for.
Related
I'm creating a login system that doesn't require email, phone, or any other identification, making it completely anonymous, and I'm worried about the implications of a system like this.
To summarize, I'm creating a system where the user can login without providing any "real" id.
I'm currently thinking of two ways of doing this:
A simple "create account" with user/nickname and password, but without requesting email or phone;
Provide a unique string (or seed phrase) for new users. This string can be used login without any password. Anyone with that string can see and edit that account data;
• In both cases if the user loses the credentials the account can't be recovered, but I don't really care;
• The second one is more practical for the user, he only has to save a randomly generated string. The security might be lower depending on how the user saves the string, however there will nothing on the database that can be used to identify the account owner; permanent cookies can be removed;
If you are wondering, the website is a calculator that currently loses all data once the cookies expire. I'm looking for a way to give users the ability to recover previously inserted data, but I'm not interested at all in linking that data to an email or phone. I'm not interested at all in who uses the system and how they use it.
How bad is this idea? Are there other approaches? Making it 100% anonymous (as possible) vs security and many more implications.
For a web application, where we need to store and manage users (SSO or openauth or what not is off the table), where we manage important business data, how risky is it to use an email address + password as the sign in?
For the last 15 years or so, encryption and protection techniques have improved, but we continue to use a proprietary user id, akin to using your bank card number for online banking; an id that will not be reused elsewhere. Customers and product owners are pushing to use email address because it is easier to remember.
I am concerned that there are a lot of websites that collect email + password pairs in order to use them to try to hack other sites; presumably asking you to sign up for an account for some humble service or other. What is this activity called?
I'm looking for some article or argument why using email+password for a site with sensitive business/financial information would be dangerous; or why it is not so bad. Again, I realize that provisioning our own accounts is not the ideal thing and am not looking for solutions at outsourcing authentication.
The "risk" of using a single authentication method for signing onto your application is difficult to determine without a risk assessment, and clearly defined system boundaries.
NIST 800-61 and NIST 800-63 gives guidelines on authentication methods for different levels of sensitive systems (in your case, a application). It will give you ideas on how to present your argument, and maybe an alternative solution, i.e., multi-factor authentication if the customer wants to authenticate using an e-mail address. This would mitigate the risk associated with malicious websites which collected e-mail addresses and passwords.
Keep in mind, password policy can also be managed to mitigate the risk behind a single authentication method using an e-mail and a compromised password associated with that e-mail.
All in all, it's not the ID that is important, but the authentication method and policies in place to mitigate the risks.
Using email + password as credentials is the widely accepted method of allowing users to log into sites on the web.
The advantage of using email is that everyone remembers their email address, whereas people will have difficulty in remembering which username or user ID they first signed up with if this is not their email address.
Username should not be considered private. This is the job of the password. Encourage your users to use a password manager such as LastPass where it can generate a 20 character completely random password (128 bits - uncrackable) which is different per site. LastPass will remember the username if this is not their email, so that solves this problem, however not using email can bring other problems such as username enumeration. If any signup function asks for a user to specify their username and you say that it is already in use, an attacker can use this to narrow the list of users in order to prepare for a password guessing attack. If you ask for email as step one of password reminder or signup forms, the system can send an email with a password reset link if already registered, or send an email with a link to the next step in the registration process if not.
In the end it all comes down to the value of the data your application is protecting. Adding two factor authentication is always a good step and can protect against password guessing and password reuse.
SSO or openauth or what not is off the table
Why is the case? Can't you use OAuth with claims based authorisation? You can still secure your application and make sure only the correct business users have access - it would just be that another entity is managing access for you.
I am concerned that there are a lot of websites that collect email + password pairs in order to use them to try to hack other sites; presumably asking you to sign up for an account for some humble service or other. What is this activity called?
Credential harvesting?
I am currently developping a platform with a PHP framework for our client.
The head of the client's IT department wants us to handle authentication with one database field containing email+password+salt (hashed) so there isn't a plain text email field in this table and the password is more secure (his reasoning). The user should be able to login with his email address and password. So the email address serves as the username.
The idea behind this is that the email addresses of the users are very important for the business of our client and the IT head wants to obscure the email address in the login table in case of a possible attack. (e.g. a hacker gets access to the login table)
This is of course only possbile, because the hashed email adress for the login is linked to his email address in the profile table.
Basically there are two tables which are required for this process to work. The tables are in the same database of course.
One login table with the hash combination field (email, pw, salt) and one profile table which contains among other things the email in plaintext in one field. Let's call it profile_email.
I have strongly recommended not to use this solution, because I have never before heard of this and I have already identified some possible problems with this solution.
So my questions are: Is this a safe and feasible solution? Can you think of any unforeseeable problems? Have you heard of similar solutions?
from an entity-relationship-point-of-view ...
you have a login table that either contains a field that is a concatination of hashes or a hash of a concatination of string values ...
you have a profile table that conatins the usual profile info, including a sensitive info (email)
if those two are linked by a key, the simple hashing of that email address is useless, since the same info is available as a clear text string from the profile table
in the other case, when in the login table it is ONE hash of a concatination of email password and salt, it is no added security, since the link to the profile table reveals a part of the hashed concatination ... since you also have to store the salt, and since that also has to be linked to the login entity or be part of the login entity, an attacker knows all parts of the concatination except the password ...
i can't see why this approach is a good idea, except if you split the database login for authentication from the rest ...
let's say you have in your login table:
s=randomSalt
e=cryptoHash(email,static_system_wide_salt)
p=cryptoHash(password,s)
id=KeyForRelationToOtherEntities
now the database rights to this table are restricted, and only the authenticator_user may access it, but nothing from the rest of the database
the email address in the authentication process is hashed and hardened against rainbowtable attacks
the password too
you can index the e colum for searching during the login process
the authenticator can not access profile information or other information that can be linked to the login entity, since the access rights restrict the authenticator to the login table
the rest of the system can't access the login table for the same reason
one additional role has to be taken into account, regarding password changes and creating new users if the authenticator may only read the login table
... just my 2 cents here ... it's just an idea, and not really complete, or guaranteed to be secure ... just an idea that picks up the general idea of separating the login table
I'm not absolutely clear about your scenario, but i guess it's something like this:
valueToStore = hash(email) + delimiter + hash(password, salt) + delimiter + salt;
This would allow to search for the email, but only if the email is made case insensitive (e.g. lower case). Otherwise you could even get duplicates with the same e-mail address.
Because the hashed email is only part of this field, searching in the database is more difficult and slower. If the user changes his email address, you would have to update both fields, the password table and the profile_email table.
Because the email is available in another table anyway, it is incomprehensible why this should be more secure. If an attacker has read access to the database (e.g. SQL-injection), there is nothing to prevent him from query the other table too.
It would be more safe, if the email would be encrypted (not hashed) in the other table too. Then you can search for the email by hash and nevertheless encrypt the email with an IV.
In every case i would not store the hashed email and the password-hash into a single field. If hashed correctly then other parameters like cost factor and algorithm are also part of the password-hash, this is enough for a single field.
Consider a company that delivers a network of computers as part of its deliveries. And it does this for hundreds of different customers. All of the PCs need to have secure passwords. This at least means:
The password should conform to the basic password rules (capitalization, numbers, special characters, etc.)
The same password shouldn't be used for different customers.
The password shouldn't be easily guessable.
If possible, the same password shouldn't be used for different PCs in the network (but it may be acceptable to do so).
Since there is also a need to maintain these systems as part of the delivery, the operators need to be able to retrieve a password for a specific system easily without causing any security problems (like forwarding passwords in emails, etc.).
Here are my questions regarding such a setup:
Is it advisable to create a password scheme such that the operators can "calculate" the password without having to look up? [Problem is, once the scheme is disclosed, all systems will have a security problem.]
How should the passwords be stored/retrieved for good security? [Is there a program that can be used to access a secure database with a web interface?]
I found WebKeePass during my investigation (which looks promising). One other option was to print the passwords and keep them in a locked filing cabinet in a disused lavatory in a basement with a sign on the door saying 'Beware of the Leopard'? but I believe that wouldn't be convenient for the operator. I wonder what are the other options would be...
Update: The "web" interface doesn't have to be open to public access (i.e., it can be accessible only within a VPN).
Since the users aren't able to choose their password, the passwords should be generated randomly. If the passwords are generated using some algorithm, as you stated, once the algorithm is cracked, all of the passwords can be cracked.
If you must store retrievable passwords, you should still encrypt and salt them. See adobe's recent issue where 150 million of adobe's encrypted passwords were leaked. The problem with unsalted passwords is that even if I can't crack the encryption, I can still see everybody who has the same password as me.
Admin Retrieval
For admin-only retrieval of passwords, you could use a password vault system, where one password entered by a staff member unlocks access to additional stored passwords. Ideally, you should have a system where you can select and display a single password on the screen. It should encrypt the passwords, log accesses, and be controlled by an administrator.
This could be a web-based system, but hosted internally on an intranet, perhaps accessed through a VPN. RDP or something similar may also be viable, perhaps even using two-factor authentication.
Unfortunately, we don't recommend products on StackOverflow.
End User Retrieval
We've designed a system in the past where you can recover a password via a HTTPS secured web site. You simply enter your username, and a random one-time-use retrieval code is delivered to the email address on record.
While we're not in control of the security level on their email account, we at least assume that only the user knows the password to access the email account. This forces the user to re-authenticate in some form in order to retrieve their password.
They then type the retrieval code into a web form and are shown their password. Again, this web site is secured with HTTPS. Additionally, the user must keep the web page open during the transaction (secure session), and the IP address must not change during the transaction.
I'm developing custom client/server application that requires client to log in with their username and password. The user accounts are not related to Windows/AD accounts in any way. After login, client application will request other services from server system.
My question is what is the best way to implement this? What kind of architecture would fit best here? I guess some kind of ticket/token authentication system needs to be implemented???
Thanks
You may in fact want to implement a system which passes "tickets" along between the different parts (login server, client, app server). This ticket will contain basic information such as the user ID (the username, the row id, etc). This ticket will either be encrypted with a secret key that the authorized servers share, or will be stamped with a hash of the ticket contents salted with a secret key that the servers share. The first way makes it possible for only the authorized servers to create and read the ticket, and the second way makes it possible for the authorized servers to verify that only the authorized servers could have created the ticket but permits anyone to read the ticket. All app servers will check the ticket (by attempting to decrypt it or by verifying that the hash matches) before proceeding with any actions that should be protected. If this is a web app, then cookies are a good place to store the ticket.
You haven't said much about your architecture, other than it is Client/Server, so I am assuming you're using some sort of forms designer like Windows Forms in VS. In these cases I have always used some form of database table authentication, as it is easy, simple to setup, and reasonably secure. You can even set up groups and roles this way, without much fuss.
Table: Users
Fields: UserID PK
Login Text
Password Text
...
Table: Roles
Fields: RoleID PK
Role Text
...
Table: UserRoles
Fields: UserID FK
RoleID FK