How do I securely read the asp.net root configuration folder? - asp.net

I have a Windows Server 2008 R2 machine running IIS7.5. This webserver hosts many websites under different domains and each website contains several asp.net applications.
Support and development access to this machine is quite restricted due to customer requirements. I want to use the Microsoft.Web.Administration library to query the configuration of each of these applications in an asmx web method:
[WebMethod(MessageName = "GetDatabases")]
public List<Connection> GetDatabases()
{
List<Connection> connections = new List<Connection>();
ServerManager sm = new ServerManager();
foreach (Site site in sm.Sites)
{
foreach (Application app in site.Applications)
{
System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(app.Path);
foreach (ConnectionStringSettings cs in config.ConnectionStrings.ConnectionStrings)
{
try
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(cs.ConnectionString);
connections.Add(new Connection { Site = site.Name, Path = app.Path, Name = cs.Name, InitialCatalog = builder.InitialCatalog, DataSource = builder.DataSource });
}
catch
{
connections.Add(new Connection { Site = site.Name, Path = app.Path, Name = cs.Name});
}
}
}
}
return connections;
}
This code runs fine in Visual Studio but once deployed to the server an error occurs:
Server was unable to process request. ---> Filename: redirection.config
Error: Cannot read configuration file due to insufficient permissions
I researched how to work around this issue and found this page:
http://www.iis.net/learn/manage/configuring-security/application-pool-identities
So I created a new application pool just for this webservice and configured the Application Pool identity to have read-only access to the folder containing redirection.config (C:\Windows\System32\inetsrv\config) using the ACL of the folder. (I did this for the folder rather than the file as it seems that more than one file in the folder is required.)
My question therefore is: as long as I restrict access to the webservice properly, are there any security implications with doing this? It seems ok to me but the implications of making the configuration of these customer sites public could be career limiting to say the least!
Thanks,
Owen
EDIT: Just wondering if I have worded this question properly? So far no-one has taken a stab at answering it so this edit is mainly to bump it ;)

