Stealing 2FA Tokens on Red Teams with CredSniper

Mike Felch //

More and more organizations are rolling out mandatory 2FA enrollment for authentication to external services like GSuite and OWA. While this is great news because it creates an added level of security to the external perimeter, it also forces red teams and pentest organizations to innovate new techniques into capturing 2FA tokens instead of just obtaining employee credentials. Over the years, there has been a number of attack primitives related to obtaining 2FA tokens. In some cases attackers would attempt to spoof GSM on mobile phones, try to brute force tokens or even bypass 2FA requirement altogether by searching for legacy portals that have multi-factor disabled. Recently, attackers have started social engineering victims into sending their tokens through SMS messages by scamming users with a fake password reset initiation on the account. While some of the techniques may work from time to time, the likelihood of them being a sound attack path is fairly unlikely. CredSniper was originally birthed out of a need while on a red team engagement and since then has morphed into a sound method of successfully obtaining credentials and 2FA tokens from even highly-technical senior staff.

Introducing CredSniper

Phishing credentials has been going on for years and most organizations are beginning to roll out awareness training in their normal on-boarding processes. The problem I see regularly is that organizations are training on how to spot red flags in emails instead of instilling healthy internet behaviors, regardless of the communication platform. If I can lure an unsuspecting victim to an exact clone of an authentication portal they are already familiar with, most will hand over their credentials and 2FA tokens if I ask nicely. This is where CredSniper really shines!

HTTPS is Mandatory

Aside from protecting targets on an engagement from putting their credentials in a non-HTTPS site, it’s equally important to ensure the quality of the cloned authentication portal doesn’t reveal the red flags most organizations train to recognize. This is mandatory if you are cloning a GSuite portal because Google Chrome browser will alert the target that the site is a malicious looking site. The moment you switch over to HTTPS, this problem resolves itself because Google isn’t intercepting the request and response payload between the visitor and the server. During the installation, CredSniper will request a new SSL certificate from Let’s Encrypt for the host you supply. The only prerequisite is that the hostname you plan to use is pointing to the IP address of the server hosting the cloned portal.

Modular Authentication Portals

While CredSniper comes with a module for GSuite, new modules can be created with minimum overhead. In the future, this will be much more streamlined but in the meantime users can create a new portal modules in 5-10 minutes. The module defines the mapping between templates and routes. For instance, if someone accesses /login then the module will know to load the correct template for that phase of the authentication process. The idea behind CredSniper was that functionality could be written to authenticate with the genuine portal behind the scenes and during the interaction with the target. By authenticating with the genuine site, the 2FA SMS token would be sent to the target and CredSniper could prompt the user to enter it.

Templates are the HTML copy of the genuine portal but with the necessary templating tags. CredSniper uses a templating language called Jinja2 which provides a seamless way to personalize phishing pages with user-supplied data. For instance, some authentication portals like GSuite first ask the user for an email address before sending them to a password page and then on to the 2FA page. Within the password page, GSuite displays the users profile image right next to their email address. Because CredSniper captured the email address at the first stage of the phish, using it in subsequent pages is as simple as placing the tag {{ username }} in the HTML template. Jinja2 automatically replaces the tag with the value when rendering the template. Any number of routes can be configured within the module to account for all different variations of authenticating processes.

API Integration

CredSniper also comes with a light-weight API so users can integrate the harvested credentials in other applications. Due to 2FA token expiration occurring fairly quick, the API provides a fast way of consuming the credentials to automate authentication tasks before it’s too late. Upon running CredSniper, an API token will be displayed on the screen which will will provide the ability to consume the end-points for viewing credentials, marking them as seen and for updating the configuration.

View Credentials (GET)

https://<phish site>/creds/view?api_token=<api token>

 

Mark Credential as Seen (GET)

https://<phish site>/creds/seen/<cred_id>?api_token=<api token>

 

Update Configuration (POST)

https://<phish site>/config

{

   'enable_2fa': true,

   'module': 'gmail',

   'api_token': 'some-random-string'

}

 

Simple Installation

In order to kick-off the installation, CredSniper requires the DNS to be configured for the hostname you plan on using. As mentioned earlier, Let’s Encrypt needs to be able to verify the hostname before issuing an SSL certificate so the hostname needs to be assigned to the IP address of the host where CredSniper is being hosted. Some people have reported that the installation script will throw errors on distros other then Ubuntu 16.04. While it’s possible to get everything installed and running on other Linux versions or distributions, it’s highly recommended to use Ubuntu 16.04 to avoid problems that might require troubleshooting.

The first thing you will want to do is clone the GitHub repo, this will grab all the necessary files and also provide an easy way to upgrade, as new code is pushed. Once it’s cloned, switch directories and run the install.sh script.

$ git clone https://github.com/ustayready/CredSniper
$ cd CredSniper
~/CredSniper$ ./install.sh

 

The install script will request information from you in order to configure the required parameters and kick-off the initial running of CredSniper. These parameters can be passed in as flags in future runs of CredSniper.

Module to deploy (ex: gmail): This is the CredSniper module that will be ran. For a list see the modules/ directory.

Final redirect URL: The final destination URL for the target’s browser after phishing. This should coincide with your ruse in order to eliminate suspicion in the mind of the target.

Enable SSL? [Y/n]: Whether to phish using SSL or not. This may be required in future versions due to how browser’s flagging suspicious looking sites.

Enable two-factor phishing? [Y/n]: This option is whether or not to control two-factor phishing without having to change the module routes. Sometimes two-factor is not enabled and being able to disable it from the command-line is convenient.

Enter hostname for certificates (ex: app.example.com): This hostname will be used by Let’s Encrypt in order to retrieve an SSL certificate for CredSniper. In order for CredSniper to be reachable by this hostname, the DNS for the hostname must be pointing to the IP address of the hostname before install.sh is ran.

Port to listen on (default: 80/443): CredSniper only runs in either HTTP or HTTPS mode, not both. Sometimes portals that are cloned run on alternative ports, in order to look legit, CredSniper can be configured to run on alternative ports. By default if CredSniper is running in HTTP mode then port 80 is assigned. If running in HTTPS mode, 443 is assigned.

A number of pre-requisites will also be installed if they are not already present:

  • Let’s Encrypt Apt Repository
  • Python3
  • VirtualEnv
  • GnuPG
  • CertBot
  • Python3 modules: Flask, mechanicalsoup, pyopenssl

Using Python3, a virtual environment will be created and the necessary Python3 modules will be installed. Next, port binding for Python will be enabled so listening on port 80/443 can be possible from userland. Finally, the certificate and private key for the SSL certificate will be copied into the certs/ folder.

After a successful installation of everything, CredSniper will be ran! The install.sh script will not be required for future executions of CredSniper. In order to execute CredSniper, simply run the python script: python credsniper.py –help

If you happen to logout of the host and want to run CredSniper at a later time, be sure to first activate the Python virtual environment before running credsniper.py:

~/$ cd CredSniper
~/CredSniper$ source bin/activate
(CredSniper) ~/CredSniper$ python credsniper.py –help

That’s it!

Flexible Usage

CredSniper comes with a flexible ability to run in a number of different configurable modes. In order to access the flags, simply pass the –help during execution.

usage: credsniper.py [-h] --module MODULE [--twofactor] [--port PORT] [--ssl] [--verbose] --final FINAL --hostname HOSTNAME

optional arguments:
-h, --help                           show this help message and exit
--module MODULE             phishing module name - for example, "gmail"
--twofactor                          enable two-factor phishing
--port PORT                          listening port (default: 80/443)
--ssl                                use SSL via Let's Encrypt
--verbose                            enable verbose output
--final FINAL                        final url the user is redirected to after phishing is done
--hostname HOSTNAME          hostname for SSL

 

If you choose to monitor phished credentials without using the built-in API, there are two files you should be familiar with:

Temporary cached credentials

.cache : The cache file provides an intermediate aggregation of credentials that pass through the username and password phase of the phish. Originally designed to temporarily store credentials when two-factor is enabled, it was to prevent a loss of credentials in the event a target doesn’t complete the two-factor step.

Phished credentials

.sniped : The sniped file provides a flat-file storage of captured credentials along with other information like two-factor information, IP address, and geolocation information. In some cases, if you authenticate with credentials from a new location to sites like Gmail, they will prompt you to supply the last location you authenticated from. By grabbing the IP address of the phished target and quickly geolocating them, you can supply an accurate answer.

Cloning Pages

While the only built-in module that has been made public is Gmail, there is also an example module in the modules/ directory that will help you quickly create new modules. In order to quickly clone a page, I tend to start by using a FireFox plugin called ‘Save Page WE’ which will conveniently embed external resources internally in a single HTML page. This makes it convenient and avoids loading embedding resources hosted by the cloned website, hopefully removing any call-backs that CredSniper might have accidentally made. Be sure to follow the example module HTML templates in order to include the correct templating parameters. Stay tuned for a future blog post on how to clone pages for CredSniper or check out our Tradecraft Security Weekly video “Phishing 2FA Tokens with CredSniper” on YouTube.

The concept is fairly straightforward, for every page you are trying to clone you will need a new template. The new template will be loaded from your module and triggered by a route within CredSniper. Without getting into the weeds here, the module is loaded by CredSniper and each route will be auto-added to the built-in web server. Each route is assigned a function within the module and it’s the responsibility of the module to load the template. If your HTML template is in the modules/module/templates/ directory and contains the proper {{template}} language, CredSniper will automatically replace the templating language with the correct value. With some sites like Gmail, there are multiple pages. Consider the lifecycle of the authentication process:

  1. A user supplies an email address, Google verifies the account
    1. If not valid, lets the user know the email is invalid
    2. If valid, continues
  1. A user password is requested by Google
    1. If not valid, let’s the user know the password is invalid
    2. If valid and 2FA not active, redirects to GSuite
    3. If valid and 2FA active, continues
  1. A 2FA token is requested by Google, this is driven from the default user enrollment
    1. If SMS, triggers text message to user with code
    2. If Authenticator, prompts for OTP code
    3. If Yubikey, prompts to insert and activate U2F device
    4. If Touch prompt, prompts user to touch phone
    5. If user-agent reflects unknown browser, prompts for SMS 🙂
    6. If valid token, redirects to GSuite
    7. If valid token but suspicious context, prompt for additional information

The way CredSniper handles all of this is straightforward:

  1. Prompt user for email
    1. Load profile image using email behind the scenes using Google’s Picaso service
  1. Prompt user for password
    1. Authenticate behind the scenes with the email and password then identify if 2FA is enabled.
    2. If 2FA is enabled, capture additional information (i.e. last few digits of SMS, OTP app name (Duo/Authenticator/etc), IP address, geolocation
    3. If 2FA is disabled, redirect to final destination URL configured in CredSniper
  1. Prompt user for 2FA token
    1. Redirect to final destination URL 🙂

Check out an example phishing workflow:

Final Thoughts

CredSniper has been an enormous success for our engagements at Black Hills and we have received lots of great feedback from users. I wanted to take a second and also shine some light on another great tool called evilginx2 by a friend named Kuba Gretzky. Evilginx2 will proxy connections between the target and phished website then intercept credentials and two-factor tokens by hosting it’s own HTTP and DNS server. If CredSniper isn’t what you are looking for, I strongly suggest giving evilginx2 a try.