Encrypted Query String - asp.net

I have used MachineKey.Encode to encrypt a ID that is getting passed as a query string to a page but as expected this is making the URL huge.
Is there a option such as HTTP handlers that could customize the url but still load the required page?
Also I am yet to find out if MachineKey.Encode is using the MachineKey that I have defined in my web.config file to encrypt the data, can anybody confirm this for me with web information that backs this up.
Thanks.

Also I am yet to find out if MachineKey.Encode is using the MachineKey that I have defined in my web.config file to encrypt the data, can anybody confirm this for me with web information that backs this up.
It does indeed use the configured keys. MachineKey calls MachineKeySection.EncryptOrDecryptData to perform the encryption, which uses encryption objects configured from the machine key section. If you want to see for yourself, the interesting calls are EncryptOrDecryptData=>EnsureConfig=>ConfigureEncryptionObject=>SetKeyOnSymAlgorithm

Related

Getting ViewStateException: Invalid viewstate while Machine keys are the same

I have 8 host behind LB and all of them are single process(not web garden). Despite setting all of them with the same machine key from iis as shown below, I'm still getting Invalid viewstate exception rarely.
There similar questions but none of them helped me(I've no server with pending updates or restart as in the other questions or i'm not using server.execute etc). So please don't flag as duplicate. Are there any alternative ways to prevent this exception?
Thx
Normally, This is because of the difference in Machine keys in different servers. We use Web Farm for High availability. In this case, if a Client sends a request then the Load balancer decides, which webserver to serve the request. It happens several times that another request might be served by another server. So here is the issue.
As we know, view stat is Client-side state management techniques and the data travels with the request and response. So if the view state is encrypted with some machine key and in other requests if handled by another server and that has different machine key, it would not be able to decrypt it and will through the error.
Every server generates a new key when it is set auto. and even sometimes any recycle of the app domain will generate a new key when it is set to auto. It means we cannot use the default auto-generated key. So here the solution is to use a specific key in the machine.config to prevent automatic key generation on each process start.
One another flexible approach, however, would be to add a MachineKey section to the web.config file of your web site. This would not require to make the changes on every web server.
another way is you could try to set below code in machine.config:
enableViewStateMac="false"

Is it safe to write connection string in web.config?

Is it safe to write connection string in web.config in an ASP.net application.
The application will be using 2 databases and I think the connection string can be retrieved easily.
Can anyone please suggest a secure place(web.config or other file) for writting the connection string except encrypting it.
Web.config is the right place for this. You can encrypt the connection string if that's a concern for you. Encrypting the connection string in Web.config it's already supported in ASP.NET and it seems that you already know that...
Link for reference.
If your worry is the outside "hackers" stealing your web.config file, then it doesn't make a difference where you store it, since if they have access to the web.config file, they probably have access to any other location where you may store the CS anyways.
If on the other hand you want to protect from an internal threat, then try saving it into a separate file (even a simple text file will do) and give that file special access permissions that only allow you and the application access and noone else. Also, you may be able to do the same thing with web.config itself.

Hows does one prevent passwords and other sensitive information from appearing in an ASP.NET dump?

