ASP.NET/IIS7 - Securing access to SQL Server for multiple user roles - asp.net

I'm working on an web application using ASP.NET 4.0, C#, and IIS7. The web application is a content management system that defines multiple user roles, such as editor and administrator. These users and roles are managed by the asp.net membership framework, and the associated database tables are integrated into the web app's database using aspnet_regsql. Finally, the web app is running under the ApplicationPoolIdentity. Thus, the web app runs under the virtual account "IIS AppPool\" which it does not share with any other application.
The site is designed such that user accounts are handed out by the administrator (there is no public sign-up page), although this detail may be irrelevant. In any case, the administrator should have the power to create and delete users and edit any of the content on the site. Editors, on the other hand, should be capable of editing only assigned sections of the site. Finally, anonymous visitors to the site should only be capable of viewing the content, with no option to edit.
The question is: Would it be insecure to just give read and write access in the SQL Server database to the IIS AppPool\ virtual account and give functionality to different user roles in the underlying business logic for the web application?
I wouldn't think so, but due to the necessity of the integrity of the data, I thought it might be a good idea to seek the opinion of another developer.
If (and only if) this does pose an unforeseen security risk, would it be a better idea to use impersonation, store multiple connection strings in the web.config file with SQL authentication, or track user privileges in the database itself?

The question is: Would it be insecure
to just give read and write access in
the MSSQL database to the IIS AppPool\
virtual account and give functionality
to different user roles in the
underlying business logic for the web
application?
This is how it's usually done, and for most business cases this is enough. There are insecurities in every application so you have to do the best you can to avoid buffer overflows, script injections and SQL injections, scrub your input, etc.
If (and only if) this does pose an
unforeseen security risk, would it be
a better idea to use impersonation,
store multiple connection strings in
the web.config file with SQL
authentication, or track user
privileges in the database itself?
Using impersonation is not uncommon, and very easy if you're using Windows Authentication. It's an administration headache, since users have to be added via database security in addition to the application database. Multiple connection strings is probably the least extensible and favorable of the approaches, not to mention it would hurt performance on a busy site.

Related

Best practices for connecting from ASP.NET Core to SQL Server?

I've had some recent difficulty with SQL Server not liking the default AppIdentityUser for logins, so I went ahead and created a custom DB user with write access.
But it made me wonder - is this the best approach?
I was wondering what the best SQL Server login approach would be for Asp.Net Core. I know there's a question similar to this for normal .NET, but you can't encrypt a Core web.config/appsettings.json (well, in a quick and straightforward manner).
Here are the options as I see them:
Connect via SQL Server ID that is stored in appsettings.json.
Pro: Already configured.
Cons: Password in web.config/appsettings.json; have to specifically configure SQL Server ID. Not centrally revokable.
Connect via user NT ID via ASP.NET "AppIdentityUser".
Pro: No passwords in appsettings.json.
Cons: Not centrally revocable. Seems to be restricted to the server name for user.
Connect via Active Directory user.
Pro: Easily revokable.
Cons: Active directory user password in appsettings.json. Could be bad if somebody accidentally reuses that user in another application in the company, and that user gets breached.
Are there other options that I'm missing? Which of these options are used in which situations? Which are more standard? Are there pros and cons that I'm not thinking about?
You should absolutely use a custom SQL Login to connect to the database. Under the hood, the SQL Login could be tied to a local account, service account, network account, etc. It doesn't actually matter.
The real issue you seem to be having here is in not wanting (rightly) to expose login credentials in plain text. I'm not sure why you keep referring to Web.config here, as ASP.NET Core doesn't use that. Instead, there's various configuration providers that can be optionally utilized. By default, ASP.NET Core (at least since 2.0) adds a JSON config provider that looks for appsettings.json and appsettings.{environment}.json in your project, a command-line configuration provider, a user secrets config provider, and finally an environment variable configuration provider.
The last two are the most interesting for your circumstances. In development, you should use user secrets. In production, you should use environment variables. However, neither stores secrets in an encrypted way. The benefit to either approach is that the secrets are not in your project, and therefore also not in your source control. Even though neither is encrypted, it's not as big of a concern as you might think. Getting at the secrets in either would require direct access to the server/development machine. Additionally, user secrets is by default tied to a particular user account, accessible only to that user, and environment variables can be set up the same way. Therefore, someone would need to both gain access to the machine and gain access to the particular account. That's actually a pretty high bar, and if it were to occur, exposing a database password is really the least of your concerns at that point.
Nevertheless, if you want true encryption, you have the option of using Azure KeyVault. KeyVault can be used whether or not your application is actually hosted in Azure, and while it's not free, it's exceedingly cheap.
Finally, you can always create your own config providers or source third-party ones. For example, while the default JSON provider doesn't support encryption, you could potentially write one that does.

