How are parameters for ScriptResource.axd calls generated? - asp.net

A client has custom firewall rules around their website to prevent any number of attacks. One of the custom rules blocks all requests (either GET or POST) including a double hyphen, in order to prevent SQL injection. While updating their website last night, we had an issue where on every page, one of the calls to the ScriptResource.axd included a double hyphen(--) resulting in access to the script being denied.
We had seen this issue previously and thought we had worked around it by using the ScriptReferenceProfiler in order to generate the list of scripts we'd need to combine in order to remove so many script references. That was working until the update last night when the issue reoccurred. (Interestingly, I reran the ScriptReferenceProfiler and all of the scripts it identified were already included in the CompositeScript listing so I don't know where this file came from.)
I finally created a new IIS virtual directory where the issue with the double dashes didn't occur, despite pointing to the same directory and codebase as the previous virtual directory. (I set the initial virtual directory to act as a redirect to the new one so the users wouldn't have to worry about updating links or bookmarks.) I can see from this post that the first parameter is generated via encrypting the assembly name and resourcename which explains the difference in the values between the two virtual directories.
But obviously, I'd like to avoid this situation in the future. Does anyone have any thoughts as to how to prevent double dashes from appearing in the ScriptResource requests?
For reference, this occurred in a VB.Net website running in .NET 4.0 on IIS 6/Windows Server 2003. Additionally, the script file being rejected was for an Infragistics control of some sort. (I turned off the firewall rule briefly in order to get the file and then re-enabled it. I wasn't able to tell from the script what role it played for Infragistics, though.)
Thanks.

The first parameter (d) is the assembly and the resource. For the assembly, this includes the name and version as well as the public key token if the assembly is strong named. If any of these change then the string for the resource will also change.
The second parameter (t) is just for the timestamp and this allows the resource to change if an assembly containing an embedded resource is updated without the assembly name or version changing even if caching is enabled on a site.
The encryption of the first parameter is based on the MachineKey so you could change the MachineKey to change the string that results from the encryption. This may help you to have a simple workaround for the issue when it does come up even if you don't control the names and versions of all of the assemblies that you use.
Related reading that may be of interest to you:
machineKey Element (ASP.NET Settings Schema)
How To: Configure MachineKey in ASP.NET 2.0
Debugging ASP.NET 2.0 Web Resources: Decrypting the URL and Getting the Resource Name

Related

Confused on what is the correct procedure on storing passwords in Web.config for Azure deployment

I've had a very frustrating experience on putting an MVC 5 app on Azure. I have been reading the following page: http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure
But what I haven't managed to put in my head is the following:
Security Warning: Do not add your secrets .config file to your project or check it into source control. By default, Visual Studio sets the Build Action to Content, which means the file is deployed. For more information see Why don't all of the files in my project folder get deployed? Although you can use any extension for the secrets .config file, it's best to keep it .config, as config files are not served by IIS. Notice also that the AppSettingsSecrets.config file is two directory levels up from the web.config file, so it's completely out of the solution directory. By moving the file out of the solution directory, "git add *" won't add it to your repository.
And:
Security Warning: Unlike the AppSettingsSecrets.config file, the external connection strings file must be in the same directory as the root web.config file, so you'll have to take precautions to ensure you don't check it into your source repository.
The problem is the following: When I upload the Web.config file with the external files without being included I get hit by "The System cannot find the file specified", so for it to go away I must include the .config files defeating the purpose of Microsoft's post.
I really really really do not understand. I have added the connectionStrings and appSetting's keys in Azure's portal. What is the correct and secured way of putting my passwords and secrets online? What am I missing? Is it because I'm running in Debug mode?
According to this:
How can I secure passwords stored inside web.config?
There is nothing to worry about accessing the Web.config file...
But that just defies Microsoft's post.
Thanks.
I find the following technique to be the easiest way to do this.
Instead of putting the deployment values of these settings into the web.config, I keep the test values in there instead. I then put the deployment values into the Application Settings section of the Azure Website via the Azure Portal:
When the website runs, these settings will take precedence over what is in the web.config. This helps me avoid externalized files, allows me to keep sane development configuration that the team can share, and makes deployment very easy.
The best way is to set your secrets in the Connection Strings section of the portal. Any values set there will override values you specify in your web.config file.
This way they are only exposed to people who have admin access over the site itself. Having full access to the source won't even be enough to get the secret values.
More details here

Add subdirectory for locale based URL existing ASP.NET website, resolve relative paths correctly

Existing ASP.NET (MVC and webforms hybrid) website displays translated content. The language is based on a cookie that stores the user's preference. There is no change in the URL when the user changes the setting. The content is reloaded in the preferred language. For SEO, the locale should be included in the URL ( support.google.com/webmasters/answer/182192?hl=en).
I've tried the following:
1) Use URL Rewrite Module: (http://www.iis.net/learn/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables)
Issues:
- All hyperlinks and redirects still point to the old URL without the locale.
- Complex outbound rules required based on the folder structure and usage (mixture of absolute paths and relative paths e.g. ../, ~/, /).
- Also need to disable static compression as per documentation
- Performance considerations due to large size of Html.
- Postback results in runtime exceptions due to issue in the relative path rewrite.
- Paths defined in script files (ajax loading etc) are a huge challenge
- Base tag does not work as expected, because the Rewrite Module seems to append ../ (http://www.iis.net/learn/extensions/url-rewrite-module/url-rewriting-for-aspnet-web-forms#Using_tilda)
2) IIS 7.5 Virtual Directory: Create Virtual Directory for each language and point it to the root. i.e. www.example.com is the root and www.example.com/fr-ca/ is a virtual directory mapped back to the root
Issues:
- Runtime exception in config file saying that the virtual directory needs to be converted to application
- Converting it to application gives 500.19 error due to duplicate entries in the web config (since the virtual directory is pointing back to the root)
- I tried moving the root to another subdirectory (i.e. have a physical directory for each language) to avoid web config conflicts, but that is resulting in some sort of "kernel" error. Also, this would mean changing the physical structure of the application, and also address routing issues
3) Using sub-domains:
I have also considered using sub-domains and hosting the application independently for each language, but this has a lot of drawbacks, including having to address scalability, single sign on, cookies, domain specific stuff like analytics etc.
So what is the least painful way to include a language sub-directory in the URL, and make all links relative to that sub-directory?
Note: The site contains a mixture of absolute paths and relative paths e.g. (../, ~/, /) sometimes used in conjunction with ResolveClientUrl, ResolveUrl
In the end, we went with option 2, with the below steps:
Create a new folder, deploy a copy of the application to the new folder. The new folder should be in a different directory from the root application.
Create a new virtual application* (not virtual directory) under the root application; 1 for each new language, pointing to the new folder. (If the need arises in the future, any of the virtual applications can point a different folder customized for that specific language)
In the new folder, remove the modules and handlers sections in the system.webServer section of the web.config file (they will be inherited from the parent web.config)
If you are using SQL session state, you will need to specify a custom Application Name in the web.config, and modify TempGetAppID stored procedure so that the Application Name is the same across all the virtual applications. See the following (http://blogs.msdn.com/b/toddca/archive/2007/01/25/sharing-asp-net-session-state-across-applications.aspx)
Hopefully, all the links are resolved on the server side using Url.Content (MVC) or ResolveUrl (webforms). If not, they need to be fixed. Any paths specified in javascript would not automatically resolve to the virtual application either (they would still be resolved to root application)
Test the heck out of it. Each and every link. (A tool like ScreamingFrog may help to make sure that no 404s are returned, methinks. But it wouldn't solve HTTP POST)
Note that depending on custom error handling, and any existing URL rewrite rules, the steps maybe different.
Summary: option 1 (URL Rewrite) is totally impractical. Option 2 (sub-directory) is the most practical solution, however it is not quite as straightforward as it should've been.

Custom VirtualPathProvider unable to serve URLs ending with a directory

As part of a CMS, I have created a custom VirtualPathProvider which is designed to serve a single file in place of an actual file structure. I have it set up such that if a file actually exists on the server, that file will be served. If the file does not exist, the virtual content stored for that address will be served instead. This is similar to the concept of serving a website from files stored in a database, though in this case the content is stored in XML files on the server.
This setup works perfectly when a request is made to a specific page. For example, if I ask for "www.mysite.com/foobar.aspx", the content that is stored for "foobar.aspx" will be served. Further, if I ask for "www.mysite.com/subdir/foobar.aspx", the appropriate content will also be served.
The problem is this: If I ask for something like "www.mysite.com/foobar", things begin to fall apart. If the directory exists on disk (and doesn't have a configured default page in IIS, such as index.aspx), I will get a "Directory Listing Denied" error. If the directory does not exist, I'll simply get a 404 - Resource Not Found.
I've tried several things, and so far nothing I've done has made a bit of difference. It seems as though IIS is simply noting the nonexistence of a directory (or default file in an existing directory) and serving up its own error code, without ever asking my application what to do with the request. If it ever did get to the application, I would be able to solve the problem, but as it stands, I'm quite lost. Does anyone know if there is some setting in IIS that is causing this?
I've looked for every resource I can find on the subject, and am coming up empty. I know this should be possible, because I have read tutorials on serving content from both databases and ZIP files. HELP!
p.s., I am running IIS6 and .NET 3.5
IIS will only pass a request to the ASP.NET process if it is configured to do so for the particular extension. The default is aspx, ascx, etc. In other words, if you request a .html file, ASP.NET will never see that HTTP request. Likewise for empty extension.
To change this behavior, add a wildcard mapping to the ASP.NET process. Load IIS Manager, go to the Properties for your web site and look at the Home Directory tab. Click on "Configuration" and there you will see the extension-to-applicaiton mappings.

Storing connection strings in web.config

Why do we store connection strings in web.config file? What are the benefits of doing so?
The web config file is used so you can reference the connection anywhere in your app. It avoids having to deal with a fairly long connection string within your application.
Here is a good article which may give you detailed information: http://articles.sitepoint.com/article/web-config-file-demystified#
There is even a wiki page for it :) (surprisingly):
http://en.wikipedia.org/wiki/Web.config
If you ever move / change to a different database format the connection string setting inside of the web.config file can be changed in one place rather then digging through your entire application looking for it. This also avoids having to recompile or build an application to get the new connection string setting.
If you are wondering how to access the information from within a web.config file that can be found here:
http://msdn.microsoft.com/en-us/library/4c2kcht0(VS.85).aspx
There is also sample code right in there.
Imagine you have several classes which access your database; you can:
Place your connection string in every class
Create a constant to store that value
Place it inside your configuration file and to refer it
These have following characteristics:
Every time a connection string changes, for instance, migrating from development to production environment, you'll need to change everywhere;
By using a constant, you just need to change a single place. But in this case, when your string needs to be changed, you'll need to recompile it.
Same as above, without that recompile part. You can to develop your application and other people set that database connection to you
So, by storing a connection string into your web.config file you gain more flexibility to change that setting than other alternatives.
Reason #1
As everyone is mentioning, having the connection string in the web.config makes it easy to update/change as needed. It becomes a single source where the arguments can be easily be changed.
Reason #2
Beyond that though, IIS is configured not serve up web.config to users who request the file. If your website is,
www.mydomain.com
someone can't hit http://www.mydomain.com/web.config and scrape all your confidential settings, passwords, and so forth.
(As a side, note, IIS won't serve up files in the App_Code directory either to a user, so the web.config file isn't unique in this respect.)
Reason #3
ASP.NET automatically detects changes to configuration files and will immediately applies new settings.
More info..
MSDN has a discussion of the ASP.NET configuration system at,
http://msdn.microsoft.com/en-us/library/aa719558%28VS.71%29.aspx
What I like most about having the connection string in the web.config is when you have multiple environments that you test on. Say you have a Test server, Staging server and a Production server. Well you don't need to have code that checks which server you're on, or have to recompile different versions for each... just use the web.config to store your connection strings and that way you can have a different web.config on each server but the same web application with no hassles. You may want to Encrypt your Connection String Settings as well so they're not visible to everyone that has access to the folder.
You can reference them using the ConfigurationManager via the ConnectionStrings property.
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.connectionstrings.aspx
It allows the connection string to be configured by someone maintaining the site.
You don't have to re-build the application if the connection string changes. An admin can make the change and the code remains the same.

Culture name is not supported

I'm receiving "culture name 'uploads' is not supported" when my ASP.NET application start. Where do I have to view/debug to toggle the error?
A full-text search for "uploads" returns 0 entries in my project.
I've deleted this folder and it solved the problem:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\8dfb04ef\44bf70fb\uploads
Do not worry, it is not a real error.
When the runtime tries to find which resource assemblies exists, it tries to enumerate folders where compiled DLL files reside. It assumes the name of the folder is the culture name, so it tries to create a culture for it. Unfortunately uploads is a folder which is created automatically by ASP.NET, and it is obviously not a culture :).
The runtime ignores some predefined folders like "hash", but not "uploads". So we have to live with it.
I am getting the exact same error. ["culture name 'uploads' is not supported"]. I do not know what is causing it but I've been able to get around it by clicking [Debug|Exceptions (Ctrl-alt-E) and un-checking "Common Language Runtime Exceptions". I do not have an 'uploads' folder or file in my project and there is nothing in my project that has anything to do with multilingual support and the error fires right off the bat when I run my project ... looking at the call stack just walks me through a whole lot of mscorlib calls. I have no clue why it's even getting called.
JumpingLethalRampage, instead of unchecking all "Commong Language Runtime Exceptions," you could uncheck just "Common Language Runtime Exceptions > System > System.ArgumentException." You don't need to uncheck all CLR items.
It sounds like maybe you have some code somewhere that is trying to set the culture based on a URL pattern (this may be tracked down if it is possible to get a stack trace). For example, sometimes I'll set up multi-lingual sites with URLs like this:
http://www.example.com/en-US/
http://www.example.com/es-MX/
I'll then have code in my base page that looks at the URL and attempts to set the culture based on the URL path. But if you tried to hit a URL like:
http://www.example.com/uploads
It would fail with an error like what you are seeing if you just blindly take the first path element and try to use it as the culture without checking it first.
If the application is it built upon DotNetNuke (and not a simple ASP.NET application), this kind of error generally occurs in DotNetNuke due to the issue described in Culture name '__page' is not supported.
If you are not using DotNetNuke, check your Application_Start code (in the Global.asax file). It might be setting the CultureInfo. Or check your web.config file for any invalid culture values.
Assuming that your search through the project wasn't restrictive (widest possible search in all files), then my guess would be that your browser has a User language set to a custom string - "uploads".
In IE, you can check via Tools -> Options -> Languages -> Add -> User defined language.

Resources