Hi I think I may have done this the wrong way round can anyone help explain how you hash/salt a password. Do you do it from the client or the webservice?
I have a datacontract which has a password datamember, in my service I do this to create a hash/salt of the password before it is saved:
So here is the process in which I was thinking.
Rest Service has https for secure connection
User creates account (along with password)
//to stop packet sniffing when user creates account https is used during POST so no one can see the password?
web service then creates a hash of the password to store it
//so if anyone did get access to the service/database they couldnt make much use of the data in terms of breaching accounts
Then some means to authenticate that user there after
Is this correct?
Sounds like you're on the right track. Hashing along with the salt value should never occur on client side, as attackers will have access to that code. And https would indeed secure the connection, disallowing others from reading the data.
During authentication you do the same thing: take the password the user entered via https, hash/salt that value, then compare the result hash with the value in the database. And of course if you ever return a Student object to the client, it should contain neither of the values.
It may be wise not to reuse the Password property of Student since now you can't tell whether it contains the plain password or the hashed value.
Related
I'm developing a Client/Server-Application with ASP.Net WebAPI and WPF.
Right now I'm thinking of authenticating the client with basic authentication over https. You can suggest better solutions but windows authentication and server side sessions won't work for me.
For basic authentication I need the password on the client in plain text (base64) to send it over the wire on every request, right?
But i don't want the user to reenter the password on every request, so I have a Login-Window on the application start.
The WPF PasswordBox uses SecureString and is not bound to the viewmodel. But at least right before the request I have to get the password as normal string to encode it to base64.
So sooner or later the password is in RAM in plain text no matter what I do.
What are the best practices to hold the password for later requests?
cache the PasswordBox
cache the SecureString
cache a plain text string because it will be in RAM either way
cache the base64 encoded string because at least it is obscure ;)
...?
So how do I handle this in a reasonably secure way?
Other applications by big players (MS, Google, Apple, ...) don't request my password for every call, so there has to be a way.
You should read into authentication tokens, this is a commonly used method and the asp.net-web-api framework provides a lot of functionality provided by OWin.
Basically the flow is as follows:
Authenticate at your web-api.
Return a token
Use this token in the header of every following web-api/http request
The benefits:
Doesn't store the username and password in memory (well, just for a single call)
Token can be invalidated at server side
Functionality out of the box with web-api2
You can read about it here:
http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
As for your WPF client:
You can create a .net client for your http/web-api requests by using the:
HttpClient https://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28v=vs.118%29.aspx
Some psuedo code will look like this:
public async Task<IEnumerable<DataContainer>> GetDataForTarget(string id)
{
var requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(new Uri(Host),
string.Format("api/Data?id={0}", id)));
var response = await Client.SendAsync(requestMessage);
//etc...
}
Note:
For the token based security to work you'll need https, otherwise the token can be intercepted. Everybody who knows the token can make calls to the web-api on behalf of the corresponding user. So, basically the problem shifts from securing the password to securing the token. The benefit of a token is that it should have a much shorter lifetime than a password, thats why it's more secure. Nevertheless it's arguable to store the token in a SecureString.
Meanwhile at the server side
It's is good practice (or even unethical if you don't) to, provided that users can pick their own passwords, you use a one-way encryption mechanism at your server to store the passwords.
This can be accomplished by using a (encryption-strong) random salt and a asymmetric-hash encryption using that salt.
To verify the user, just encrypt the incoming password with the stored salt and check if it gives you the stored hash value. In this case no actual passwords will be stored at your server and there is no way to retrieve the users password (.... well ehh excluded some technical details).
i need to clarify a few things about user authentication, because i want to know hows its done properly,
I was told that the authentication is a process that concerns about security. So the authentication process should be hidden from the client as possible and the client should receive only a flag value (1= password is correct and authenticated, -1= incorrect password) and/or user name of the authenticated user. So it should be a SQL operation that should occur in the back end. So the process in detail should be, client form sends user name and hashed /encrypted password to SQL, SQL authenticates and it sends 1/-1 with the user name to the client as the return value and the output.
But when i search online, on user authentications, that was not the case, all the threads i have seen on web, either the app is windows or web, developers do two operations:
In SQL server, the saltHash value of the password is searched by user name then return the saltHash value along with the PasswordHash to the client form / or to the business layer
In the client or in BLL, Use the entered password and the returned saltHash value to generate a PasswordHash and then compare this passwordHash with the returned passwordHash. if match password is correct if not password is incorrect.
Is this actually how developers write code to authenticate a user in a login event? If so basically the password comparison happens at the client side(either in the form or in the business layer) then wouldn't this be huge security risk by exposing the actual saltHash and passwordHash to the client?
if some one could write me some code to demonstrate SQL and C# the login / authentication process, would be a delight!
PS- when you reply please do not use LINQ, LINQ to SQL or entity framework. At the moment i dont know them. still learning them. Please reply from Ado .NET
thanks
This is a much larger pros/cons discussion, and it is hard to state it general. Pros of client-side hashing:
Since cryptographically secure hashes are computationally intensive, by pushing them to the client, the load from the server is decreased.
The server never gets to see the actual passwords, and since users share passwords between sites, if your system was to ever become compromised, you can make a claim that the passwords were not leaked.
Pros of server-side hashing:
The code for computing hashes does not to be written for multiple clients, that is for various mobile devices, such as Windows Phone, Android, and IOS as well as browser. Sometimes, specialized code needs to be written for browsers too when there are compatibility differences.
The hashes can be more "secure", e.g. you can have random salts for every user, which makes it computationally expensive for someone to brute force attack the passwords should the database be compromised. This gives more time for you to inform users should a breach occur and for users to change the passwords.
Some other guidelines:
Never store passwords, whether encrypted or plaintext, in the DB. You cannot guarantee that everyone who has access to the DB will not look at the passwords, hacked, or make a mistake and compromise them.
Such traffic must always go over TLS or SSL, which will guard against many attacks (such as eavesdropping, MITM, replay, etc.)
Always use cryptographic functions (such as SHA2 for hashes, PBKDF2 for deriving salts, etc.) for all cryptographic operations.
The following are some guidelines on how to approach password hashing both for client vs server scenarios.
If hashing is on the server:
When the user first registers:
Generate a random salt
Hash the password using this salt
Store both the salt and the password hash in the DB
When the user comes to login
Read the salt from the DB
Compute the password hash
Compare with that in the DB
If hashing is on the client:
When the user first registers:
Generate a salt based on some user attribute, such as user name, on the client
Hash the password using the salt on the client
Send the password hash to the server, and store the DB
When the user comes to login
Generate the salt based on the same user attribute (i.e you can always use user name for example)
Hash the password using the salt on the client
Send the password hash to the server, compare with the one in DB
The method may be the same between a client/server application and a web app, but a windows app directly accessing a SQL database is a different matter. You probably do want to avoid disclosing the hashed password, but the salt doesn't need to be private. You could get the salt for the user and hash client side, then compare server-side.
I don't know if SQL has actual password hashing algorithms (mcrypt, PBKDF2, etc.) or is limited to purely cryptographic algorithms like the SHA family, but a benefit of hashing outside the server is that you can choose your hash algorithm. You can also build some logic around it. For example, you can store which hash algorithm is in use for an individual user, and then if it's broken in the future you can update them to a more secure algorithm the next time they log in.
You also have to realize that, whatever you do, there's little actual security beyond your SQL authentication. It's fairly trivial to modify the program to ignore what the SQL server responds with and proceed as if the login was successful. If you want actual security, you'll need an application server sitting between the client and the database. It's also trivial to decomplie the program, see what it does and use that information directly or in another program, bypasing authentication entirely.
Regarding reuse, it would be a better approach to seperate the authentication into a separate module and reuse that module in both applications. ASP.NET has some robust authentication built in, so I would look to that, either to use or as an example. Crypto.HashPassword() already uses the currently-accepted best practice as long as you provide it with a relatively long (say 8+ character) random salt for each user.
i would use the following method to get a random salt, but i cannot use this in the login user event, because even the user enters correct credntials, it will return failed authentication. this is because the entered password in the login form will be hashed with the random salt, this salt is different to whats in the database for this user
private static byte[] GetSalt()
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] b = new byte[32];
rng.GetBytes(b);
return b;
}
Here is the users table structure
CREATE TABLE [dbo].[Users](
[UserId] [int] NOT NULL IDENTITY(1,1) PRIMARY KEY,
[LoginName] [varchar](256) NOT NULL UNIQUE,
[UserName] [varchar](256) NOT NULL,
[EmailAddress] [varchar](256) NULL,
[IsActive] [bit] NOT NULL,
[UserPasswordHash] [varbinary](64) NULL,
[UserPasswordSalt] [varbinary](32) NULL
)
GO
I just started a development of my first REST API in .NET. Since it will be stateless I will use tokens for authentication:
Basic idea (System.Security.Cryptography):
AES for encryption + HMACSHA256 for integrity
token data will consist object with properties: username, date of issuing and timeout
database will hold username, hashed password and HMAC hash
Login:
check if credentials are valid (username, compare hashed password to db value)
if true, encrypt data object
use HMAC on generated token and store it to database
return token (without HMAC) to user (cookie/string)
Request to method which requires authentication:
user sends token with each request
token is decrypted
if it is expired, error
if not expired use HMAC and compare username + generated hash with db values
if db check valid, user is authenticated
The way I see it, this approach has following pros:
even if db is comprosmised, it does not contain actual token (hash cannot be reversed...)
even if attacker has token, he cannot increase expiration by updating fields since expiration date is in the token itself
Now firstly, I wonder if this is good approach at all.
Besides that I still didn't figure out, where to store AES and SHA256 keys on server (should i just hardcode them? If I put them into web.config or use machine key than I have a problem in case of load balanced servers,...).
And lastly where do I store AES IV vectors, since Crypto.CreateEncryptor requires it for decryption? Does it mean that users have to send token + IV with each request?
I hope this makes any sense and I thank you for answers in advance.
UPDATE:
Ok, now I did some more research and came down with this solution:
token will contain originally specified data (username, date of issuing and timeout)
token is generated with encrypt-then-mac (it includes AES encrypted data, IV vector + tag of these 2 values for authentication, generated with HMACSHA265)
token tag will be written to db
user will be authenticated if:
tag is valid (token authentication)
data can be decrypted
token has not expired yet
tag matches the one written in database
user is not blocked in database (token invalidation on demand)
keys will be stored in web.config separate section. Same keys will have to be on every server (per application of course)
I didn't use FormsAuthenticationTicket because in .NET there are following issues:
same keys are used for different purposes (machinekey for view states, resources and formauthtickets)
mac-then-encrypt, used by .NET is not considered as safe as encrypt-then-mac
no built in way to invalidate token before it is expired
This is a follow up from the comment thread under the question.
You seem to be a bit confused as to what, exactly, OAuth is, so hopefully I can clarify it here.
OAuth is not a web service or something you consume. It is a protocol that describes the way that a site can authenticate a user against a service, without allowing the site to know what the user's credentials are. As a side benefit, most OAuth providers also have a web service to query the user's information, and permission to do so can be granted at the same time.
Typically, you are interested in implementing OAuth from the perspective of the site (eg, AcmeWidgets.com) so that a user can log in via Facebook or Google or something. However, you can also implement the service side (eg, where Facebook normally would be), and allow others to authenticate against YOU.
So, for example, let's say you have a web service to allow for third-party sites to provision Acme-brand Widgets for users. Your first third-party implementor is the popular MyBook.org. The flow would look something like this:
Someone invites the User to use the "Acme Widgets" app on their MyBook profile.
The user clicks on the button, which redirects to AcmeWidgets.com. The URL looks something like:
http://acmewidgets.com/oauth/user?r=http%3A%2F%2Fmybook.org%2Foauth%2Fclient&appid=12345
The user is asked if they want to allow MyBook to access their data and provision widgets.
The user clicks Yes, whereupon Acme Widgets notes that the user has allowed it.
The user is redirected back to MyBook, at a URL like this:
http://mybook.org/oauth/client?token=ABCDEFG
MyBook, on the server side, now takes that token, and places a web service call BACK to AcmeWidgets:
http://acmewidgets.com/oauth/validate?token=ABCDEFG&appid=12345&appsecret=67890
AcmeWidgets replies with the final authentication token identifying the user.
Alternately, it fails, which means the user is trying to fake a token, or they denied permission or some other failure condition.
MyBook, with the token, can now call AcmeWidgets APIs:
http://acmewidgets.com/api/provision?appid=12345&token=ABC123&type=etc
This is all known as the OAuth dance. Note that there are a number of implementation defined things here, like URLs, the means of encoding the various tokens, whether tokens can expire or be revoked, etc.
Hopefully that clears everything up for you!
I have implemented an md5 hash salted algorithm.
Using this algorithm I have saved the hashed password and salt value to the database.
then on login page retrieved the salt value of login user, get the byte of password add the salt value and computed hash and matched the result with the saved password and it is working perfectly but I am still able to see my password value in clear text at client side.
How can I encrypt the password value at client side along with md5 hash salted algorithm?
You do it right way. You won't be able hash password on client-side without knowing salt (and passing salts to client is not a good idea). If you want that data sent by client was secure, use ssl.
Note: If you use ssl client will still be able to see my password value in clear text because data will be encrypted only before sending.
You can use data protection API (DPAPI) to store password on the client side securely. Use SafeString class, to store password in memory and, as #PLB already mentioned, use encrypted connection.
If you are worry for password which you are typing in text box.
Then change TextMode of textbox as Password
Like this
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password"></asp:TextBox>
There are many different ways to solve this, the easiest I can come up with right now is to use some kind of challenge; the server sends a value the client has to use as a salt. The server ensures that the value is unique, hasn't expired, and only used once (this makes sure a replay attack isn't possible.)
This makes sure that a plain text password isn't sent, only a hashed one. The server can trust (trust as much as when doing plain text auth anyway) the client to not simply resend some old hash since the clear text password is needed to compute the hash with the "one-time-salt".
Another, more sophisticated (and secure) way is to generate a RSA-keypair from the password where the server has the public key, and the client the private. The client also has a copy of the servers public key. The user enters the password, and only the correct password will get the correct rsa-key.
The user then encrypts the requests with the server's public key, and then signs the requests with the user's private key. Only the server can then decrypt the requests, and the server can verify that the sender really is the right user by verifying the sign with the user's public key. And the opposite for the response. To add some security you should add some unique "salt" as I wrote earlier to ensure replay attacks are impossible.
I pass a loan ID, social security number and zipcode in url.
LoanID: 205689
ssn No: 555-896-4569
Zip code: 12345
the url is http://localhost/Product/abc/manager/internet/PayCredential.aspx?LoanID=205689
I need to convert the social security number and zip code into a hashcode for security purposes and pass them in this url. I would then decrypt them when the page is called. How can I do this?
Don't bother reinventing the wheel. Use SSL - all your communications will be encrypted, including your URLs.
Hasing wont work in your case. You cannot access the object from its hashed value. You should encrypt the data before you send and decrypt it before you use. Here you can see an example of how to use encrpyt and decrypt in c#:
http://www.codeproject.com/Articles/5719/Simple-encrypting-and-decrypting-data-in-C
plus you can use https for more security.
Your whole approach is wrongheaded. Under no circumstances should you be passing that information via the querystring, even if you are encrypting it using SSL. As I mention in the comment to #zmbq, I don't want someone shoulder surfing my SSN while I'm paying my mortgage, thanks.
What you should do is have the data securely stored on the server side, SSL secure your connection, and the client's URL should only use a non-identifiable token (like session ID) to refer to it. If the user needs to enter their SSN as part of their login identifier, it should be entered via a password field so that the browser masks the input.