Josh Lospinoso home posts about
Defeating PoisonTaps and other Rogue Network Adapters with Beamgun November 30, 2016
New and improved Beamgun now defends against USB network adapters and mass storage!

Over the past few months, security researchers like Rob Fuller and Samy Kamkar have been exploring vulnerabilities associated with the implicit trust Windows gives to USB network adapters. Wielding devices like the USB Armory, the LAN Turtle, and even the $5 Raspberry Pi Zero, Rob and Samy have demonstrated how simply inserting one of these rogue USB devices into a Windows machine–whether it’s locked or not–can affect serious compromise of logged in users, including:

  • storing HTTP cookies and sessions,
  • persistence to an attacker as an internal router,
  • gives persistent HTTP cache poisoning,
  • forcing the user to make HTTP requests and proxy back responses

Aside from logging out of a computer each time you step away or epoxy-gluing your USB ports shut, there aren’t very many good options for mitigating against this kind of attack.

Beamgun

Last month I released Beamgun, an open-source Windows application that mitigates against another kind of rogue USB device, the USB Rubber Ducky. In principle, both of these devices rely on the implicit trust Windows gives to physical machine access. With the Ducky, Windows gives full trust to a newly-inserted USB keyboard. The Ducky then blasts the target computer with a rapid volley of pre-programmed keystrokes (you can imagine how bad that is). Windows administrators are not able to disable USB devices without physically disabling ports (note that you are able to disable USB mass storage–more on that later).

I replaced the Win32-API-based RegisterDeviceNotification approach with Windows Management Instrumentation approach. We first construct a WqlEventQuery:

var keyboardQuery = new WqlEventQuery("__InstanceCreationEvent", new TimeSpan(0, 0, 1),
  "TargetInstance isa \"Win32_Keyboard\"");

and then we pass this query to a ManagementEventWatcher:

_watcher = new ManagementEventWatcher(keyboardQuery);

This new _watcher has an EventArrived event handler where we can register arbitrary callbacks. A major improvement to the WMI approach is that we only get callbacks for keyboards rather than all USB devices! The upshot of this is that there are far fewer false-positives. Before, Beamgun would alert on any USB device, now it’s just keyboards.

Ok, ok, but what about PoisonTap?!

Registering for new network adapters (as in ALL network adapters, not just USB!) is as simple as changing the WQL to our new target:

var networkQuery = new WqlEventQuery("__InstanceCreationEvent", new TimeSpan(0, 0, 1),
  "TargetInstance isa \"Win32_NetworkAdapter\"");

The new challenger here is that just locking the workstation is no longer a sufficient mitigation. With rogue keyboard devices, locking the workstation blocks the attack (unless the attacker knows your password). PoisonTap is a particularly nasty attack because it can work even when your computer is locked.

Fortunately, we can disable the new network adapter immediately upon receiving notification via WMI:

_watcher.EventArrived += (caller, args) => {
  var obj = (ManagementBaseObject)args.NewEvent["TargetInstance"];
  var query = $"SELECT * FROM Win32_NetworkAdapter WHERE DeviceID = \"{obj["DeviceID"]}\"";
  var searcher = new ManagementObjectSearcher(query);
  foreach (var item in searcher.Get())
  {
      var managementObject = (ManagementObject)item;
      try
      {
          var disableCode = (uint)managementObject.InvokeMethod("Disable", null);
          // ...
          return;
      }
      catch (ManagementException e)
      {
          // ...
      }
  }
};

So again, while we cannot tell Windows to block these new devices explicitly, we can listen for the new devices with callbacks and take action when they are detected.

USB Mass Storage Devices

Things can get particularly crappy for the target when an attacker adds storage into the mix. Darren Kitchen recently demonstrated some methods for slurping files directly off a target with the USB Rubber Ducky. This kind of attack completely bypasses any kind of firewall/perimeter monitoring that may be in place. All of the document stealing happens right on the spot.

Supposing that Beamgun’s workstation lock was evaded somehow, there’s an added layer of protection we can add basically for free. The one USB policy that Windows does support is to disable USB Mass Storage devices with the following registry key:

HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbstor\\Start

If it’s set to three, USB is enabled–four, and it’s disabled. You can even set it with group policy. Since it’s just tweaking a registry entry, I’ve added it to Beamgun as an option. Hey–it’s the one rogue-USB-device-mitigation that Windows actually ships with, so why not use it?

Updates

Beamgun can now check to see if new versions have been released by periodically polling

https://s3.amazonaws.com/net.lospi.beamgun/version.json

If it finds it’s out of date, it will write a friendly message into the log. If you don’t want this, just set this registry entry to “False”:

HKEY_CURRENT_USER\\SOFTWARE\\Beamgun\\CheckForUpdates

Installing Beamgun

You can get links to install beamgun, clone the repo, etc. at https://github.com/JLospinoso/beamgun.

Feedback

Please post any issues or bugs you find!

Defeating the USB Rubber Ducky with Beamgun November 15, 2016
Introducing Beamgun, a lightweight USB Rubber Ducky defeat for Windows

