SQL Agent jobs owned by users
Issue: Every SQL Server Agent job has an owner, which is the login responsible for the job and used to determine the security context in which certain job steps execute. The owner of a job affects how the job is treated during execution, who can modify it, and what happens when the owning login changes or is removed.
This finding identifies SQL Server Agent jobs whose owners are individual user logins rather than a system or service principal. The condition is most often the result of jobs being created ad hoc by administrators or developers without consideration of long-term ownership.
Problem: When a job is owned by an individual user login, the job becomes tied to that person's account lifecycle. If the user leaves the organization, changes roles, or has their login disabled or dropped, the job can fail to start, fail to send notifications, or stop running entirely depending on the specific configuration and SQL Server version.
Job ownership also affects security context. Job steps that run as the owner inherit that user's permissions, which means a job owned by a sysadmin runs with full instance privileges even if the work being performed does not require them. This creates a hidden privilege escalation path, since anyone who can modify the job can effectively execute code as the owner.
User owned jobs also complicate audit and review. The presence of jobs owned by former employees, by personal accounts, or by accounts with elevated privileges produces audit findings and indicates that job ownership is not being managed deliberately. The audit trail of job changes also becomes harder to interpret when ownership reflects whoever happened to create the job rather than a consistent ownership model.
The condition often persists because job ownership is rarely visible in normal monitoring. Jobs continue to run successfully under their original owner long after the owning user has moved on, and the issue surfaces only during audits, security reviews, or when the owning account is finally removed and jobs begin to fail.
Learn More...Cross-database ownership chaining
Issue: Ownership chaining is a SQL Server security mechanism that allows a user to access objects through a stored procedure or view without needing direct permissions on the underlying objects, as long as the calling object and the underlying objects share the same owner. Within a single database, ownership chaining is enabled by default and is the basis for the common pattern of granting users execute permission on a stored procedure while denying direct access to the tables it reads or writes.
Cross database ownership chaining extends this mechanism across database boundaries. When enabled, ownership chains can span databases as long as the relevant objects are owned by the same login at the server level. The behavior is controlled by two settings: the server level cross db ownership chaining configuration option, which enables the feature globally, and the database level DB_CHAINING option, which enables it on a per database basis.
This finding identifies instances where cross database ownership chaining is enabled, either at the server level or for one or more individual databases.
Problem: Cross database ownership chaining bypasses the permission checks that normally occur when a query crosses database boundaries. A user with execute permission on a stored procedure in one database can read or write objects in another database with no direct permissions there, as long as the ownership chain is unbroken.
This expands effective access in ways that are not obvious to administrators, since the chained access does not appear in any user's direct permission grants. Tracing the full set of accessible objects becomes difficult when chained procedures call other chained procedures across multiple databases.
The feature also creates privilege escalation paths that are hard to anticipate. A user with db_owner rights in one database can create dbo owned objects that reach into other databases owned by the same login at the server level, which is often a privileged account such as sa.
Microsoft recommends keeping cross database ownership chaining disabled at the server level and enabling it only on specific databases where it is genuinely required, with documentation of the reason and the access paths involved.
Learn More...xp_cmdshell enabled
Issue: xp_cmdshell is an extended stored procedure in SQL Server that executes a command string as an operating system shell command and returns the output as rows of text. It runs the command under the context of the SQL Server service account by default, or under a proxy account if one has been configured. The feature is disabled by default starting with SQL Server 2005 and is controlled by the xp_cmdshell server configuration option.
This finding identifies instances where xp_cmdshell is enabled. The setting is sometimes turned on intentionally to support administrative scripts, scheduled jobs that need to interact with the file system, or vendor applications that depend on shell access, and other times it is enabled by an administrator who simply wanted to run a single command and never disabled it afterward.
Problem: xp_cmdshell is widely discussed as a security concern, but the actual risk picture is more nuanced than the configuration setting alone suggests. By default, only members of the sysadmin fixed server role can execute xp_cmdshell, and members of sysadmin already have the ability to enable or disable the feature at will using sp_configure. This means that for an attacker who has already obtained sysadmin level access, the on or off state of xp_cmdshell is essentially a formality, since they can flip the setting and run commands at any time.
For this reason, the more important security control is who has membership in the sysadmin role (and the equivalent CONTROL SERVER permission and securityadmin role), not whether xp_cmdshell is currently enabled. An instance with xp_cmdshell disabled but with excessive sysadmin membership is no more secure against a compromised privileged account than an instance with the feature enabled, since the elevated account can change the setting in seconds.
That said, xp_cmdshell does increase risk in specific scenarios that warrant attention. When the xp_cmdshell proxy account is configured, non sysadmin users can be granted execute permission on xp_cmdshell and run commands under the proxy account context. This delegated access path is sometimes used to allow application accounts or scheduled jobs to run shell commands, and the proxy account's permissions on the host become a critical security boundary. A poorly scoped proxy account, or one with excessive permissions, can become a privilege escalation path that does not require sysadmin to exploit.
Enabling xp_cmdshell also expands the impact of certain attack patterns, including SQL injection. An injection vulnerability in an application connecting with a privileged account becomes significantly more dangerous when xp_cmdshell is available, since the attacker can move from data exfiltration to operating system command execution in a single step. Disabling xp_cmdshell does not prevent the injection vulnerability itself, but it does limit the immediate options available to the attacker if they reach the database.
Learn More...CLR enabled
Issue: The clr enabled server configuration option controls whether SQL Server allows the execution of managed code through the Common Language Runtime (CLR) integration feature. When enabled, developers can create stored procedures, triggers, user defined functions, and aggregates written in .NET languages such as C# and have them execute inside the SQL Server process.
This finding identifies instances where clr enabled is set to 1. The setting is off by default and is enabled either explicitly to support CLR based code or as a side effect of installing certain features and vendor applications that depend on CLR functionality.
Problem: CLR integration extends the attack surface of SQL Server beyond traditional T-SQL, allowing managed code to perform operations that T-SQL alone cannot, including file system access, network calls, and direct interaction with operating system resources. While CLR assemblies are sandboxed by default, the protections depend on how the assembly is registered and on the overall security model of the instance.
Historically, CLR assemblies could be registered with one of three permission sets: SAFE, EXTERNAL_ACCESS, or UNSAFE. SAFE was the default and provided the strongest containment, while EXTERNAL_ACCESS and UNSAFE allowed progressively broader access to system resources.
Microsoft introduced a security advisory and a new configuration option, clr strict security, in SQL Server 2017 and later. With strict security enabled (which is the default in SQL Server 2017 and later), all assemblies are treated as UNSAFE regardless of their declared permission set, and the engine requires either that the assembly be signed with a certificate or asymmetric key that has been granted UNSAFE ASSEMBLY permission, or that it be added to the trusted assemblies list using sp_add_trusted_assembly. This change closes the older privilege escalation paths but requires that assemblies be properly signed or trusted, which not all environments have done.
When clr enabled is on without clr strict security enforced, or when assemblies are run as UNSAFE without proper signing, the instance is exposed to risks including code that can read or modify files on the SQL Server host, make outbound network connections to exfiltrate data, execute arbitrary operating system commands under the SQL Server service account context, and bypass SQL Server permission checks through the elevated execution context.
Learn More...About sp_checks
This page contains a list of SQL Server configuration checks performed by Straight Path's suite of sp_check tools. For more details about our free tools, select one from the following list: