Home             About Us             Sign Guest Book             Contact Us             Subscribe              RSS  
Articles
Tools
Code Snippets
Links
Tips & Tricks
FAQ
Resources
Articles
Code Snippets
Links
FAQ
Resources

Saravana Kumar
Vinod Kumar

Click on the image to subscribe to our Monthly Newsletter.


Click here for Archives

No Chats Available

Security in SQL Server 2005 – Part II

In  Part I on Security with SQL Server we did try to get into some aspects of security which as an administrator or developer one needs to know. We started with instance security, database security, authentication, authorization etc. Now we will get into aspects that I couldn’t cover before like Agent Service security, Object-level security, Execution contexts and many more. We will try to cover as much ground as possible in this article.

Securing the SQL Server Agent Service

The SQL Server Relational Engine includes an assistant service called SQL Server Agent, which handles administrative operations such as jobs, alerts, and defining operators. This service facilitates administrative tasks and is the fundamental element related to security because of the nature of the activities it performs. It could be a target of security attacks if it is improperly configured. With the context set, here are some guidelines to secure the SQL Server Agent service.

The SQL Server Agent service is a separate administrative process in Windows and must run under a Windows security context. In SQL Server 2000 and earlier versions, the security context of SQL Server Agent is the Local System account. This security context is a violation of the principle of least privilege because the Local System account has more permissions than those required by the SQL Server Agent service. And these in many cases were exploited by many hackers. Later in this article we will take a look at how this vulnerability got mitigated with SQL Server 2005’s Agent architecture.

Objects created in SQL Server Agent run under different security contexts, depending on the type of user who creates the object. For example, if the creator of the job is a member of the Sysadmin group, the job executes under the context of the SQL Agent service account or the user needs to specify a proxy account.

In SQL Server 2005, you can create multiple proxy accounts for multiple subsystems in SQL Server Agent. Subsystems include tasks such as SQL Server Integration Services Package Execution, ActiveX Script, PowerShell, Replication related and even Analysis Services Query. You can restrict access to a specific set of tasks and create multiple proxy accounts for each activity.

A proxy account is usually assigned to a subsystem, and a user is associated with the proxy account. If a user creates a step in a job and wants to run the step under the context of a specific proxy, it is possible only if the user is associated with the proxy account. You can control the security configuration by defining which user has the ability to use which proxies. By using this definition, a user can execute specific subsystem tasks under the context of a specific proxy.

The SQL Server Agent service includes a new security model to control access to this service. There are three new database roles created in the msdb system database to control access to SQL Server Agent: SQLAgentUserRole, SQLAgentOperatorRole, and SQLAgentReaderRole. Users with logons that belong to SQLAgentUserRole can create and add job steps. By default, no logon is a part of this database role. By now we have a fair idea to how granular the Agent Service has become since its SQL Server 2000 era inside of SQL Server 2005.

Securing Database-Level DDL Events

One of the risks to SQL Server security is the modification, creation, or deletion of objects inside a database. To control the risks associated with these activities, a new kind of trigger—data definition language (DDL) triggers—has been implemented in SQL Server 2005. Use the following guidelines to audit and monitor DDL events. In the earlier article we did discuss about the instance level DDL triggers though.

There are specific DDL events that support DDL triggers. These triggers allow you to cancel or audit the event that fired the trigger. This feature helps you to protect databases and instances from unwanted DDL events, such as a DROP TABLE statement.

For example, if you have a security requirement to store audit information about the attempts to modify the objects in a database, you can create a trigger that records the attempts and rolls back the operation. The trigger can then store the information related to the two activities in a table for auditing purposes. In the case of DDL events, you can use the EVENTDATA function to make the context information available. This function will return an XML value with the information related to the event.

There is a specific event class called Objects that has three events related to object management: Object:Altered, Object:Created, and Object:Deleted. By using these events, you can keep track of who modified what object, and when an object was modified in the database.

Object-Level Security Policy

The security that you apply to database objects is the final layer in your database security configuration. To secure database objects, permissions are granted at different layers of the SQL Server architecture. When defining object permissions, you should consider the granularity level and data access methods. The granularity level reduces the administrative overhead on SQL Server without violating the principle of least privilege. Access methods are used to work with the data in the database objects. These access methods will have an impact on the level of control that we can create for users’ actions.

The three levels for granting access to objects in a database are database level, schema level, and object level. The three main data access methods are ad hoc data access, stored procedures, and views.

Here are some rough guidelines for designing the granularity of permissions:

  • Define permissions at various levels: When defining the granularity of permissions, you should apply access permissions at the object level. Defining permissions at the object level allows you to control, in a very granular and specific way, the principles that access specific resources.
  • Reduce the administrative overhead by using higher scopes: If there are generalizations in your permission sets, you can use the higher levels (scopes) in the permission hierarchy to reduce the administrative overhead involved when using object-level permissions. For example, if you need to grant EXECUTE permissions to all stored procedures in a schema, you do not need to grant EXECUTE permissions to each stored procedure individually. Instead, you can grant EXECUTE permissions at the schema level. The same concept is valid if you need to grant EXECUTE permissions to all schemas—you can grant EXECUTE permissions at the database level, which will be applicable across all schemas.
  • Choose appropriate permissions: Whether you choose permissions at the object level, schema level, or database level, you must keep in mind that the most restrictive permission takes precedence over other permissions. For example, a DENY permission at any level overrides permissions set at higher or lower granularity levels.

