Why is encryption considered safer? - encryption

This has puzzled me for a while now. I don't have a broad understanding on encryption, but I understand the principle.
For the sake of an example, let's assume I have a program whose sole purpose is to post a random user's input to my private facebook profile. Now to do this, the program must have my login information to facebook (if this is not the case, assume another third-party application). This information, or credentials, must be stored somewhere, since the program's post method would be done without administration.
I know it is a bad policy to store the login credentials in the code as plain strings, as the compiled code can be decompiled and my credentials would be readable. The recommended solution is to store them in a separate file, encrypted.
As far as I understand, the encryption / decryption needs a key that also needs to be stored somewhere. Can't this key and the encryption algorithm be read from the decompiled code and used to decrypt the credentials?
Is the benefit of storing the credentials encrypted based on the extra step on decompile-decrypt, or have I drastically misunderstood something?

There are 2 ways one could check supplied credentials when you have encrypted version:
Decrypt the encrypted version; this would obviously require storing the tools necessary to decryption, which is unsafe
Encrypt what you are trying to check, and see if it matches your encrypted version. This does not require the ability to decrypt anything.

Related

How JWE works with Request Object in OIDC

I wanted to use encrypted local PASETO tokens for the Request Object in the OIDC, but it turns out that I need to store the key somewhere to decrypt this request object, and it must be available unencrypted/unhashed as it will need the Request Object to decrypt. So I will have to store it as plain text in a database? Pretty dangerous. So I started to wonder how JWE works, but the documentation from https://datatracker.ietf.org/doc/html/rfc7516#section-5.1 about JWE encryption is quite confusing for me. Does JWE solve this problem of storing a symmetric key in a database as plain text or does it have other ways?
There are a few different solutions here, which solve different problems:
ENCRYPTED JWTs
These can be used when the app wants to prevent information disclosure. They are issued by the Authorization Server, which uses a public key to encrypt them. There is then a burden on the app to maintain a private key to decrypt them. See the Encrypted ID Tokens for some example usage.
REQUEST OBJECTS
These are often used to protect against man in the browser tampering. The app only needs to deal with public keys, which it already has access to, so the solution is easier to manage. Newer standards such as PAR and JARM are used, as in this summary.
JWT INFORMATION DISCLOSURE
If you want to avoid revealing sensitive data in access token JWTs, then the usual technique is to return only opaque access tokens to internet clients. This is easier to manage than encryption. See the Phantom Token Pattern for how this works.
SUMMARY
I would usually avoid introducing key management into apps. Aim to manage this in the Authorization Server instead.

Does encryption add any benefit if I'm using SSL?

I recently stumbled across this article on securing Web API endpoints.
If I'm using SSL, is there any advantage to encrypting the user string in the header? What are the risks if I include the user key (Id) as plaintext instead of ciphertext?
TLS is transport-level security. I.e. the data is not secured by TLS before the data reaches the transport and after that. If your data is long-term and/or you keep them elsewhere besides using during the transport session, then it might make some sense to keep them encrypted (and then transfer them encrypted if possible). If your data lifetime is short and the data makes sense only during the transport session, then there's no much sense in encrypting the data besides TLS.
The author of the article is basically combining the concepts of a user identifier and a user secret into a single cryptographic token. If you choose to send a user identifier in plaintext instead, then that user identifier must be kept secret (just as the token must be kept secret). As long as that secrecy is maintained there is no advantage to using the token.
Note that this system doesn't seem very secure as presented. If an attacker can guess a valid user identifier then they can generate a valid token. The author is basically using RSA as a glorified hash function. I'd recommend you look for another reference.

Encryption Web.config sections

