I have a message that I am passing to myself which will be subject to man-in-the-middle attacks. Because of that, I am concerned about the integrity of the message being maintained between the time I send it, and the time that I receive it back.
It should be assumed that once I send the message to myself, no information about the message sent will be available to me in the future. The message is completely self-contained.
To that end, I know that should hash the message contents and compare the hashes before I send the message, and after I send the message, if they differ, then the message has been tampered with.
Of course, if the man-in-the-middle knows that the hash is really just the hash of the message contents, as-is, then because the message is self-contained, he can just create new contents and apply the same hash algorithm to the contents.
The question is, to what lengths should I go to randomize the message contents when generating the hash? When does it reach the point of diminishing returns?
In this scenario, I have a set of key/value pairs. To that end, the steps that I know I HAVE to take are:
Add a salt to the message. The salt is a secret to the rest of the world. It gets attached to the contents of the message before hashing.
Order the key/value pairs in a consistent manner before generating the hash.
While not directly relevant, a timestamp is going to be added to the contents of each message before hashing, to prevent replay attacks.
These are the optional steps that I am considering:
Transforming the keys before I order them. I've considered reversing them, then ordering by count/key.
Playing with the separators that separate key/value pairs (both for the separator for the key/value and the separator for the pair).
NOTE
Message privacy is not a requirement here, so I am not looking for encryption. The values must be transmitted in plain-text.
Finally, what hashing algorithms should I avoid?
Specifics
I have an ASP.NET MVC site which I have a controller which handles input validation and persistence.
If (based on a heuristic, it's not important which) the input is determined to be an automated spam attempt, a model of IDictionary<string, string> is created with the input values and a ViewResult is sent to a general CAPTCHA page.
In that view, in the form that contains the CAPTCHA control, the contents of the IDictionary<string, string> will be written out in hidden input fields, and the action of the form will be the same action that the contents were originally posted to. This way, MVC can pick up the values when the form is resubmitted.
It's because of this I can't encrypt the key/value pairs (or maybe I can and should, tell me why and how!).
Of course, I need to add one more value, which contains the hashed message contents. If that value is there, then the controller will check to see that the message integrity is maintained, and allow the input to be persisted if it has.
Solution
I've opted to go with the SignedCms class in the System.Security.Cyrptography.Pkcs namespace, which represents the signging and verifying of CMS/PKCS #7 messages.
To elaborate, I've created a self-issued certificate with MAKECERT.EXE and then in my code, I use the example here to digitally sign the data:
http://blogs.msdn.com/shawnfa/archive/2006/02/27/539990.aspx
Now, it should be a matter of keeping the password on the exported private key secure, as well as security on the server, which makes it less about programming.
I'll have to add an extra key for the timestamp for replay attacks, but that won't be too hard.
The answer goes to Kalium, not for his initial post, but for his follow up comments which pointed the way to digital signatures, and eventually my discovery of how to utilize them in .NET.
Thanks to everyone who contributed.
I think PGP/GPG is what you want here.
The most straight forward approach to allow your application to verify that its own messages have not been tampered with would be to use a keyed hash message authentication code. The message is sent in the clear, but it also includes a hash to prevent tampering. The hash depends on both the message contents and a secret key. The man in the middle can't forge a hash on an altered message without knowing the key. Since your application both creates and verifies the messages, it never needs to disclose the secret key.
I would particularly recommend the implementation described in RFC-2104 http://www.ietf.org/rfc/rfc2104.txt as it has been carefully thought through to avoid most of the likely pitfalls.
If the messages must also be verified for authenticity by untrusted parties, then you should use a digital signature scheme instead.
There is likely some support for both in the .Net libraries. Miles helpfully provided (as a comment) a link to the MSDN web page for the .Net library functions implementing a keyed HMACs using the SHA1 hash: http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx.
You want a Digitally Signed message. Using GPG you can sign the message without encrypting it. But no one will be able to tamper with it, because they can't generate the hash - only you can because the hash uses your private key.
You should probably digitally sign the message (hence PGP/GPG recommended by Kalium is relevant as an option). Any pure hash that you can create can be recreated by the attacker. Digital signing - using your private signing key so that your public key can be used to verify it - is the solution. Anything else is an exercise in futility.
Assuming that you can't pass any information over a "secure" channel (i.e. the hash) here's how you would do it:
Hash the message, then sign the hash with a private key. Include the signed hash in the message.
When you get the message, use the public key to decrypt the signed hash and verify that it matches the actual hash of the message.
An attacker would not be able to "fake" a message, since they would need to have your private key in order to encrypt their new hash.
As others have mentioned, this is just plain vanilla digital signing and can be handled by something like PGP/GPG
Related
I want to encrypt Yii2 URL parameters
Example: http://localhost/school/backend/web/index.php?r=user%2Fview&id=20
20 must be encrypt.
Whats the simplest way in Yii2 to achieve this.
The problem with trying to encrypt part of the URL like that is that the client browser must have the key to use for the encryption. You can supply that over HTTPS but it would mean that anyone could also obtain the key. Alternatively you could have one key per browsing session, but that will impact performance and may be overkill.
What's the reason for encrypting the id parameter? If it's just to avoid an insecure direct object reference then you could create a hash for the user based on random data (you'd need a unique hash for each user object). The hash would make it difficult, but not impossible, to correctly guess another object's hash. Essentially this is security by obscurity.
A better approach is to securely handle viewing other IDs. For example, it may be that I'm allowed to view my own objects / users but not yours. To achieve this you should programmatically check the user is authorised to view the object in question. This does mean writing more code but is a significantly better way of doing things.
Submitting the request by HTTP POST would only protect you from a casual user. A more skilled user (or attacker) would just intercept the POST request, modify the value and send it on.
I have an iPhone App communicating with a web server. When starting the App the user must authenticate with a user name and password.
The communication between the App and the web server is secured (HTTPS) but I don't want to send to the web server the clear password, I would like to send just the "signature" of the password (the signature will be stored in the database on the web server).
What is the best solution to create this "signature" on IOS? Should I use MD5 or something else?
Do I need to get an external library to build this signature or can it be done using SecKeyEncrypt from IOS SDK?
In the long term I will have an App running on Android and I must be able to generate the same signature for IOS and Android.
Thanks for your help,
Sébastien.
Transmitting the password in clear text is bad, so doing anything is a good first step. If you're going to make the effort, it is worth knowing how to do it right.
While MD5 is not a strong hashing algorithm anymore, choosing between MD5 and SHA256 (or even SHA512) is less important than how you use it. Let's ignore the specifics of the hashing algorithm and look at how it can be used first.
The idea of using a hash is that the hash of a string is always the same and is a one-way operation. By capturing the string, it is not supposed to be possible (or practical) to determine the password. That has become untrue in recent years with the mass use of rainbow tables. A rainbow table contains every possible password (up to a given length) and their hash, so that the attacker can use a reverse lookup to discover the password. Rainbow tables are readily available for all hash algorithms for passwords under 16 characters.
There are a few common solutions to this problem. One is to perform the hash many (around 1,000) times. The exact number of times must be known and predetermined by both the client and server so they can do it the same. This has the advantage and disadvantage of making hash generation expensive. It becomes computationally more difficult for an attacker to brute force, but rainbow tables are still useful if they are expanded to be large enough.
A better, but less common, solution is to add a known random string (commonly referred to as a Salt) to the password to make it long (maybe 64 characters). This salt must be known by both client and server in advance. This solution is cheap and easy, and it doesn't even matter if the salt is leaked out.
There is another common problem with password hashing. If a malicious user knows the hash of a user's password, that is as good as knowing the password itself for a poorly designed system. Let's assume we have an RPC function that requires a username and password hash. A malicious user that knows the password hash can submit it, even without knowing the password, and get access into the system. This known password hash will continue to work until the user changes their password, which could be months or years. What is needed is a way to limit the duration that the password hash is useful. That is achieved by using a dynamic salt.
The authentication then becomes a multi-step process.
The client connects to the server and presents some sort of client (or device) identifier, such as a UUID.
The server then generates a dynamic salt for that client identifier. The dynamic salt is only good for a short period of time (generally minutes to hours).
The server stores the dynamic salt, its expiration, and the associated client identifier in a database table for future use.
The server returns the dynamic salt back to the client, along with its expiration.
The client hashes the password, using either of the two mechanisms above, concatenates the dynamic salt, hashes again, and then attempts to authenticate by using username, client identifier, and dynamically-salted hash.
The server validates the submitted credentials by checking the users known password hash against the submitted value trying to concatenate and hash each known dynamic salt for that client identifier. If a match is found, authentication is accepted.
This is (roughly) the mechanism that is used by MySQL. It is secure enough that it can be used without SSL safely, but I would always recommend using SSL so that the rest of the payload is protected.
If you use secure mechanisms like this, it doesn't matter much if you use MD5 or a SHA variant. That said, it wouldn't make sense for any new development to not use SHA256, unless there was a very good reason MD5 was necessary.
md5 is not the best idea - there are lots of really fast rainbow tables nowdays to decrypt them.
I would suggest using AES256 - on iOS you have NSData+CommonCrypto which allows you to easily do that.
NSString* encryptionPass = #"myEncryptionPass";
NSData* passData = [userPassword dataUsingEncoding:NSStringEncodingConversionAllowLossy];
NSError* error = nil;
NSData* encryptedPassData = [passData AES256EncryptedDataUsingKey:encryptionPass error:&error];
if(!error)
{
NSString* encryptedString = [[NSString alloc] initWithData:encryptedPassData encoding:NSUTF8StringEncoding]
}
I'm working on a project that will generate an OAuth querystring in JavaScript, using HTTPS and in internal application, so security is not a major concern at this point (figured I'd mention that up front )
The JavaScript querystring is used to call a C# script on a different server and domain, essentially to pass data from the internal application to the C# application, and allow to verification that a) the query comes from the right source, and b) the query is valid and hasn't expired, etc.
OAuthSimple gives me a signed URL like this:
http://www.myremotesite.com/mycodepath/mycodefile.aspx?firstname=Kevin&lastname=Blount&oauth_consumer_key=ThisIsTheConsumerKey&oauth_nonce=nuOoM&oauth_signature=DAoaSxD5SvVFTTDNSxiTbANzGlc%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1313162452
My question is, one the C# side of things.. what do I do next? I've two thoughts, but I can't work out which I need to explore:
using C# generate a new signed URL and compare the two (or just compare the oauth_signature values)
take the querystring and somehow decrypt/decode it and verify it.
I'm told that DotNetOpenAuth is the standard to use, but I can't figure out my next step using it.
Can I get some advice on what I need to look into, or articles that explain how I should proceed?
Read the instructions on DotNetOpenAuth and make sure you understand it. I haven't used it previously, but have heard good things about it.
The oAuth server will do several steps:
Validate version - Is the client using the correct version of oAuth for you to handle
Validate TimeStamp - All timestamps must be in UTC to avoid Time Zone problems
Validate Nonce - Has it been used previously allowed time range
Validate Signature - Get the private key from the consumer key, compute the signature using the values passed in the parameters and compare to the actual signature.
Once the message has passed all the checks, then the server will return the resource requested by the message
I'm going to be writing the services for an iPhone app being built by a third party vendor.
I'll be using ASP.NET MVC to accept posts and also return JSON formatted data.
My question is, how do you secure it?
Just using an API key perhaps? Would that be enough to ensure that only data from the iPhone apps are allowed to hit the specified services?
I'm sort of struggling with the same concepts myself. I think the first thing is to do HTTPS only, so that it's starting out more secure than not.
Next, it depends on how you're going to do authentication. If all you need is an API key, (to track which entity is accessing the data) that should be fine. If you also want to track user information, you'll need some way to associate that specific API keys can access specific types of records, based on a join somewhere.
I'm looking at doing forms auth on my app, and using an auth cookie. Fortunately ASP.NET on IIS can do a lot of that heavy lifting for you.
Example time: (I'm sure I'll need to add more to this, but while I'm at work it gives something to gnaw on)
Forms auth:
Send a pair (or more) of fields in a form body. This is POST through and through. There's no amount of non-reversible hashing that can make this secure. To secure it you must either always be behind a firewall from all intruding eyes (yeah right) or you must be over HTTPS. Simple enough.
Basic auth:
Send a base64 encoded string of "username:password" over the wire as part of the header. Note that base64 is to secure as a screen door is to a submarine. You do not want it to be unsecured. HTTPS is required.
API key:
This says that an app is supposedly XYZ. This should be private. This has nothing to do with users. Preferably is that at the time that the API key is requested, a public key is shared with the API grantor, allowing the API key to be encoded on transit, thus ensuring that it stays private but still proves the source as who they are. This can get complicated, but because there is an application process and because it won't change from the vendor, this can be done over HTTP. This does not mean per-user, this means per-developing-company-that-uses-your-api.
So what you want to have happen is that for the app accessing your data, that you want to make sure it's an authorized app, you can do negotiation using private keys for signing at runtime. This ensures that you're talking to the app you want to talk to. But remember, this does not mean that the user is who they say they are.
HOWEVER.
What you can do is you can use the API key and the associated public/private keys to encode the username and password information for sending them over the wire using HTTP. This is very similar to how HTTPS works but you're only encrypting the sensitive part of the message.
But to let a user track their information, you're going to have to assign a token based on login based on a user. So let them login, send the data over the wire using the appropriate system, then return some unique identifier that represents the user back to the app. Let the app then send that information every time that you are doing user specific tasks. (generally all the time).
The way you send it over the wire is you tell the client to set a cookie, and all the httpClient implementations I've ever seen know that when they make a request to the server, they send back all cookies the server has ever set that are still valid. It just happens for you. So you set a cookie on your response on the server that contains whatever information you need to communicate with the client by.
HTH, ask me more questions so we can refine this further.
One option would be to use forms authentication and use the authentication cookie. Also, make sure all the service calls are being sent over SSL.
How does one protect against XSRF attacks in Grails. I see that forms support the notion of useToken which (I think should suffice). However, remoteForm or other AJAX related request don't support this feature.
Also, is there a way to invert the functionality of useToken so that it is always used rather than enabled on a case by case basis?
You could try looking at the source code of the <g:form> tag. It uses a SynchronizerToken to create a token and store it in the session. Based on the resolution of this issue it should be possible to use the same token for all forms on the same page. I did not try this, but theoretically you would just need to manually create a hidden field on the form and generate the token in that field.
We have inject a hidden value to the request object in a before filter and encrypt the value with a specific key. We then inject that request.token value to every form on the site and when we receive a POST we have a before filter to verify that that hidden field is present and its value can be decoded by that same secret key.
If that hidden value is not present or if it is stale -- we use a timestamp as payload -- we give the client an error status.
This is an alternative way to what was described above and we use this, because we do not use sessions on our sites to make it easier to load balance.