IIS with a Web Application using Windows Authentication with Impersonation

Im not using this, but is a interesting question.
If i set a Web Application on IIS to use Windows Authentication and Impersonate the Authenticated User and my ConnectionString to a SQLServer database use Integrated Security=true;, my application when try to connect to the database will use the User authenticated by the application?
If yes, this is a good thing?
( The database has LDAP/AD "Domain Users" permissions. Considering an Database that will be auditable where each user will have your actions logged.)
I believe E.K.'s answer is true only under a situation in which kerberos authentication is used. What you are describing is known as the 'double-hop'. Essentially, if the user authenticates to 'Server-A', the code that is running on 'Server-A' cannot turn around and use those credentials to access other network resources, such as a SQL Server on 'Server-B'. This is detailed quite a bit but here is a direct link: Blog Article
If you are running on a kerberos architected network, then you can mark a server as being a trusted delegation server. But for most people, this is not the case. If you'd like to learn more about how to do this, see this link.
Yes, the connections to the SQL Server will be under those users.
In general, it isn't good. But it depends on the situation. The following are main factors to consider :
Each user will require its own connection. Connections from different users can't be reused even if connection pooling is used. Creating of connection is relatively expensive operation. And each connection requires a little bit of memory
Each user needs to have its log in (or at least Windows group that the user is member of needs to have the log in). This can be additional maintenance to create log ins, etc. On the other hand, each such log in can be secured in a different way. Important to say is that securing objects for different users can be achieved also if a single account is used to connect to the SQL Server
Yes, it would use authenticated user and impersonate the "authenticated user" rights to access the database.
For more information do look on this link How To: Use Impersonation and Delegation in ASP.NET 2.0
The other approach is to use a service account a non-interactive windows domain account that has complete access to the database.
This allows connection pooling
Eliminates complex permission models to allow selected users to perform a delete on a set of data for example.
This does mean however that audit logic has to be added to the data layer of the application and to stored procedures that access the database to insure that the calling user is logged as part of the database access otherwise the service account would be the only account in the audit table.

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.

Application pool identity or Impersonation

(A question of similar vein has been asked before but both the question and the accepted answer do not provide the detail I am looking for)
With the intention of running an asmx web service under a dedicated domain account what are the usage scenarios and/or pros and cons of using an Application Pool with the identity of the domain account versus Impersonation?
We have 3 small internal web services that run under relatively low load and we would like to switch them to running under their own domain accounts (for the purpose of integrated security with SQL Server etc). I appear to have the choice of creating dedicated app pools for each application, or having a single app pool for all the applications and using impersonation in each.
I understand app pools provide worker process isolation and there are considerations for performance when using impersonation, however those aside what else would dictate the correct option?
Typically, you will choose different identity for worker process (or do ASP.NET impersonation) because there is need to access local/network resources that needs specific permissions. Obvious dis-advantage is that your application code may run under more permissions than it may need and thereby increasing the vulnerability against malicious attacks.
ASP.NET impersonation would have more overhead because user context needs be switched for each request. I will suggest to go with separate app pool approach - only disadvantage with app pool approach is that you have process for each one of them and so there will be overhead (from OS perspective) for each process. If your applications are smaller and don't have strong memory demands then this should not be an issue,
If you want your web services to connect to SQL via Windows authentication, you will almost certainly want to set up each application with the dedicated app pool option. This requires the least amount of setup and administration.
If you go the impersonation route, you'll need to account for the "two-hop" issue. When a user calls a web service that is using impersonation, the web service can access local resources, as that user. However, if the web service tries to connect to a non-local resource (e.g., a database running on a separate server), the result will be an authentication error. The reason is that NTLM prevents your credentials from making more than one "hop". To workaround this, you would need to use Kerberos delegation. Delegation isn't difficult to set up, but it does require Domain Admin privileges, which can make things difficult in some corporate environments.
In addition, using impersonation means that you need to manage database permissions for each user that may visit your web service. The combination of database roles and AD groups will go a long way in simplifying this, but it's an extra administrative step that you may not wish to conduct. It's also a possible security risk, as certain users may end up with privileges that are greater than your web services are anticipating.
Impersonation is useful when you need a common end user experience with other Windows services that are based on Windows security.
For example, Microsoft SharePoint servers use impersonation because you can access SharePoint document libraries with web browsers and with the standard Windows shares UI (connect / disconnect to a network share, based on the SMB protocol). To ensure security is consistent between the two, in this case, you need impersonation.
Other than this kind of scenario, impersonation is most of the time not useful (but can cost a lot in terms of scalability)
Application pool pros:
You don't have to be a .Net programmer to understand what's going on.
The security aspect leaves the domain of the programmer and falls under the remit of infrastructure
Easy to change through IIS with proper saftey checks that the username is correct when setting up the app pool. I.e. It won't let you enter an incorrect username.
Impersonation pros:
Privileges can be documented and traced back through changes to configuration through source control history if configuration files are stored there.
Impersonation cons:
To change the user, you need to be familiar with .Net configuration rather than just setting up a website
Not sure I can think of much else.
My gut says to go with different application pools for each of the websites but it's your party.
I would advise you to check the following page for security details...
https://www.attosol.com/sample-aspx-page-to-show-security-details-in-asp-net/
Once you are done with this, you will see "precisely" how impersonation changes the identity.

