When Databases Attack: SQL Server Express Privilege Inheritance Issue
SQL Server Express is commonly used by database hobbyists, application developers, and small application vendors to manage their application data. By default, it supports a lot of great options that make it a very practical solution to many business problems. However, it also comes configured with a not so great setting that could allow domain users to gain unauthorized access to SQL Server Express instances. In this blog I’ll cover what the issue is, how to attack it, and how to fix it.
How it works
Through privilege inheritance, all domain users have access to default SQL Server Express instances that have remote listeners enabled. This appears to be possible because the local Windows “BUILTIN\Users” group is assigned “connect” privileges during the default installation. Below is a summary of how this configuration allows users to gain unauthorized access to databases.
- By default, the “NT AUTHORITY\Authenticated Users” built-in security principal includes all users that have been “authenticated locally by a trusted domain controller.”. That includes all domain user and machine accounts.
- By default, the “NT AUTHORITY\Authenticated Users” built-in security principal is added as a member of the local “Users” group in Windows. This can be verified by issuing the following command from a Windows console:
C:\>net localgroup users Alias name users Comment Users are prevented from making accidental or intentional system- wide changes and can run most applications Members ------------------------------------------------------------------------------- NT AUTHORITY\Authenticated Users NT AUTHORITY\INTERACTIVE The command completed successfully.
- By default, SQL Server Express 2005 to 2014 create a login for the local “BUILTIN\Users” group that provides users with connection privileges. This can be verified by issuing the following query in any default SQL Server Express instance:
C:\>SQLCMD -S "%COMPUTERNAME%\SQLEXPRESS" -E -Q "SELECT * FROM sys.server_principals WHERE name = 'BUILTIN\Users';" name ------------------------------------------------ BUILTIN\Users (1 rows affected) ...[snip]...
- As a result, all user and machine accounts on the same domain as the SQL Server Express instance also inherently have connect permissions to the SQL Server Express instance if a TCP listener has been enabled. Below is a basic example of how to issue a query to one of the affected SQL Servers from a Windows console:
SQLCMD -E -S "AffectedServer1\SQLEXPRESS" -Q "SELECT @@Version"
At a minimum, this default configuration provides an internal attacker with initial access to SQL Server Express instances. That “foot in the door” could potentially be leveraged to gain access to other database servers, systems, and network resources. During penetration tests, this type of issue often leads to exposure of sensitive data, and system access.
How to attack it
Below I’ve outlined one method for accessing SQL Server Express instances on the current broadcast domain using a standard ADS domain account. Keep in mind that there are a number of ways to accomplish the same thing. For example, it could be run through the “xp_cmdshell” extended stored procedure in order to run with the privileges of the SQL Server service account, which is the domain machine account if configured with “nt authority\system”. Also, a full list of domain SQL Server targets could be obtained by any domain user via LDAP queries for MSSQL SPN information.
Note: You may have to disable/modify your local firewall to ensure that SQLCMD can process the UDP responses from the SQL Servers on the network.
- Log into a Windows system with domain credentials.
- Install SQL Server Express.
- Open up a command prompt.
- Enumerate SQL Server instances that you have access to on the domain with the command below.
FOR /F "" %a in ('SQLCMD -L') do SQLCMD -E -S %a -Q "SELECT 'Vulnerable: '+@@SERVERNAME" | FIND /I "Vulnerable:" >> dbservers.txt
- Now you have a list of vulnerable SQL Servers that you can issue arbitrary queries to with SQLCMD or SQL Server Management Studio. If you’re a penetration tester, you can also start escalating privileges and gaining unauthorized access to data.
At some point in the near future I’ll also release a TSQL script that will output the list into a pretty table. If you’re interested in similar attacks, I wrote a blog called “When Databases Attack: Hacking with OSQL” that you might like.
How to fix it
Remove the “BUILTIN\Users” login from SQL Server express instances to prevent evil doers from accessing your data.
Conclusions
From what I understand, Microsoft only made this a configuration default in express editions to help make SQL Server easier to deal with on Windows systems with User Access Control (UAC) enabled. So if you’re running any other edition you shouldn’t have to worry about anything unless someone manually added a login for BUILTIN\Users. With that, I have a few words of advice. First, never trust default configurations. Second, always leverage best practice hardening guides to help lock down new systems and applications. Third, don’t forget to configure accounts and securables with least privilege. Good hunting.
References
Explore more blog posts
The Balancing Act of In-House vs Third-Party Penetration Testing
Discover how combining in-house and third-party penetration testing brings a hybrid approach to enhance your cybersecurity strategy.
CVE-2024-37888 – CKEditor 4 Open Link plugin XSS
NetSPI discovered CVE-2024-37888, a cross-site scripting (XSS) vulnerability in the CKEditor 4 Open Link plugin. Read about the nature of the vulnerability and its implications.
An Introduction to GCPwn – Parts 2 and 3
Example exploit path using GCPwn covering enumeration, brute forcing secrets manager versions, and downloading data from cloud storage both through default enum_buckets and with HMAC keys.