Implementing application security - App Level & DB level (ASP .NET & SQL Server 08) - asp.net

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.

Related

Granting Secure Access from one website to another

I'm really just looking to see how much folly is in the below suggestion from a security perspective.
I have two websites. One is an administration portal and the other is a members portal.
Within the administration portal administrators can retrieve a listing of members and I need to offer the ability for administrators to login to the member portal without having to enter the members login credentials.
Both are separate websites within IIS and for this discussion lets say they are on different servers.
Both websites access the same SQL Server database.
I was thinking that I could on the administrator clicking a "Login as Member" link create a random code string and save this to the database along with the member number.
I could then pass the code and member number to the member portal as query string parameters.
The member portal then read in these values and checks them in the database to verify that the code string exists and if so that it matches the member number also being passed. I could then login the member and set a flag in the database to set the code as being used and therefore invalid for future requests.
I'm thinking to bypass this a hacker would need to successfully guess the random code and pass that to the page alongside the corresponding member number for that code and for that combination to be marked as unused in the database.
This would seem to be unlikely given that only seconds will pass between the code being generated and the code being used.
If necessary I could always check the IP address of the request as users of the administration portal all share the same fixed IP address.
So do you think the above would stand up to scrutiny on a security review or will I need to go down the SSO route?
Your approach is very sound. I can confirm because I have implemented just such a solution for just such a reason. We analyzed the options and exposure. And after implementation, our application passed a PCI Complaince Audit.
Reasons:
SSL is Esential! protects against sniffers. Essential. Without Encryption, sniffers could detect your GUID and may have a window to use it)
As Tony pointed out, the GUID is effectively unguessable.
Guid Tokens expiring should expire within 24 hours.
Suggestions:
Checking against IP is good. But don't be fooled into a feeling of security from it. Anyone can fake IP's in headers. To be Secure against XSS and CSRF by using AntiForgery tokens.
The AntiForgery token is a cookie that populates your HTTPHeaders with __RequestVerificationToken which is almost as hard to guess as your GUID.
Consider using an established Authentication framework like .NET Identity 2 and multitenancy.
An established framework takes the burden of encrypting your passwords. MS Frameworks like Simple Membership and Identity integrate into modern ASP.NET frameworks and give you very strong base of functionality to lean on.
If you're using an old framework like classic ASP or .NET 2.0, the classic Membership Provider is more appropriate.
If you are creating new MVC 5 applications utilizing Entity Framework, I strongly suggest using Identity 2.1.
Consider Mult-Tenancy. While there is nothing wrong with your solution, if Admins and users shared Membership Provider, your solution would be cleaner. An admin could log into the main site and "get" the token from the DB. Then no exposure.
Assuming the use of HTTPS and adequate physical and IT security processes and procedures in place for the administrators, this method should be adequate. It is more secure than most financial website password resets, which typically only require a compromised email account and some personal information to reset the password. If you check the IP address range of the originating client request as well, a hacker would have had to already have access to your systems or network. Also, if you make the code a GUID, it would be (pragmatically speaking) impossible for someone to guess.
You could add a layer of checking for hack attempts by storing a record in the database each time this event occurs (or at least each it fails due to a bad key), and each time it occurs run a check to see if it is happening too often (like 100 times in the past hour, or something--the right number depends on how often you expect it to happen). If it's happening too often, then have it send an alert to IT personnel and revert so that the user has to enter their credentials manually.
Disclaimer: I am not a security expert by any means, so I'll gladly defer to anyone claiming such status. I'm weighing in here due to a lack of answers.

Is there a need to secure connection string in web.config?

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.

Security Issues ASP.NET integrated Authentication

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.

Sending sensitive data from server to server via client

I have situation where I need to authenticate a client across multiple web services. Basically each service needs to identify the client and know a few other small pieces of information about the client.
The way I have it working now is that the needed identifying information is stored in a session table in a database by the authenticating web server. The web server hands the client an string, which IDs the database entry and gets passed to the other web services. The web services then use this string to pull the needed information about the client from the database entry.
It has occurred to me that it might be possible to give the client an encrypted blob that contains the user ID and other needed information, which is rather small, and avoid using the database for this completely. The client would just pass around the blob (like the string in the previous paragraph) without needing to know what it contains, and only the web services would know how to decrypt it.
This should eliminate the need for the database to store the session information and would make the whole process a good bit simpler. With the database you have to worry about cleaning up old sessions and timeouts and so on.
So my question: is passing around sensitive data from service to service via client considered safe and acceptable? Is it possible to do this in a way that would eliminate worry about the client tampering with the data? What encryption algorithms would be good to use? I'm using .Net - specific classes would be quite helpful.
That seems like a reasonable approach to simplify your app, but remember that if you use the client to store identifying data, you'll always be vulnerable to session hijacking attacks.
In other words, no matter how well you encrypt the blob, someone else can take the user's browser data and copy it, and impersonate the user. The ASP.Net session cookie is always vulnerable to this too, btw.
The only way to be completely secure is to use SSL.

How secure is basic forms authentication in asp.net?