Here are some other aspects while designing the data access methods with SQL Server:

  • Disable ad hoc users: Accessing tables directly could imply that users and applications understand the internal structure of the database. If you need to implement schema changes on tables, the process of determining the impact of these schema changes becomes complex. This is because there is no centralized place to make changes, and these changes must be made for each user and application.
  • Create stored procedures to access data: Database administrators (DBAs) who are responsible for data security should create stored procedures to access the data in a database. Many business requirements and government regulations require DBAs to restrict access to sensitive data in their databases. Permitting ad hoc access violates these requirements and does not allow users or applications to use predefined stored procedures or views.
  • Use predefined procedures or views to restrict data access: DBAs are responsible for users or applications that do not use predefined views or stored procedures.

Now that we have taken a tour on the access and the permissions part, let us move into another interesting aspect of Execution Context which is equally important and very much linked with the discussions we just started.

Designing the Execution Context

The execution context establishes a security identity against which permissions to execute statements or perform actions are checked. This is determined by the user login. To impersonate another principal, SQL Server supports the explicit use of the stand-alone EXECUTE AS statement, or the implicit use of EXECUTE AS clause on modules such as stored procedures, triggers, and user-defined functions.

Use EXECUTE AS to create a custom permission set. Instead of the user calling the EXECUTE AS statement or the module, SQL Server checks permissions against the login and user for the account to which the execution context has been switched. In other words, the user or login account is impersonated for the duration of the session or module. The execution context can be explicitly or implicitly switched at both the server and database level. The execution context of a session can be explicitly changed by specifying a user or login name in an EXECUTE AS statement.

The execution context of a module, such as a stored procedure, trigger, or user-defined function, can be implicitly changed by specifying a user or login name in an EXECUTE AS clause in the module definition. The impersonation scope of a context established within a database can be extended to other scopes if the authenticator is trusted in the target scope, and the source database must be marked as trustworthy. There are four ways in which you can use the EXECUTE AS clause: EXECUTE AS CALLER, EXECUTE AS 'user', EXECUTE AS SELF, and EXECUTE AS OWNER. The recommended EXECUTE AS clauses are EXECUTE AS 'user' or EXECUTE AS OWNER.

Use code signing in scenarios in which you do not trust all the content, but only trust a few modules in the database.

Securing Module Execution

The switching of the execution context has multiple granularities. Moreover, you might not want to trust all of the content in a database, but only a few specific modules in it. In such cases, consider implementing the security features by using digital signing. The objective of using digital signing is to include an intermediary whom you trust to create a certificate. This intermediary will sign the code that you want to trust with the certificate. The intermediary drops the private key from the database to ensure that nothing can be signed in another module. Digital signing prevents anyone who does not have access to the public key from executing the signed module.

The intermediary gives you a copy of the public key. You create another certificate with that public key, which you use as the base for creating a user in your database. You can then trust that user because it is signed by the certificate created with the public key. This user can execute modules that are signed by certificates created with the private key.

When you use certificates to sign individual modules, you define a security environment that will not require marking the complete database as trustworthy. Therefore, digital signatures ensure a finer control over impersonation and code security.

Security for SQLCLR Objects

SQL Server 2005 is integrated with the Microsoft .NET Framework. This integration enables you to take advantage of all the objects and the speed of development that is available in the different parts of the common language runtime (CLR). However, this option requires a security model to permit safe interaction between the CLR code and SQL Server.

When the CLR code is executed in SQL Server, the code must be compliant with all the rules defined in the security policies. If a policy allows a specific feature and another policy denies it, the denied option takes precedence. This means that the effective set of permissions in an assembly is a mutually allowed set of permissions defined in the policies affecting that assembly. You should catalogue most of the code as SAFE. If an assembly has a SAFE code and an EXTERNAL_ACCESS code, the codes should be separated into two different assemblies and catalogued separately.

When accessing external resources, CLR objects will use the security context of the SQL Server service account by default. However, this behavior can be overridden by implementing impersonation in the CLR code. To define which objects can be accessed, the security model is the same as that for every other object in SQL Server.

The code accessing the internal SQL Server resources will have the security context of the user executing the module. For example, if a user executes a CLR stored procedure that tries to access a table, the permissions of the user are evaluated to access that table.

Quick Tips for Alerting

To get your alerting mechanism done, it is critical to undestand the high level classification of the error levels for which alerts might be required. There can be 4 types of alerts and each have different characteristics.

  • There are informational messages which are not severe and are status like information like the login / logout informations. These can be logged for further analysis but dont quite need immediate attention. Sometimes abnormal behaviours in these informational messages can be indicators of malicious activities like # of Invalid Login attempts in a short span of time can be an indicator of DOS attacks.
  • Errors such as “permission denied” or a “failed logon” can be resolved based on user interaction. For example, the user could try to log on again by using the correct user name and password. To rectify such errors, the user could access a stored procedure that returns information from a table by using a view. Incidentally, these errors are very much corrected by the user itself. Although such errors could be managed by the client application code, they could be an indication of more severe errors or performance issues. For example, you can manage these errors by using the TRY...CATCH structure in the Transact-SQL code.
  • Then comes the Software errors, These errors provide information about the status of SQL Server databases—for example, unauthorized disabling of a network library or a change of port because of an attack. You must define alerts for these types of errors.
  • And finally the fatal errors, these are errors that require immediate action from the DBA Group—for example, corruption of a table or index due to a hardware problem or a suspect database or torn-page detection or corrupt check-sum page etc.

Conclusion

In this Part II we continuted from where we left on the other article and continuted to build the base with Agent Service specifics, Object-Level Security, Execution Context, CLR Object specifics and many more. Even this in my opinion might not complete all the aspects of security and hardening infrastructure one might want with working with SQL Server. But I would want to take this opportunity to iterate that these are basic concepts and SQL Server 2008 very much builds on these fundamentals. We might get specific features but the core features never change. Hope you enjoyed reading and do drop your comments.

Comment about this article
Free Hit Counters
Free Hit Counters