非常不错的文章:
APPLICATION SECURITY, INC. | WWW.APPSECINC.COM
HUNTING FLAWS IN SQL SERVER
INTRODUCTION
This paper will discuss a number of recently discovered vulnerabilities in Microsoft SQL Server
and will demonstrate the techniques used by the author to find these security holes.
COLLECTING PASSWORDS
When SQL Server is running using mixed-mode authentication, login passwords are saved in
various locations. Some passwords are saved using strong encryption and permissions (such as
the passwords saved in master.dbo.sysxlogins), but many of them are saved using weak
encryption (most accurately referred to as encoding) and weak default permissions. You may be
asking, “Why passwords are saved with weak encryption?” The reason is that these passwords
must later be extracted and used by SQL Server to establish connections with itself and other
SQL Servers. This occurs during many of the batch processes that SQL Server relies on,
including replication, jobs scheduled through the SQL Agent, and DTS packages.
Using various techniques, such as examine system tables and stored procedures or running tools
such as SQL Profiler, we can determine where and how these passwords are saved. Typically
system tables that hold these passwords are properly secure, that is only if dbo has permissions
to select from the table. There are, however, system stored procedures that access these tables
- so looking at these stored procedures is a good place to start.
SQL AGENT PASSWORD
We start by looking at the SQL Agent configuration from within SQL Enterprise Manager. Select
the node <SQLServerName>/Management/SQL Server Agent. Then click the right mouse button
and select Properties from the popup menu. Within the “Connection” tab you will see that the
SQL Server Agent can be configured to connect using standard SQL Server authentication with a
login in the sysadmin role. This information must be saved some place in order for SQL Agent to
later access the password and connect to the SQL Server, so we start a new trace in SQL Profiler
to see what happens behind the scenes. Set the login to “sa” and set the password to “a”. We
can see the difference between the two SQL statements in SQL Profiler.
EXECUTE msdb.dbo.sp_set_SQLagent_properties @host_login_name = 'sa’, @host_login_password = 0x6e1c7e83d0a487d623fc7cd689b8e702cc416bcd8d18c28ee0a4ba37c97ccfb5
Performing the same action but setting a password of “aaaaaaaaaa”, we execute the following
statement.
EXECUTE msdb.dbo.sp_set_SQLagent_properties @host_login_name = 'sa’, @host_login_password = 0x6e1c1f1b809cb8a1a1acd3c2cb1cce7e0a099592a03ab7979f196de0b6898deb
We can see that the encrypted password is passed to the stored procedure
sp_set_SQLagent_properties. In the stored procedure we see:
EXECUTE master.dbo.xp_SQLagent_param 1, N'HostPassword', @host_login_password
The encrypted password is finally saved by the extended stored procedure xp_SQLagent_param
- but where is it saved? We must assume that it is not saved in a system table because the
APPLICATION SECURITY, INC. | WWW.APPSECINC.COM
HUNTING FLAWS IN SQL SERVER
password is used to connect to SQL Server so the Agent would need to access the password
before connecting to the database. Given that it is not saved in a table then it is probably saved
in the registry. We can run Regmon.exe (Registry Monitor tool from
http://www.sysinternals.com/ntw2k/utilities.shtml) and see where it’s saved. We will find that it is
saved under the LSA Secrets key:
HKLM/security/policy/secrets/SQLSERVERAGENT_HostPassword/currval
Only the Windows LocalSystem account has permissions to access this registry key. Even
Windows Administrators cannot access this area, although they can take ownership and give
themselves permissions to these keys. Now we know how and where the encoded password is
saved, but how is it retrieved when Enterprise Manager displays the SQL Agent properties? Well,
we select SQL Server Agent properties in Enterprise Manager again and then record the SQL
sent through SQL Profiler. We see this statement:
EXECUTE msdb.dbo.sp_get_SQLagent_properties
We start SQL Query Analyzer, execute the query, and see that most of the properties of the SQL
Server Agent are returned - even the encrypted password! But which users can execute
sp_get_SQLagent_properties. To determine this we execute the following statement.
EXECUTE sp_helprotect sp_get_SQLagent_properties
The results are as follows:
Owner Object Grantee Grantor ProtectType Action Column dbo sp_get_SQLagent_properties public dbo Grant Execute .
Cool! We have discovered a security hole that can be used by any user in the database! We
have the encrypted password – now we must figure out how to decrypt it. We go back and look
at the passwords:
The encrypted version of the password (a) is:
0x6e1c7e83d0a487d623fc7cd689b8e702cc416bcd8d18c28ee0a4ba37c97ccfb5
The encrypted version of the password (aaaaaaaaaa) is:
0x6e1c1f1b809cb8a1a1acd3c2cb1cce7e0a099592a03ab7979f196de0b6898deb
Upon first analysis, we can see that the first two bytes are the same in both encrypted passwords.
Upon further analysis we realize that the encryption algorithm used is a simple XOR with a
positional key depending on the previous character. We can do a chosen plain-text attack
knowing that the first character is always XOR’ed with a fixed key. Why not look for the function
used by Enterprise Manager to encrypt the password. (Special thanks to Jimmers for discovering
and sharing the following) After some research, we find that SEMCOMN.DLL (located in SQL
Server Instance Binn folder) has a Decrypt() function that can be used to decrypt the password.
So we can code a simple program and use the Decrypt() function to get the clear text password.
Ok, now we have the password for a login that has been granted the sysadmin role. The server
belongs to us at this point! It is important to note that if we are successful in the previous attack,
we can now get system or administrator privileges over the OS with additional attacks. This is
because if the SQL Server Agent is configured to connect to SQL Server using SQL Server
authentication, the SQL Server Agent must run under the LocalSystem account or an
Administrator account in order to have permissions to successful retrieve the encrypted password
from the registry.