Imagine that you have a simple site with only 2 pages: login.aspx and secret.aspx. Your site is secured using nothing but ASP.net forms authentication and an ASP.net Login server control on login.aspx. The details are as follows:
The site is configured to use the SqlMembershipProvider
The site denies all anonymous users
Cookies are disabled
The are obviously many things to consider regarding security but I am more interested in the zero code out of box experience that comes with the .net framework.
If, for the sake of this question, the only attack points are the username/password textboxes in login.aspx, can a hacker inject code that will allow them to gain access to our secret.aspx page?
How secure is the zero code out-of-box experience that Microsoft provides?
You still have some variables that aren't accounted for:
Security into the data store used by your membership provider (in this case, the Sql Server database).
security of other sites hosted in the same IIS
general network security of the machines involved in hosting the site, or on the same network where the site is hosted
physical security of the machines hosting the site
Are you using appropriate measures to encrypt authentication traffic? (HTTPS/SSL)
Not all of those issues are MS specific, but they're worth mentioning because any of them could easily outweigh the issue you're asking about, if not taken care of. But, for the purpose of your question I'll assume there aren't any problems with them.
In that case, I'm pretty sure the forms authentication does what it's supposed to do. I don't think there's any currently active exploit out there.
As far as I know password will be sent as plain text (but encoded). So the most important thing to do is to use HTTPS protocol on login screens.
The other setting seems to be secure for me.
With HTTP Basic Authentication, which is what the .NET basic forms authentication is using, in order to view the secret.aspx page, the browser must send a Base64 encoded concatenation of the username and password.
Unless you utilize SSL, anyone who has access to scan the network between the server and the browser can read this information. They can decode the username and password. They can replay the username and password in the future to gain access to the secret.aspx page.
That said, unless you use SSL, someone can also scan the whole session of someone else using secret.aspx, so in effect, they would have access to the content of the page as well.
Well, try and look behind the scenes:
Password Protection
Applications that store user names,
passwords, and other authentication
information in a database should never
store passwords in plaintext, lest the
database be stolen or compromised. To
that end, SqlMembershipProvider
supports three storage formats
("encodings") for passwords and
password answers. The provider's
PasswordFormat property, which is
initialized from the passwordFormat
configuration attribute, determines
which format is used:
MembershipPasswordFormat.Clear, which stores passwords and password
answers in plaintext.
MembershipPasswordFormat.Hashed (the default), which stores salted
hashes generated from passwords and
password answers. The salt is a random
128-bit value generated by the .NET
Framework's RNGCryptoServiceProvider
class. Each password/password answer
pair is salted with this unique value,
and the salt is stored in the
aspnet_Membership table's PasswordSalt
field. The result of hashing the
password and the salt is stored in the
Password field. Similarly, the result
of hashing the password answer and the
salt is stored in the PasswordAnswer
field.
MembershipPasswordFormat.Encrypted,
which stores encrypted passwords and
password answers.
SqlMembershipProvider encrypts
passwords and password answers using
the symmetric encryption/decryption
key specified in the
configuration section's decryptionKey
attribute, and the encryption
algorithm specified in the
configuration section's
decryption attribute.
SqlMembershipProvider throws an
exception if it is asked to encrypt
passwords and password answers, and if
decryptionKey is set to Autogenerate.
This prevents a membership database
containing encrypted passwords and
password answers from becoming invalid
if moved to another server or another
application.
So the strength of your security (out of the box) will depend on which password protection format strategy you are using:
If you use clear text, it is obviously easier to hack into your system.
Using Encrypted on the other hand, security will depend on physical access to your machine (or at least, machine.config).
Using Hashed passwords (the default) will guarantee security depending on: a) known reversals of the hashing strategy of RNGCryptoServiceProvider class and b) access to the database to compromise the randomly generated salt.
I do not know if it is possible to use some sort of rainbow table hack into the default Hash-base system.
For more details, check out this link:
http://msdn.microsoft.com/en-us/library/aa478949.aspx
If configured correctly through the membership provider, you will have a adequate level of security. Outside of that, access to that page might be accessible through cannonical attacks, but that has to do with your general security. I gave a presentation on using the Security Enterprise Application Blocks. You might want to read up on those and look into that when implementing security on your site, and just be aware of common security threats. No site will ever be 100% unhackable, given that you are on an open shared network and total security would be an unplugged server locked in a safe guarded 24/7 by the military (around DoD "A" level security, based of Orange book). But the out of the box functionality of the Membership Providers (when configured correctly) will offer a good amount of security.
Edit: Yeah, I agree with the other comment that was made, HTTPS on at least the log in screens is a given, if you want to protect the username/passwords from packet sniffers and network monitors.
Asp.Net supports cookieless sessions, as this blog post shows. Instead of a session cookie, it uses an identifier in the url to track users.
I am not sure how secure this is, but I would think it is a secure as the difficulty to brute force the identity string.
It looks like it works more or less out of the box, however when redirecting a user and wanting to maintain session state you must include the session id. The blog post shows how to do that, as well as many other articles on the web.
Here are two good articles from Microsoft on the subject:
How To: Protect Forms Authentication in ASP.NET 2.0
INFO: Help Secure Forms Authentication by Using Secure Sockets Layer (SSL)
Cookies over URL is not secure enough, there are so many different problems with it (especially referrer leakage if you've got any) and usage of HTTPS.

Resources