I'm no security expert (so take my words with a pinch of salt), but I would say that there isn't a hard and fast answer on this. However, most probably lean more towards recommending against this.
If your requirement is to allow support to see the connections your different sites use, then I see no issue creating a service like this in general principle, so long as you are careful.
That said, there are a number of things you should think long and hard about before going ahead with it:
Could the same be achieved by simply creating a secured share on the Server, and granting your support/devs RO access to that location? That may be more secure than writing your own service.
If you are doing this via a webservice, you should add security to the service to prevent unauthorised access (I'd probably use windows authentication myself, but that depends on your requirements)
I would recommend that you ensure that this service is not visible outside your Local network: you don't want someone from the wider web to be able to get onto this
Use an SSL connection for your service, to prevent packet sniffers being able to snoop on your traffic and retrieve this sensitive information.
I would recommend stripping out sensitive information from the Connection string before displaying it. At a minimum, I would remove the password. Anyone who needs the password already knows it, or knows how to get it. Anyone who doesn't need it won't be able to get it via this tool. You may also want to strip out all but the last part of the IP, it's not really secure, but it helps obfuscate information that would make it easier to hack.
Above all, you almost certainly want to communicate this to management/the customer, clearly lay out the potential risks, and detail what (if anything) you will do to mitigate it. If they sign off on it after all that, then the responsibility is really with them.

Security of the web service should be your last concern, primary concern is should you even make such a sensitive/confidential data available through a web service?
And the answer is straight NO.
More than security threats there may be quite a few legal implications on doing such a thing. Even if your customer is the sole owner of all the Apps running on their server they themselves may not be free decide about implementing such a functionality, as it may potentially be a threat to sensitive data belonging to their clients. So if you yourself are planning to make such a decision then you can very well imagine the consequences.
Moreover access to the servers and sensitive data like connection strings is restricted for obvious reasons, and that restriction should not be breached under any circumstances.

Related

How can I deliver an an encrypted file from my web server?

I have a web application running under Windows/IIS that includes some reports via SSRS.
I would like to be able to render a report, somehow save it on the web or SSRS file system, create an encrypted version, and deliver that encrypted file to the user.
I've considered creating a zip file with a password, but not sure about how well that would work.
What would be the best way to do this?
There are a couple of issues in this - and I have to work on the assumption that the purpose of encryption is that you want to be able to distribute the report in a way that only authorized users can view it.
The simplest way of achieving this goal would be to have a login scheme, and serve the report over HTTPS. This means only those who have a log-in can download the report, and it can't be intercepted using network sniffing.
In the past, a client insisted that they wanted to avoid allowing users to download unencrypted files, because they might forward the (unencrypted) report to un-authorized users. To meet this requirement, we created a windows service which created encrypted ZIP files; we used a service because performance tests showed that creating the ZIP in the context of a web request created a serious scalability issue.
The major problem you have with this scheme is distributing decryption keys; making sure everyone has the right key for their report is a huge pain in the backside.
It also didn't prevent users from decrypting the ZIP file and emailing on the unencrypted report - but this was a clear breach of IT policies, which was a harder point to make with unencrypted reports.
Maybe 7-zip or TrueCrypt?
Both require the installation of additional software however. I'm really not sure how strong ZIP file password protection is, so I would be hesitant to go that route without some research.
TrueCrypt is pretty secure, from my understanding.
You'll need a reference in your project to http://<Server Name>/ReportServer/ReportExecution2005.asmx. See the example included in ReportExecutionService.Render Method for how to execute and render a report. You can then take the returned byte array from the render method and create a MemoryStream based on it.
You can perform simple compression using thing in the System.IO.Compression Namespace like this:
public void CompressData(Stream uncompressedSourceStream, Stream compressedDestinationStream)
{
using (DeflateStream compressionStream = new DeflateStream(compressedDestinationStream, CompressionMode.Compress))
{
uncompressedSourceStream.CopyTo(compressionStream);
}
}
public void DecompressData(Stream compressedSourceStream, Stream uncompressedDestinationStream)
{
using (DeflateStream decompressionStream = new DeflateStream(uncompressedDestinationStream, CompressionMode.Decompress))
{
compressedSourceStream.CopyTo(decompressionStream);
}
}
using (FileStream sourceStream = File.OpenRead(#"C:\MyDir\MyFile.txt))
using (FileStream destinationStream = File.OpenWrite(#"C:\MyDir\MyCompressedFile.txt.cp"))
{
CompressData(sourceStream, destinationStream)
}
See the AesCryptoServiceProvider Class for information on how to encrypt data. It shouldn't be hard to modify the example to encrypt a stream instead of a string.
It's also possible to issue certificates to users and perform encryption/decryption based on that but it's more complicated. For that you'll need to look at the System.Security.Cryptography.X509Certificates Namespace.

Are there any Asp.net security tools and/or frameworks?

As per the increasing security threats, my site needs extreme care in terms of security in all aspects. I know asp.net has built in some security measures (Anti-forgery token, cross-site scripting, authentication, roles), but that is just not enough.
I need a tool to test all possible security threats (Brute-force attacks, .... IP location, browser info ... )
and a framework (open source is better) that handles all these concerns and let you build upon.
EDIT
So to narrow a bit, my primary concern is protecting the "login" page from all possible threats.
Help is highly appreciated !
P.S. If someone can not answer, please skip the question and spare the comments and negative votes. Thanks.
In terms of security it sounds like your building a pretty serious system.
When I build apps I first analyze the usage if I know the end client and they operate behind a firewall I first restrict access to the site via ip address.
Always use SSL certificates for sensitive parts of your site.
If the site is public facing use microsoft forms authentication, but split the security elements out into a separate db so no accidental amends can happen on the schema that may affect security.
Make sure that any client side validation is also repeated on the server side, client side validation is their to save round trips but someone can spoof your site.
Make sure you set a limit on the number of times a password can be tried before it locks out.
Enforce a strong password policy thru the .net membership provider.
Make sure you encrypt any important variables passed to javascript.
Don't do any of this stuff: -
//sql injection
string sql = "select * from Test where userid = '" + textbox1.text "'"
The best starting point to testing you whole server for security vulnerabilities is below: -
http://www.microsoft.com/en-us/download/confirmation.aspx?id=573
Regards
Steve
I think that a general defence approche is what you must think of. With that I mean that you must "seal your server" and not only the web pages. In the server side you need first to change the default ports, use a firewall to block port scanning and to monitor critical ports to not get out/in.
Now from the web/page side I know at least one tool from google that can help you with some attacts.
http://google-gruyere.appspot.com/
a second article about sql injection
http://www.symantec.com/connect/articles/detection-sql-injection-and-cross-site-scripting-attacks
From programs I know the iMperva that is more close to what you search for
http://www.imperva.com/products/wsc_threatradar.html
I am sure that there are more...
Also take some time and read the
Can some hacker steal the cookie from a user and login with that name on a web site?
How serious is this new ASP.NET security vulnerability and how can I workaround it?
Use the built in ASP.net membership system. It was designed by security professionals and is thoroughly tested and robust. If you use it properly, you have very little to worry about. It has a lot of built in features such as logging failed login attempts which would probably benefit you.

How to keep multiple connectionString passwords safe, separate, and easy to deploy?

I know there are plenty of questions here already about this topic (I've read through as many as I could find), but I haven't yet been able to figure out how best to satisfy my particular criteria. Here are the goals:
The ASP.NET application will run on a few different web servers, including localhost workstations for development. This means encrypting web.config using a machine key is out. Each "type" or environment of web server (dev, test, prod) has its own corresponding database (dev, test, prod). We want to separate these connection strings so that a developer working on the "dev" code is not able to see any "prod" connection string passwords, nor allow these production passwords to ever get deployed to the wrong server or committed to SVN.
The application will should be able to decide which connection string to attempt to use based on the server name (using a switch statement). For example, "localhost" and "dev.example.com" will should know to use the DevDatabaseConnectionString, "test.example.com" will use the TestDatabaseConnectionString, and "www.example.com" will use the ProdDatabaseConnectionString, for example. The reason for this is to limit the chance for any deployment accidents, where the wrong type of web server connects to the wrong database.
Ideally, the exact same executables and web.config should be able to run on any of these environments, without needing to tailor or configure each environment separately every time that we deploy (something that seems like it would be easy to forget/mess up one day during a deployment, which is why we moved away from having just one connectionstring that has to be changed on each target). Deployment is currently accomplished via FTP. Update: Using "build events " and revising our deployment procedures is probably not a bad idea.
We will not have command-line access to the production web server. This means using aspnet_regiis.exe to encrypt the web.config is out. Update: We can do this programmatically so this point is moot.
We would prefer to not have to recompile the application whenever a password changes, so using web.config (or db.config or whatever) seems to make the most sense.
A developer should not be able to get to the production database password. If a developer checks the source code out onto their localhost laptop (which would determine that it should be using the DevDatabaseConnectionString, remember?) and the laptop gets lost or stolen, it should not be possible to get at the other connection strings. Thus, having a single RSA private key to un-encrypt all three passwords cannot be considered. (Contrary to #3 above, it does seem like we'd need to have three separate key files if we went this route; these could be installed once per machine, and should the wrong key file get deployed to the wrong server, the worst that should happen is that the app can't decrypt anything---and not allow the wrong host to access the wrong database!)
UPDATE/ADDENDUM: The app has several separate web-facing components to it: a classic ASMX Web Services project, an ASPX Web Forms app, and a newer MVC app. In order to not go mad having the same connection string configured in each of these separate projects for each separate environment, it would be nice to have this only appear in one place. (Probably in our DAL class library or in a single linked config file.)
I know this is probably a subjective question (asking for a "best" way to do something), but given the criteria I've mentioned, I'm hoping that a single best answer will indeed arise.
Thank you!
Integrated authentication/windows authentication is a good option. No passwords, at least none that need be stored in the web.config. In fact, it's the option I prefer unless admins have explicity taken it away from me.
Personally, for anything that varies by machine (which isn't just connection string) I put in a external reference from the web.config using this technique: http://www.devx.com/vb2themax/Tip/18880
When I throw code over the fence to the production server admin, he gets a new web.config, but doesn't get the external file-- he uses the one he had earlier.
you can have multiple web servers with the same encrypted key. you would do this in machine config just ensure each key is the same.
..
one common practice, is to store first connection string encrypted somewhere on the machine such as registry. after the server connects using that string, it will than retrieve all other connection strings which would be managed in the database (also encrypted). that way connection strings can be dynamically generated based on authorization requirements (requestor, application being used, etc) for example the same tables can be accessed with different rights depending on context and users/groups
i believe this scenario addresses all (or most?) of your points..
(First, Wow, I think 2 or 3 "quick paragraphs" turned out a little longer than I'd thought! Here I go...)
I've come to the conclusion (perhaps you'll disagree with me on this) that the ability to "protect" the web.config whilst on the server (or by using aspnet_iisreg) has only limited benefit, and is perhaps maybe not such a good thing as it may possibly give a false sense of security. My theory is that if someone is able to obtain access to the filesystem in order to read this web.config in the first place, then they also probably have access to create their own simple ASPX file which can "unprotect" it and reveal its secrets to them. But if unauthorized people are trouncing around in your filesystem—well… then you have bigger problems at hand, so my whole concern is now moot! 1
I also realize that there isn’t a foolproof way to securely hide passwords within a DLL either, as they can eventually be disassembled and discovered, perhaps by using something like ILDASM. 2 An additional measure of security obscurity can be obtained by obfuscating and encrypting your binaries, such as by using Dotfuscator, but this isn’t to be considered “secure.” And again, if someone has read access (and likely write access too) to your binaries and filesystem, you’ve again got bigger problems at hand methinks.
To address the concerns I mentioned about not wanting the passwords to live on developer laptops or in SVN: solving this through a separate “.config” file that does not live in SVN is (now!) the blindingly obvious choice. Web.config can live happily in source control, while just the secret parts do not. However---and this is why I’m following up on my own question with such a long response---there are still a few extra steps I’ve taken to try and make this if not any more secure, then at least a little bit more obscure.
Connection strings we want to try to keep secret (those other than the development passwords) won’t ever live as plain text in any files. These are now encrypted first with a secret (symmetric) key---using, of course, the new ridiculous Encryptinator(TM)! utility built just for this purpose---before they get placed in a copy of a “db.config” file. The db.config is then just uploaded only to its respective server. The secret key is compiled directly into the DAL’s dll, which itself would then (ideally!) be further obfuscated and encrypted with something like Dotfuscator. This will hopefully keep out any casual curiosity at the least.
I’m not going to worry much at all about the symmetric "DbKey" living in the DLLs or SVN or on developer laptops. It’s the passwords themselves I’ll keep out. We do still need to have a “db.config” file in the project in order to develop and debug, but it has all fake passwords in it except for development ones. Actual servers have actual copies with just their own proper secrets. The db.config file is typically reverted (using SVN) to a safe state and never stored with real secrets in our subversion repository.
With all this said, I know it’s not a perfect solution (does one exist?), and one that does still require a post-it note with some deployment reminders on it, but it does seem like enough of an extra layer of hassle that might very well keep out all but the most clever and determined attackers. I’ve had to resign myself to "good-enough" security which isn’t perfect, but does let me get back to work after feeling alright about having given it the ol’ "College Try!"
1. Per my comment on June 15 here http://www.dotnetcurry.com/ShowArticle.aspx?ID=185 - let me know if I'm off-base! -and some more good commentary here Encrypting connection strings so other devs can't decrypt, but app still has access here Is encrypting web.config pointless? and here Encrypting web.config using Protected Configuration pointless?
2. Good discussion and food for thought on a different subject but very-related concepts here: Securely store a password in program code? - what really hit home is the Pidgin FAQ linked from the selected answer: If someone has your program, they can get to its secrets.

ASP.Net Session State

I was wondering whether it would be possible to change the sqlConnectionString used for SessionState in ASP.net based upon the domain an application is running on?
A scenario; We have 20 sites running from one application all talking to different databases depending which domain (site) they are browsing from.
When browsing www.domain1.com the application talks to the database 'db1'. The site www.domain2.com on the other hand talks to the database 'db2' etc, thus selecting the relevant content and also spreading the load to each database rather than using one master database to handle all connections for the sites.
An issue that has arisen though - for this setup we use SqlServer mode for the SessionState so all users to all sites sessions are stored in 1 aspstate database, now as the sites get busier / number of sites increase this database comes under increasing strain to handle all the session requests for all the sites and we are starting to get some timeout errors where the connections to this database are bottlenecking.
We can seperate out the sites to from their own application and set up different applications with the same code but within each application set a different Session database in each Web.Config and thus lightening the load. This task would be quite time consuming though and would result in more management in the long term. SO.. I would love to know if it's possible to modify within the code the sqlConnectionString used for SessionState, based upon a domain, before the session object is created? Can we inherit from System.Web.HttpApplication and use the Application_AcquireRequestState event to create the required setup of the HttpSessionState object?
Hopefully this makes sense and that someone can provide some pointers and prove to me that this isn't a pipe dream!
Cheers,
Steve
I think you are missing a big point--putting things in separate databases on the same server isn't going to help things at all if the bottleneck is sql server--it is either SQL running out of headroom or the network running out of bandwidth. I'd try and figure out which one it was before doing anything.
Your issue isn't so much that the connections to the database are bottlenecking, its that you are overwhelming the network connection to the database with data from all of the sessions.
By default, the Sql Server state provider simply serializes your data and ships it to the database. This is VERY inefficient and takes a LONG time to transfer on a fast network.
We solved this problem by going to a custom provider, like DOTSS that compresses session content before shipping it to the database. The compression rates we see are 80%-90% and the compression time is less than 10ms.
You can implement a custom session state provider. See MSDN for details. I've never done it, but with a little luck you can wrap the SqlServer session state module and redirect it based on the domain
First of all, I don't see there is advantage of "I would love to know if it's possible to modify within the code the sqlConnectionString used for SessionState, based upon a domain, before the session object is created" compared to set this in web.config.
Secondly, I think you need change that connection string setting in App_Start, so all the request will use that changed settings.Application_AcquireRequestState probably too late for this.
Why not split up the sites into sperate web applications and use hostheader to differentiate between the web sites. That way you could easily configure which session database you want your web application to use since each web application would have a seperate web.config file.
You could partition your session across different databases by implementing IPartitionResolver, and using a different partition for each domain.
Here's an example showing how to implement a custom partition resolver. (The example partitions by session ID, but it would be trivial to change it to partition by domain instead.)
We have several dozen development sites whose database connections are handled via the project's main Web.Config.
There is a separate configuration section corresponding to each URL on our intranet (e.g. http://development11, http://development12). We have SQL instances with a similar naming convention (DEVDB1\SQL1, DEVDB1\SQL2).
Based on the URL configured on the intranet IIS server, the app grabs the appropriate config. For testing we can easily modify the user, the database server or individual databases utilized for a particular site.

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.

Resources