The USB Rubber Ducky is an awesome little piece of infosec goodness put together by the venerable hackers at HAK5. Ever since it was popularized on Mr. Robot, I’ve wanted to write some software to mitigate the vulnerability:

15 Second Password Hack, Mr. Robot Style

Basically, this little USB device registers itself as a keyboard, waits a bit, then blasts the victim’s computer with a flurry of keystrokes at super-human speed. This requires an active session (i.e. the user is logged in), although obviously the computer need not be unattended.

The possible effects of this attack are devastating. Generally it is trivial to elevate privileges to administrator (since you’re emulating a user typing), so you can install whatever kind of malware you’d like, pull larger scripts down from a remote server, or worse.

What, you ask, can men do against such reckless hate?

Reckless

Install Beamgun!

Beamgun Infographic

You can download and install Beamgun using the simple instructions on Github.

Using Beamgun

Beamgun shows up in the system tray whenever you run BeamgunApp.exe. If you install using the MSI installer, this will happen whenever you login. You can click on the icon to view the application’s status:

Beamgun Screenshot

From here, you can disable Beamgun, e.g. if you are about to insert and remove USB devices frequently, for the next 30 minutes. You can also “Reset” Beamgun if it has alerted, and finally you can force Beamgun to quit by clicking “Exit”.

You can also configure the security settings for Beamgun using the two check boxes. I recommend checking both boxes to get the benefits of both mitigations. Whenever beamgun detects a USB device, it will only execute the mitigations you have checked. If you check “Attempt to steal”, Beamgun will attempt to steal all of the keystrokes and sink them harmlessly into its window. If you check “Lock workstation”, Beamgun will tell Windows to lock, forcing you to type your password in to continue.

Beamgun Internals

There are a few important Win32 API calls that enable us to do the following:

  • monitor for keyboard device insertions so we can alert,
  • hook keystrokes so we can see what the attacker tried to do,
  • continuously steal keyboard focus to stop the attacker from making progress, and ultimately
  • lock the workstation.

Device insertions

The Win32 API gives us the following functions for getting device notifications:

HDEVNOTIFY WINAPI RegisterDeviceNotification(
  _In_ HANDLE hRecipient,
  _In_ LPVOID NotificationFilter,
  _In_ DWORD  Flags
);

BOOL WINAPI UnregisterDeviceNotification(
  _In_ HDEVNOTIFY Handle
);

Basically, we’re telling Windows that we’d like to get notified about device insertions, and we pass off a handle to our main window. When device-related events happen, Windows alerts us and stuffs a 2-byte code into our callback function to tell us what kind of event it was. See UsbMonitor.cs in the Model section of BeamgunApp for the code that implements all of this.

Hook keystrokes

Next, we’d like to hook keystrokes so that when we alert on a USB device insertion, we can record what the attacker was trying to do and present it to the user.

For this, we turn to the tried and true Windows Hooks APIs:

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);

BOOL WINAPI UnhookWindowsHookEx(
  _In_ HHOOK hhk
);

Use of these functions is well documented. We’re just using them for good-guy purposes. See KeyStrokeHooker.cs for my implementation (again in Model of BeamgunApp).

Steal focus continuously

I chose Windows Presentation Foundation to build Beamgun, so I used WPF APIs to steal focus:

public static IInputElement Focus(
	IInputElement element
)

The real trick is getting it to run in the thread that’s responsible for the window. This can be done with Dispatcher.Invoke, as in the following snippet:

viewModel.StealFocus += () => Dispatcher.Invoke(new MethodInvoker(delegate
{
    Show();
    Activate();
    Topmost = true;
    Keyboard.Focus(this);
}));

Here I also call the functions Show() and Activate() before stealing keyboard focus. This ensures that the Beamgun alert window pops up for the user to see. See the code-behind in MainWindow.xaml.cs of BeamgunApp for more details.

Lock the workstation

As another (potentially more robust) option, the user can elect to lock the workstation whenever a USB insertion happens. This is safe because we are piggy-backing off the safety mechanisms built into the login screen, e.g. the local security authority subsystem service. The Win32 API for locking the screen is as straightforward as it gets:

BOOL WINAPI LockWorkStation(void);

Special considerations

Since the Rubber Ducky is a keyboard device, I had to be very careful in implementing Beamgun to try to thwart some countermeasures. I’m sure that some enterprising Rubber Ducky fans will try hard to subvert Beamgun, so I hardened the following features:

  • Disabling ALT-F4
  • Using custom buttons that do not respond to keyboard events
  • Stealing focus on a loop with a very tight interval

Feedback

Please post any issues or bugs you find!

Setting Up a Matterbot with Slack via ngrok October 14, 2016
Running a Matterbot on Slack with ngrok

When matterbot was introduced, we configured it to work with an instance of Mattermost that we hosted. In this post, we’ll get it working with Slack, which will already hosted be for us. The major challenge is that your bot may not be routable from Slack’s servers (i.e. the internet). If you are behind a firewall, NATed behind a router, etc., you will be able to POST messages into chatrooms via incoming webhooks but you won’t receive messages from Slack when people try to trigger your bot. ngrok is a beautiful solution for situations like this. After signing up and downloading a client, you’ll get a subdomain that will tunnel traffic to you (even if you aren’t routable!)