How does one prevent passwords and other sensitive data submitted to and received from ASP.NET web pages in IIS/ASP.NET dump files?
Steps to reproduce
Using Visual Studio 2010, create a ASP.NET MVC 3 intranet application.
Configure it to use IIS 7.5.
Fire it up and register an account (say bob123 as the user and Pa$$w0Rd as the password. I'm assuming that the SQL Express database is created and the site is fully functional.
Using task manager, right click on the w3wp process and create a dump.
Open the dump in an editor capable of displaying its contents as hex, such as SlickEdit.
Search for "Pa$$0Rd" and "Pa%24%24w0Rd" in the hex dump. You should be able to find several copies of it stored as ASCII, Unicode, or encoded.
Note that it doesn't matter whether you use HTTPS because it only encrypts the communication. ASP.NET stores that data in the clear in memory or disk.
The problem
Common wisdom has it to encrypt sensitive data and not to store it in the clear. However an employee may receive a dump of an IIS/ASP.NET application and discover passwords and other confidential data of users because this information is neither encrypted, nor is memory used by ASP.NET cleared after usage.
This puts them at risk simply because they have access to it. Dump are sometimes shared with partners (such as Microsoft) to help them diagnose issues in their code. It is a necessary part of diagnosing some really complex problems in one's application.
Things I looked at
Use SecureString for passwords and other sensitive data. However, the ASP.NET Membership provider, along with other frameworks like WCF, often accepts passwords as System.String, which means that those copies will still be in the dump.
Looked to see if there is anything in the framework to clear out a copy of System.String when it is no longer being used. I couldn't find anything.
Investigated whether one can zero out the memory used for requests and responses once IIS is done with it, but I was unable to find anything.
I investigated wether one can encrypt files IIS receives (as HttpPostFile) so that they are not stored in the clear. We may receive documents that are extremely confidential and every step is made to encrypt and protect them on the server. However, someone can extract them in the clear from an IIS dump.
What I was hoping for is to tell IIS/ASP.NET that a specific request/response contains sensitive data and that IIS/ASP.NET will clear out the memory when it is done using it.
A dump file by definition dumps all the memory the application uses at the moment it is dumped, If you were to create a filter so that certain things were excluded then you could never be sure that you had enough data to zero in on a problem.
Would you be comfortable handing over your databases / configuration settings to a third party? if not then you probably shouldn't be handing over dumpfiles either. (imho)
I know this doesn't answer the question directly but why not look at this problem differently.
You could easily put together some javascript to do the hashing client side. I would combine the password with something random such as a guid that is sent down by the server and is valid only for a single use. The data exchange would no longer contain the password and the hash could easily be compared server side. It would only be valid for the session so someone looking at the dump data couldn't use the hash to "authenticate" themselves in future.
On the file side, how are these files being uploaded? directly from a web page? There are quite a few javascript libraries that do encryption (blowfish) and I would definitely use this option when sending a sensitive file. It does have a speed penalty but you can be sure that the data is secure.

Encrypting sections of web.config. Should I?

I am responsible for several ASP.NET web apps running on a local Intranet server. Users outside the company aren't supposed to have access to the server, but I don't like leaving anything to chance if it's not necessary. And only admins should have access to the file system.
Should I encrypt the app settings and connection string sections of web.config? I haven't see this mentioned very often, and I was wondering if it's overkill or not a best-practice. I've got passwords in my connection strings and account info for a service account I use to query AD in the app settings.
BTW: I would encrypt using
Configuration webConfig = WebConfigurationManager.OpenWebConfiguration(System.Web.HttpContext.Current.Request.ApplicationPath);
ConfigurationSection section = webConfig.Sections["connectionStrings"];
if (section != null && !section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
webConfig.Save();
}
Should I encrypt the app settings and connection string sections of web.config?
If the connection strings include passwords: then yes, there is no other reasonable option.
If using integrated security to connect to the database, then the information exposure would be database and server names, which is less of an issue. But might be easier to have a deployment rule of always encrypting, because the simpler rule is easier to follow and audit.
You can also use aspnet_regiis.exe to encrypt sections, rather than writing your own code. Enter aspnet_regiis.exe -? into a PowerShell (or cmd) prompt to see options.
I did something similar for encrypting my web.config file, and I don't regret it. Maintaining it isn't complicated, and it adds yet another layer of defense. Since security is built in layer, there's nothing wrong in doing that.

How do I send a user ID between different application in ASP.Net?

I have two web applications and both are developed in ASP.NET. Now I want to provide a feature which enables the user to click from one URL in application site (one virtual directory of IIS) A to the other URL in application site B (another virtual directory of IIS).
I have two ideas to implement them, but both of them have issues. I want to know what solution should be optimum solution?
Solution 1: using cookie, so from both application sites, we could retrieve user ID information from reading cookie, but I am afraid if cookie is disabled in browser, this "jump" feature never works.
Solution 2: When the user redirects to an URL in another site, I could append user ID after the URL, I could redirect to this URL in another site http://www.anotherapplicationsite.com/somesuburl?userID=foo, but I am afraird that in this way userID will be exposed easily which raise security issues.
I work with this sort of thing a lot. What you're looking for sounds like a candidate Single Sign-on solution or Federated Security.
You might try doing something similar to the following:
Create a simple db or other sort of table storage with two columns "nonce" and "username"
When you build the link to the other site create a GUID or other unique identifier to use as a one-time nonce, passing it as a querystring ?id=. Insert an entry into the table with the current authenticated username and the unique identifier you created.
When you reach the destination of your link, pass the unique identifier to call a webservice that will will match up the identifier with the username in the database you inserted before jumping to the second site (secure this with ssl).
If the nonce checks out with a valid username, you're all set. The webservice should remove the used entry and the table should stay more or less empty any time you are not in the middle of a transaction.
It is also good to include a datetime in your nonce/username table and expire it in 60 seconds or less to minimize the risk of replay attacks. We also require client certificates for external applications to call the webservice in order to verify the identity of the caller. Internal applications don't really necessitate using client certificates.
A nice thing about this is that it scales fairly well to as many sites as you would like to use
Not perfect security, but we've never had a significant compromise with a such as system.
As long as you have a good authentication system in place on the second website I think solution 2 is the one for you, taking into account the remark Andrew made about the sensitive ID's of course.
For more information on encryption: check the documentation of the FormsAuthentication.Encrypt Method . I think they even do something with writing a value in a cookie in that example.
If you put the userid in a query string and that's all the 2nd app uses to allow login, what's to keep me from manually typing in other users id's? You'd still have to prompt for password on the new site.
I'd use a database to hold login information, and have both sites reference that same db. Use it like you'd use a session.
D
I don't think 1) will work due to browser security (cookies from one domain cannot be read by another domain). I would go with 2), except I would encrypt the querystring value.
EDIT: For more info on cookie privacy/security issues, check out the "Privacy and third-party cookies" section here.
What are you using as the user's id? If you are using their social security number or email (something sensitive) then you are going to want to encrypt the value before you put it on the query string. Otherwise (if the user's id is something ambiguous like an integer or a GUID) it should be fine to put the id on the query string.
using cross domain, you can not SHARE the session, so I was thinking about POST
idea 1
if afraid of "showing" the username in the address, why not sending a POST?
<form name="myForm" action="http://www.mydomain.com/myLandingPage.aspx">
<input type="hidden" id="userid" value="myUsername" />
click here
</form>
but then... off course, "View Source Code" will show it
idea 2
then.. I remembered that I do the same, but sending a Encrypted string like:
http://www.anotherapplicationsite.com/somesuburl?userID=HhN01vcEEtMmwdNFliM8QYg+Y89xzBOJJG+BH/ARC7g=
you can use Rijndael algorithm to perform this, link below has VB and C# code:
http://www.obviex.com/samples/EncryptionWithSalt.aspx
then in site 2, just Decrypt and check if the user exists... if it does, continue, if not saying that the user tried to temper the query string :)

Resources