What is the best practice for role security for an Intratnet ASP.NET/SQL2K5 environment?

Our current Intranet environment is a little outdated. The current stack has ASP.NET 1.1/2.0 applications that are querying against a SQL 2000 database.
For role security, there are user groups on the servers that users are added into (so you need to be added into the group on the test and production machine). These user groups are synchronized into user roles on SQL 2000 itself. Roles are granted execute permissions to stored procedures as needed to prevent any access violations.
At the web application level, we use basic authentication (which authenticates against our Active Directory) and have identity impersonation turned on. The connection string to the database uses Integrated Security. This creates an environment where the web application connects to the database as the user logged in, which will enforce database security on stored procedures being called. It also allows us to use the typical User.IsInRole() method to perform authorization within the application itself.
There are several problems with this. The first is that only our server administrators have access to the user groups on the machine, so updating role security, or adding additional users is out of the hands of the application administrators. In addition, the only way to get the role was to call a SQL procedure called "xp_logininfo" which is locked down in SQL 2005. While I don't know the full details, our DBA tells us that this general model doesn't play nice with SQL 2005 given the nature of schemas in the newer version.
We're at the point now that we're ready to update our environment. We're writing .NET 3.5 apps to leverage more AJAX and SQL Server 2005 is the primary environment for our database. We're looking to update the security model as well to be a bit more flexible for the application administrators, and potentially leverage Active Directory more.
One concern we have as well is that a given user will most likely have access to multiple applications, so having some kind of centralized solution is optimal so we can easily remove users when needed.
What is considered the best practice for maintaining role security in this kind of environment?
ASP.NET 2.0's Membership, Roles, and Profile
I don't think the considerations related to the decisions that where made before has changed that much.
About the schema comment, those will just help you organize the database elements, so you can assign permissions to all inside a schema instead of having to configure for each procedure/table.
The decisions involved on whether having the identity flow down to the SQL Server instead of using the trusted subsytem model, are pretty much specific to the particular scenario. That said, I don't like to flow identity like that, because usually there is still logic being enforced on the application which means the sp are probably enforcing partial rules. Because of that reason, that approach also pushes to have more logic in the stored procedures.
About only administrators having access to the user groups in the machine, consider looking at ADAM (active directory application mode). I don't know if it supports integrating it with SQL Server, so I am not sure if that will work with that architecture. It is worth checking though.
Regarding not being able to get the roles, based on your info, I would assume there is a close relation between user groups and involved database roles. You can get the groups(roles) the user has in active directory.
Bottom line: evaluate how ADAM fits in your scenario, and whether the considerations involved into using the current identity flow approach remain. Also don't forget to consider the impact in the project on changing the identity flow of the application.
Try to refactor your design in such a way that your repository itself is LDAP. So essentially your users and roles objects map AD objects. You can then have the complete control rather than going through various system administrators. Of course, this is not easy depending on the state of code. But the best way to start out is to create small proof of concept to accomplish this mapping of your business objects to AD.

Resources