ngrok

Setting up an account with ngrok is simple and free. Just follow the instructions, then download the client. I put the client binary on my PATH so that I can invoke it from anywhere in my command prompt (I suggest that you do the same).

Once you’ve signed up for an account and you’ve downloaded the client, you’ll need to install your authtoken (this will be available from your dashboard.) Just run ngrok with the issued token:

ngrok authtoken THISISMYSECRETTOKEN123ABC

Now, you’ll be able to expose any local port you’d like to the internet (be careful!) We are about to bind Matterbot to local port 8000, so all you need to do is issue the command

ngrok http 8000

You’ll end up with some output that looks like this:

ngrok by @inconshreveable                  (Ctrl+C to quit)

Session Status                online
Account                       Josh Lospinoso (Plan: Free)
Version                       2.1.14
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://88319c22.ngrok.io -> localhost:8000
Forwarding                    https://88319c22.ngrok.io -> localhost:8000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

You can navigate to http://127.0.0.1:4040 in your browser, and you’ll be able to interact with ngrok through a nice web app. Notice that you’ve now got an internet-routable domain that is mapped to a local port on your machine! In my case, it’s http://88319c22.ngrok.io.

Unless you have a paid plan with ngrok, this subdomain will change whenever you restart ngrok. Keep this in mind as you’re developing!

Slack

Now, sign up for a Slack account. You’ll need administrative privileges to enable webhooks for Matterbot, so create a new team (or continue along with a team that you have administrative privileges for).

  1. From the team homepage, click the top-right icon to get into the drop-down menu.
  2. Select “Apps & Integrations”. Alternatively, just point your browser to https://MY-TEAM-NAME.slack.com/apps where MY-TEAM-NAME is the appropriate subdomain.
  3. In the search bar, type “Incoming WebHooks” and click on the Incoming WebHooks icon when it pops up.
  4. Click on “Add Configuration”
  5. Choose the channel you’d like the Matterbot to interact with in the drop-down menu.
  6. Click on “Add Incoming WebHooks integration.”
  7. Surf right over all the setup instructions (Matterbot will handle all of these details for you!) Save the “Webhook URL”. You’ll need this when setting up your Matterbot.
  8. Optionally, you can give your bot a descriptive label, customize its name, give it a custom icon, etc.
  9. When you’re done customizing your bot, click on “Save Settings.”

We are going to follow a similar pattern for the Outgoing WebHooks; go back to the “Apps & Integrations” search, and continue: 10. In the search bar, type “Outgoing WebHooks” and click on the Outgoing WebHooks icon when it pops up. 11. Click on “Add Outgoing WebHooks Configuration” 12. Choose the channel you’d like the Matterbot to interact with in the drop-down menu. This should match the channel you selected for Incoming WebHooks. 13. As in the Mattermost case, you’ll need to choose some trigger words that your bot will respond to. Put these in the “Trigger Word(s)” textbox and separate them with a comma. 14. In the “URL(s)” box, put your internet-routable ngrok URL. In my case, it is https://88319c22.ngrok.io. Note again that if you restart ngrok on your machine, you will need to change the settings of your Outgoing WebHooks! 15. Save the “Token”. You’ll need this when setting up your Matterbot. 8. Optionally, you can give your bot a descriptive label, customize its name, give it a custom icon, etc. 9. When you’re done customizing your bot, click on “Save Settings.”

Matterbot

You are now ready to build Matterbot and wire it into Slack. Pull down the latest version from github:

git clone git@github.com:JLospinoso/matterbot.git

Open matterbot/Matterbot.sln in Visual Studio. In the MatterbotSample project, open main.cpp in Source Files. You’ll notice several TODO sections to fill in. The only requirement to get things up and running is to paste your routes and tokens:

//TODO: Put your own routes and tokens here
wstring mattermost_url = L"https://hooks.slack.com", // URL to the incoming webhook for Mattermost/Slack
  incoming_hook_route = L"services/AAAAAAAAA/BBBBBBBBB/CCCCCCCCCCCCCCCCCCCCCCCC", // Route
  outgoing_hook_route = L"http://127.0.0.1:8000/", // URL of the box running matterbot
  outgoing_hook_token = L"CCCCCCCCCCCCCCCCCCCCCCCC";

Take the route portion of the URL you copied when setting up your Incoming WebHooks and put this into the incoming_hook_route variable. Put your Outgoing WebHook token into outgoing_hook_token. If you set up ngrok to listen on :8000 then you are all set. If not, modify outgoing_hook_route to bind to the correct port.

Testing

Navigate to the slack channel that you’ve configured Matterbot to interact with. Using your trigger word for the bot (mine is matterbot), broadcast this message into the channel:

matterbot help

If all is well, you should receive a helpful message from your bot telling you that it supports the echo command. You can follow up by issuing an echo:

matterbot echo Hello, world!

Your matterbot should echo the given message back to you.

See the original post on Matterbot to see how to write your own functionality into the bot!

Feedback

Please post any issues or bugs you find!

Fork me on GitHub