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.
Related
I am working with the eBay API using OAuth on my current Meteor project app.
There is a section of the app where I can create an eBay account profile, and assign custom values to the account (such as nick-naming it, etc.). This is where I initiate the OAuth sign-in redirect process.
My question is about the 'state' parameter in the token requests. I understand that it is for helping prevent CSRF, but do I HAVE to use it that way? 'state' does seem to be optional after all.
Let's say I wanted to pass another value into the request call such as the string 'eBay Seller', and expect that the same exact string be returned in the response. I want to use that value to help my app determine which account to assign the returned tokens to (based on which account profile initiated the redirect link).
Is 'state' a valid place to pass in a variable that I expect to be returned exactly as sent? I considered using Session variables to handle this scenario, but quickly realized that this would not work, since the OAuth process takes me outside of my project's domain.
Does OAuth support passing variables that are expected to be returned as sent? Is sending my variable as 'state' allowed or even recommended (or absolutely not recommended?) Is there a better way to achieve what I want to do that does not involve updating database values?
Thank you!
You can send what you want as state. You should try to make sure it's not guessable though, to mitigate against CSRF attacks.
If you want to return useful information like 'ebay seller' then include something for CSRF (e.g. hash of the session key id) and the text 'ebay seller' and delimit them e.g.
2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824|ebay seller
Now you have the best of both worlds: useful state info + CSRF protection.
Your redirect endpoint logic can check the hash of the session id matches and also confirm the account type from the initial request.
I am using MVC3. I have a couple of pages which does not require authentication but these pages have querystrings which could be tampered. I am planning to encrypt these urls when sending to users and decrypting it back when they hit it, what is the best way to encrypt and decrypt query strings in MVC3? Send me a pointer If there is any module that I can reuse...
Why dont you trust in another kind of storage mechanism instead of a query string?. You could pass the information over a POST operation, there are several ways to do that, such as cache or other. Post automatically puts that information on the request header, and its hidden to the ussers, also if your site is over SSL connection, that information is encripted.
You could improve security to your site against malware petitions with integrated MVC security features, such #Html.AntiForgeryToken(), this prevents that a malitious site tries to bypass your system impersonating a real petition. In a nut shell this means that a unique ID is printed on the form header when the form is sent to the client, and if the ID does not equals the one that the server expects, simply the request is ignored.
Heres an interesting post that could help you.
https://sites.google.com/site/muazkh/asp-net-mvc-security-and-hacking-defense-in-depth
Best regards!
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.
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