I have read about aspnet_regiis for encrypting web.config sections in an ASP.net project, but I am confused how this works since the decryption key must live in plaintext on the actual server somewhere.
I would ideally like to use AES for encryption, but this requires adding the aes key to the web.config in plaintext itself, which seems useless to me. (from https://stackoverflow.com/a/8777147)
Perhaps I am missing something.. can someone explain how this encryption process is actually secure?
aspnet_regiis encryption is easy to decrypt if you are able to login to a session on the machine and have access to the key.
This protects against a scenario where someone can view the file but cannot login to the machine and a scenario where the decryption key is correctly ACL'ed to a known set of users.
Under the hood it uses DPAPI and machine context specific information. I believe you can also encrypt using a user profile in which case no other user can decrypt it.
Here are some useful links:
http://weblogs.asp.net/owscott/archive/2005/07/29/421063.aspx
http://weblogs.asp.net/scottgu/archive/2006/01/09/434893.aspx
You must create a key first and than use this key in your web.config
An detailed explanation can be found here: msdn microsoft
the one under web farm scenario's is the most practical.
I think it's useful to encrypt them if you have a lot of passwords etc. in the web.config.

Is it possible to hash a password and authenticate a user client-side?

I often make small websites and use the built in ASP.NET membership functionality in a SQL Server database, using the default "hashing" password storage method.
I'm wondering if there's a way to authenticate a user by hashing his password on the client and not sending it in clear text over the wire without using SSL.
I realize that this would only be applicable for users with Javascript enabled.
Or... possibly, this would be a great built-in capability for Silverlight (is this in the Silverlight roadmap?)
EDIT:
I'm also looking for "degrees of security." Meaning, if there is a method that has some advantages over simply sending plaintext password, I'd like to know what they are and why.
I know there are lots of people who do small sites with logins (such as a family website or volunteering to make a site for a local cooking club) and don't see the need for purchasing SSL certificates.
This is possible. This is actually what Kerberos authentication does, only with a little bit of added spice. To ensure that your authentication mechanism is secure, you need the following:
A common hashing algorithm on both the client and server.
A one-time salt value generated on the server and shared with the client.
The original password stored in a database.
To securely authenticate a user via hash code, so you avoid sending the actual password across the wire, first generate a random, single-use salt value on the server. Send this salt value to the client, and generate a hash code from the salted version of the password the user has input. Send the resulting hash code to the server, and compare it with a hash code generated from the salted version of the stored password. If the comparison fails, discard the salt, regenerate a new salt value, and repeat the process.
The reason for the single-use salt is to prevent anyone listening to the conversation from capturing the hash code of the users password, which, when you use hash code comparison, is just as good as having the password itself.
Note that you need to keep the original password around, you can't hash it once on the server and save the hash in the database. If you need to ensure that the passwords stored in your database are also secure, then you will need to encrypt them before storing them. I believe that ASP.NET membership providers do allow you to store passwords encrypted, however, if you really wish to have a secure authentication mechanism that is difficult for a hacker to crack, then I would recommend handling password storage and retrieval entirely on your own.
Finally, I should note, that such a complex password transfer mechanism should be largely unnecessary if you use SSL to encrypt your connection during authentication.
References (for those who have never heard of Kerberos or SRP):
http://en.wikipedia.org/wiki/Kerberos_(protocol)
http://en.wikipedia.org/wiki/Secure_remote_password_protocol
This is a bad idea, security wise. If you send a non-ssl form that contains the hashed password, then anyone capturing traffic has all they need to login. Your javascript has to result in something that indicates success (a redirect, token passed to the server, etc). Whatever it is, the listener now can recreate that without proper authentication.
SSL was built for a reason, by people who tried a lot of other web authentication schemes. It is far safer and cheaper to get a cert than to try write your own safe authentication scheme that works without encryption.
Added for clarity:
Client side hashing alone is not safe. Say I have a form with the following inputs
<form action="signin.whatever" method="post">
<input type="text" id="txtUser">
<input type="text" id="txtPass">
<input type="hidden" id="hiddenHash">
<input type="submit" onclick="hashAndSubmit()">
</form>
where hashAndSubmit() hashes the password and puts it in hiddenHash, and blanks out the password field. If I sniff your submission and see the following fields:
txtUser:joeuser
txtPass:
hiddenHash:xxx345yz // hash result
that's all I need as an attacker. I build a form with your user and hash value and I'm all set. The password is not necessary for a replay attack.
To get around this, you have to look at one-time salt values, or other schemes. All of which introduce more cost(don't forget developer time) and risk than SSL. Before you do something like this, ask one question...
Do I trust myself more than years and years of public testing of the SSL encryption?
You could do this, but it would be just as insecure. The problem is that someone could capture the hash and replay it (just as they could the original password). I suppose you're providing some protection against the exposure of the actual password (in case they use it on other systems), but your system will be no more secure.
You can implement your hashing algorithm client side (in javascript) and send only the user name and hash result over the wire. Note that in order for this to be secure the hash must be salted with a string provided by the server, and the string must be unique for every request. The sever still needs to check whether the hash is correct or not and authenticate the session.
At least you have to use a salt for generating the hash. Otherwise the hash value is as "valuable" as the plain password when intercepted - at least on your site.
You can send as post fields the username/realm/password hash following the HTTP Digest protocol. AFAIK there is no built-in client component nor server side component to generate/validate this so you have to do everything manually. It also requires your storage to store a specific hash format, see Storing password in tables and Digest authentication
The advantage is that you're following a well analyzed and understood authentication protocol. Don't roll your own.

FormsAuthentication and setting the userID/name in an encrypted cookie, security risk?

Asp.net stores the session in a cookie, thus not having to worry about sessions on the server side (traditionally sessions are stored in a database, and lookups are done via a session ID, which is usually a Guid like string).
In my previous question, I was asking about how a spring application stores/creates sessions etc: Spring authentication, does it use encrypted cookies?
Cletus pointed out that storing a username/id in a cookie, although encrypted, is a security issue because the would-be-hacker has both the encrypted text, but also the hacker knows what the actual encrypted text is i.e. the userId or username.
What are you thoughts on this?
I am sure StackOverflow is also using this mechanism, as is **99.9% of asp.net web applications that are using formsauthentication in this manner.
Microsoft's MSDN site itself is filled with examples like:
FormsAuthentication.RedirectFromLoginPage(UsernameTextbox.Text, NotPublicCheckBox.Checked);
In the above code, the username value is stored in the encrypted cookie.
actually, I recall that the asp.net website was hacked because the web.config didn't have the Protection=All in the forms authentication tag.
So is this a real issue?
To repeat what cletus linked to:
In case you're wondering what a "crib" is. see: http://www.faqs.org/faqs/cryptography-faq/part03/
Cryptanalytic methods include what is
known as practical cryptanalysis'':
the enemy doesn't have to just stare
at your ciphertext until he figures
out the plaintext. For instance, he
might assumecribs''---stretches of
probable plaintext. If the crib is
correct then he might be able to
deduce the key and then decipher the
rest of the message. Or he might
exploit ``isologs''---the same
plaintext enciphered in several
cryptosystems or several keys. Thus he
might obtain solutions even when
cryptanalytic theory says he doesn't
have a chance.**
Maybe you should take a look into this document: Improving Web Application Security: Threats and Countermeasures -- Threat Modeling
It's a good start point to understand what security risks are involved and how can you mitigate that threats.

Resources