I am trying to secure a MSSQL database for our .Net website.
I wanted to separate the database into different schemas so that we had an schema like 'Account' which had personal information and a schemas like 'Public' that had generic public content data.
Each of these schemas would be accessed using different SQL user accounts and they would each need their own DBML since they would need separate connection strings(we are using LINQtoSQL).
My colleague is claiming that since we just have both of these accounts in our web.config anyways this design is no more secure than just using one SQL server account that has access to the whole database. There is no need to separate the schemas since we aren't using Windows based authentication.
So my question is who is correct? Would separating the database into schemas be any more secure? Or is it a waste of time since both SQL accounts would be located in the web.config (even if encrypted)?
Your colleague is wrong on one level and right at another.
Breaking the database into schemas as you propose will help with attackers who are able to find things like SQL injection flaws. If you are diligent in setting your permissions, that is...
However, splitting the schema like this offers no additional benefit if someone manages to get into the actual file system and can red the web.config.
You need to think about all the possible layers.
If you haven't already, check out this great resource:
http://msdn.microsoft.com/en-us/library/ms998372.aspx
Also, try googling storing your connection strings in the registry. There are some good references for that, which will help protect you if someone gets into the file system and can read your web.config.
Finally, don't forget to encrypt your web.config...
Separating the accounts will reduce the risk in case the attack vector is SQL Injection. The attacker will only be able to do whatever is allowed by the priviledges of the session is using to carry on the injection. Presumably only an authenticated attacker can use the Account session as the injection vector so he will be detered because it can be discovered from logs who did it. Wether this separation is an effective mittigation of a threat, it depends a lot on information you left out, most importantly how do you separate access to the two areas in your code.
Having both connection strings in the web.config means that if the ASP pool itself is compromised then an attacker can use both string.
I presume the strings are encrypted none the less, see Encrypting Configuration Information Using Protected Configuration. This way at least the connection info is not lost if the web.config is leaked.
Well if you encrypt the section the accounts are in, I don't see what would be the problem. The only problem could be on connection pooling, it will fragment the pool in 2 that's it.
Related
So I am using connection strings in my web.config using SQL authentication.
Of course people say this could be a vulnerability as you are storing password in plaintext.
However, from what I know, IIS never serves web.config, and web.config should only have read access to administrators and IIS anyway. So if the hacker has gained access to the webserver, then it won't matter what encryption I use because the private key will be on the webserver.
Wouldn't encrypting connection string be classified as security through obfuscation?
Is it worth encrypting web.config connection string and storing the private key on the webserver?
Further, of course if I don't use SSL, I am transmitting connection string over HTTP in plaintext. If I use SSL then this problem should be mitigated as well.
I wouldn't say that storing a plaintext password in Web.config is a security vulnerability, in and of itself. But encrypting the password is a useful defense-in-depth measure, not just security through obscurity:
What if IIS is misconfigured to serve Web.config?
What if a security vulnerability is discovered in ASP.NET (like the padding oracle vulnerability) that allows anyone to download Web.config?
There are varying degrees of access to the Web server, from full administrative privileges to server-side code injection. If an attacker can only manage to do the latter, he might be able to read Web.config but might not be able to access the machine keys, especially if your application is running under partial trust.
In the end, it's up to you to decide if the risk of storing plaintext passwords in Web.config is acceptable. Of course, if Windows authentication is an option, then you may want to consider using that instead of SQL authentication.
UPDATE: When talking about security, it's a good idea to identify the assets and the threats. In this case, the asset is sensitive data in the database (if the data is unimportant, then why bother protecting it with a password?), and the threat is the possibility of an attacker somehow gaining access to Web.config and thus the database as well. A possible mitigation is to encrypt the database password in Web.config.
How much of a risk is it? Do we really have to plan for such an astronomically rare occurrence?
This mitigation has already proved its worth once: when the ASP.NET padding oracle vulnerability was discovered. Anyone who stored a plaintext password in Web.config was at risk; anyone who encrypted the password wasn't. How certain are you that another similar vulnerability in ASP.NET won't be discovered in the next few years?
Should we also encrypt source code and decrypt on run-time? Seems excessive to me.
So what if an attacker does get access to your source code? What's the asset you're protecting, and what's the threat you're concerned about? I think that in many cases, source code is much less valuable than data. (I'm thinking here about off-the-shelf commercial and open-source software which anyone can obtain.) And if your source code is valuable, maybe obfuscation is something to think about.
I feel if they already have even limited access to your box, then your host has failed or you've installed vulnerable services already.
What about security vulnerabilities in ASP.NET or your code? They do pop up from time to time.
My concern is standard practices. Is it a standard?
Microsoft has recommended encrypting connection strings.
What you should do is evaluate the risk that storing a plaintext password poses:
How likely is it that an attacker will be able to discover and exploit a security vulnerability that exposes Web.config? Based on past history, I'd say the likelihood is low (but not "astronomically" low).
How valuable or sensitive is your data? If all you're storing is pictures of your cat, then maybe it doesn't matter much whether an attacker gets your database password. But if you're storing personally identifiable information, then from a legal standpoint, I'd say you should take all possible measures to secure your application, including encrypting your connection strings.
Consider that, if Production passwords are present in the web.config file, then any developer with access to that file has access to the Production database. This is especially a problem when the username in the connection string has read/write access to the database. It then becomes possible for developers to "fix" things with no record that the "fix" ever occurred.
I think this is not from "outside" protection, but for "inside".
Sometimes, SQL administrator/user and OS administrator are different people. But OS administrator has access to all files, so he could easily read the SQL credentials in web.config file. But those credentials can be encrypted in a way, that even OS administrator has no way to decrypt.
And it is hardly "security through obscurity", because encrypted connection string canno't be decrypted without correct user certificate and usualy only IIS "user" has that one.
I used to read some articles on IHackStuff online blog. This guy explained some ways to get to really interesting info using Google search engine typing things on the search box like:
filetype:config web.config -CVS
This came out with multiple results related to cached web.config files on production servers, all the info of those files were available to public eye. Considering this possibility I would still recomend to encrypt web.config database access info whenever such info is valuable enough.
You're right to say that web.config won't be served by ASP.NET to a browser. But developers are cautious, so when they release a new version, sometimes they copy a known good web.config to something like web.config.old or web.config.bak. And because developers are lazy, after the release they forget to delete the old web.config, or keep it hanging round for a few days in case they need to rollback the release.
Now, .old and .bak files will be served to a browser, which means it's easy to write a script or a tool that scans for these files and downloads them to an attacker who can then go through them at their leisure to look for connection strings with usernames and passwords, and suddenly credit card numbers from your database are circulating the Internet...
If you don't want to get into command-lines and RSA keys (and frankly, why would you?), take a look at this tool for encrypting your web.config.
We currently use a connection string to authenticate our database credentials. Due to grown and compliance the developers are no longer allowed to "see" the database credentials that our websites use. Are solution to this problem is use Integrated Authentication. We planned on setting up a user per App Pool and then allowing that use access to the Database.
My question is: Are there any security concerns around this approach? As far has removing the DB credentials from the connection string, is there a better(easier or simpler) approach we should/could be taking?
If you need to secure and audit access to the production database then Windows Authentication is a better choice than Sql Authentication for a number of reasons:
You can control exactly who can access the database via NT groups and permissions, which means you know who specifically has access to the database. The pool of access with sql authentication is only limited by who knows the password. Given n people who know the password, tracking who did what at a certain point of time is trickier (but not impossible) given that.
Only your sysadmins need know the password for the nt identity with access to the database; in fact, much of the config can be done only knowing the username
Logins and access can be tracked at the domain level far more easily than with SQL Server logins.
What it wont give you is:
Ability to ensure that the developers can't see production data - whoever writes the app can easily include some diagnostic routines to select out data
Ensure that production data only stays in production - anyone making a backup of the production database (say to restore it to a UAT environment for testing) could easily expose production data.
Problems with this approach have already been discussed in other posts; in particular, with ASP.Net applications, you have to consider whether or not you are going to use Impersonation/Delegation (webserver can act as the NT user accessing it) or a Trusted User model (where you configure a fixed identity to access certain resources).
This is further complicated by the IIS version you are using.
If your connection string is stored in a web.config file, you could create a separate production version of that file that the deverlopers can't see. That's easier to test and setup than integrated authentication using app pools.
One word of warning though: If you restrict developers that much, it will slow down their velocity of change. Since the rest of the world does keep moving, this usually ends with the application becoming a dead legacy package. That's dangerous if you plan to grow, improve or extend.
Use of application pool's identity can be quite complicated to set up, consider trust and delegation problem.
A better option can be securing connection strings using encryption.
I have come across this excellent blog explaining how to encrypt/decrypt the database connection string with a PKCS12ProtectedConfigurationProvider inside Azure Cloud.
http://social.technet.microsoft.com/wiki/contents/articles/sql-azure-connection-security.aspx#create_aspnet
Is this something that should be done, or is it rather security overkill?
If Web.config cannot be accessed from internet due IIS restrictions, nobody would be able to read the DB connection string (incl. password etc) inside the Web.config anyway, so why bother to encrypt it in first place?
Many Thanks,
I think it is the same argument as when considering encrypting connection strings outside Windows Azure, which is - who has access to the box.
I have been talking to organisations who had several people with access to the box, which would allow them to see the web.config and extract the credentials for the databases, in places where you don't want system administrators/developers/etc accessing your database, this makes sense.
If you are the only one with access to the instance or if that is not a concern of yours, you don't have to worry about it
I am about to deploy an ASP .NET application (developed with LINQ-to-SQL).
I have taken following precautions:
Database access via user with limited access, however, since application is to access the sensitive data, I can't deprive this limited access user from it
Database server is not exposed to external network - is hiding behind DMZ and all external ports are blocked
I have done thorough security testing of the web-application; SQL Injections, rights management, illegal data access (via post/get data tempering)
Application is operating on SSL
Questions:
1 - I am using ASP .NET authorization API; any recommendation for avoiding session hijacking (in case someone some-how gets to know the session key). Is there are way to change the authentication cookie less prone to threats? Say like, changing it after every request? (I know I am get very conscious about this particular item)
2 - Data in the database is not encrypted. To make things ultra-secure, I am thinking about implementing transparent data encryption. Can someone share his/her experience or a link about implementing data level encryption with SQL Server 2008 along with pros-and-cons?
3 - Recommendation for storing connection string in web.config. Is using integrated security better then using encrypted database connection string?
It's seems to me that it's enough of standard asp.net api for this task. There is a very good article from MS P&P team about securing your forms authentication, it should help you.
I don't have such experience but here is a link with article.
I don't know :(
Also I recommend to check AntiXSS tool, it can show you some potential xss holes. And one last note, never trust to user input.
Integrated security is your strongest option.
I'm not an ASP.Net expert, but in my PHP projects I encrypt the cookie and affinitize it to a specific client IP. This way sessions cannot migrate to a different client. Ultimately, if you want to be absolutely sure, cannot rely on cookies for authentication, but instead use HTTP Digest, since browsers will transparently re-authenticate every request within the realm. Unfortunately this option does not work with the built-in ASP.Net membership providers as the HTTP Digest option they offer is half-brained to say the least (only authenticate against AD).
What specific threat are you trying to mitigate by encrypting data? TDE is designed to mitigate the threat of accidental media loss (ie. someone find an old disk of your with all the data on it, or you loose a laptop with the database on it). This is also the threat mitigate by most other database encryption schemes, like column encryption or file level encryption (bit locker). Other threats, like accidental compromise of access to the database (ie. someone finds a SQL injection vector to your db) cannot be mitigated by TDE, since the database will offer the decrypted data to any authenticated user. To mitigate such threats it means the data is encrypted with keys presented by the user (ie. only the user session can decryt the data becaus eonyl that session know the key password), but that knocks out the 'Transparent' aspect of all these encryption schemes. Having the user encrypt data with it's own key password protects data from other users (other sessions), so it is stronger, but its very difficult to 'get right', and the user is always at risk at locking himself out of its own data by forgetting/loosing the key password.
Use integrated security and store connection string encrypted. Since encrypting the strings in Web.Config is trivial and well supported in ASP deployment and operation, just do it. Encrypting the string protects agains accidental compromise of the IIS/ASP host from a non-admin account. An admin account, or the account under which the ASP runs will always be able to read the encrypted connection string. Since the most likely attack vector will always be ASP compromise (ie. SQL injection and friends) the attacker will most likely be able to read the connection string even when encrypted, so there isn't that much benefit from it, but every little bit counts.
Working inside the context of an ASP.NET application I am creating a page that will be able to execute database scripts against one of many databases in our environment. To do this we need to prompt the user for a username/password combination, this value can be used for all servers without issue.
The question is where is the most secure location to store this information? We need to store it temporarily as when they are on this specific page they could be executing hundreds of scripts, over multiple postbacks. From what I can tell I have 3 options and I'm not sure what is the best. Below is my take on the options, what is the recommendation of everyone here? What is the most secure, while still being friendly for the user?
Store Information In Viewstate
One of the first ideas we discussed was storing the information after being supplied by the user in the ViewState for the page. This is helpful as the information will only exist for the lifetime of the page, however, we are unsure of the security implications.
Store information in Session
The next idea we had was to store it in session, however, the downside to this is that the information can be made available to other pages inside the application, and the information always lingers in memory on the server.
Store Information in Application
The last idea that we had was to store it in the Application cache, with a user specific key and a sliding 5 minute expiration. This would still be available to other pages, however, it would ensure that the information is cached for a shorter period.
Why?
The final question that is important is "Why are you doing this?". Why don't we just use their Lan id's? Well we cannot use lan id's due to the lack of network support for delegation.
S0 what is the recommended solution? Why? How secure is it, and can we be?
Update
Great information has been discussed. TO clarify, we are running in an intranet environment, we CANNOT use Impersonation or Delegation due to limitations in the network.
In my opinion the natural place for this is the Session.
I'm not sure why you seem to be fearing "other pages inside the application" (you control the appliciation, don't you?), but if you really are, you could use some sort of encryption before you store it.
But if you are going to do that, the data could live in the ViewState as well.
I don't like any of these ideas, but totally hate the viewstate idea.
I don't know how many databases you are attaching to, but if there is a limited number, I kind of wonder if handling your authentication and authorization in a standard secure manner, then connect to those databases via integrated security using identity impersonation with an account that has minimal permissions.
The ViewState approach is good but has the problem that you are giving out the username and password to the client. Even if you encrypt it, if some attacker has the encryption key, the situation will not be very good.
Regarding the Session and Application approaches, I don't think Application approach makes sense. Data is user specific, so Session should be the way to go. It'll go away as soon as user's session is closed. By the way, if you chose to store it at the server, use SecureString class.
As John MacIntyre wrote you should use integrated security and impersonation for this.
If for some reason you can not use it and you are going to provide your own login page, use by all means SSL to encrypt the traffic between the browser and your server. Using the ViewState approach is also completely insecure if you do not use SSL, there are tools to view the contents very easily. From the methods that you enumerate the best one would be to use the Session state. You can offload saving the session state from your web server memory and save that data in a database that you can secure the way you want. If you don't like the way these work you could even write your own session state provider and apply the security you need there.
Storing in Viewstate increases your exposure because the password will be flying around the internet again and again. It's up to you if encryption is good enough to address this risk.
Using Application or Session both keeps the password in the server. As mentioned above SecureString will keep people from simply reading passwords out of memory. Session will scale to more users, and probably more importantly to multiple servers much easier than Application. Unless you are sure you will never use more than 1 web server I would not use Application, as it will be up to you to synchronize all the servers.
Never store passwords!
Rather store the hash of a password. See: http://en.wikipedia.org/wiki/Crypt_(Unix)#Library_Function.
I'm aware this does not answer the question, but the more programmers who ignore this advice, the easier it will be for criminals to steal data. Don't let your organization become a news story.
The username/password really shouldn't be stored anywhere.
You store a live database connection, preferably from a pool in your Session object. You only need the username/password as long as it takes to log into the database.
While another page can use the live connection, it doesn't give anyone else permanent access to the database as you would by storing a username/password.