The Lab – Gear Check – Hak5 Bash Bunny – Serial

The last attack mode we haven’t covered is the SERIAL mode. This mode presents a serial device to the “victim” machine, which can be connected to via any standard serial console software tool. On Windows machines, PuTTY can handle serial connections. For Unix and Linux systems, a variety of options exist including the traditional “cu” and “tip” command line programs, “screen” (the tool used in Hak5 examples,) “kermit,” “minicom,” and so on. If you have a tool you’re comfortable with, you might stick a statically compiled version of it onto the drive and access it via the STORAGE mode using a HID mode control mechanism, perhaps.

There isn’t as much use for this, given the complexity it presents, except where the network is blocked by some kind of corporate software control, but serial is not. It seems more like a niche attack vector, but it’s better to have it available than not.

As you should be aware if you have experience connecting to serial consoles, a serial connection has some control setting that need to be set correctly before a serial session can be reliably established. The settings for the Bash Bunny’s serial session are as follows:

Baud Rate: 115200
Data Bits: 8
Parity Bit: No
Stop Bit: 1

This is often abbreviated as 115200/8N1 for some serial console software.

Again, it is almost always going to be easier to just use one of the network based attack modes, and ssh to the Bunny using plink (Windows) or openssh (Unix/Linux.)

Sudo Policy Fixes and Fails – The Cmnd Alias

So we’ve covered the User_Alias, Host_Alias, and Runas_Alias labels up to this point.  Today, we’re going to cover the Cmnd_Alias label.  This one takes a comma separated list of commands that the policy will allow.  It can contain defaults overrides, TAGs, command flags, and command arguments.  It can use special keywords in place of commands.  It is the most complex label in the policy, and it is critical to get this “right” if you don’t want to accidentally grant more privilege than you intended.

Most of our examples (after we go over the Defaults in detail) will be identifying problem policies, and most of those problems will relate to this label.

To define the label as an alias, we use the Cmnd_Alias entry like so:

Cmnd_Alias C_DOSTUFF = /usr/bin/stuff

This would grant policy to call the command “/usr/bin/stuff” (or just “stuff” if /usr/bin is in the PATH environment variable,) without restricting the flags or arguments that can be passed to it.  If we want to force it to never allow any arguments, we can change the policy like this:

Cmnd_Alias C_DOSTUFF = /usr/bin/stuff ""

This tells the policy to make the argument list “empty,” which means “no arguments are allowed.”   We can similarly restrict the flags that may be passed.

Cmnd_Alias C_DOSTUFF = /usr/bin/stuff [!-]* ""

This is the place where it is important to remember that “whitelisting” is the way to go.  Trying to “blacklist” often leads to heartache and pain killers.  The biggest example of a failed “blacklist” mentality is this:

Cmnd_Alias SHELLS = /bin/bash, /usr/bin/ksh, /bin/zsh
Cmnd_Alias SU = /bin/su
Cmnd_Alias C_BABYADMIN=ALL, !SU, !SHELLS

This is even mentioned in the man page, and yet, it is seen in the wild all too often.  This command appears to say “the user can run any command except the listed shells or su.”  However, by being able to run any command, the user is able to make a copy of any of the shells under a different name, and then use sudo to execute them.  This does not work the way people seem to think it does.  Even the man page has a “valid” entry that is dangerous.  The “valid” example it provides is this:

jill SERVERS = /usr/bin/, !SU, !SHELLS

On the surface, it looks like “jill” can execute anything within “/usr/bin” except the SU and SHELLS commands.  Since “cp” and “mv” and the like are in “/bin” but not “/usr/bin” on many systems, this looks like it might work, right?  Here’s the problem.  The “at” command often resides in “/usr/bin” so something as simple as this could be used to also bypass this problem:

echo "cp -p /bin/bash /usr/bin/myshell" | sudo at now

This is why it is always better to whitelist as much as possible, not give any kind of “blanket” policy with dumbed down “blacklist-like” restrictions.  My preference when dealing with Cmnd_Alias issues is to have the user write a script, (or write one for them) that handles the exact command that will need privileged access, then make that be owned by root and not writable by anyone.  Grant sudo policy to that script, instead.  You can control what flags are always passed, what arguments are always passed, and so on, if you do it this way.

We won’t look at the “Defaults” overrides this week, since we’re going to being covering Defaults next week, but we will look at the TAGs again.

So the defined TAGs are listed below.  The log related ones will be covered when we go over the Defaults, but I’ll list them, anyway.

PASSWD: | NOPASSWD:  -  Force a user to authenticate, or don't force authentication for this command.
EXEC: | NOEXEC:  -  Allow or attempt to prevent the command from forking a child process.
SETENV: | NOSETENV:  -  Override the value of the "setenv" Default on a per-command basis.
LOG_INPUT: | NOLOG_INPUT:  -  Override the value of the "log_input" Default on a per-command basis.
LOG_OUTPUT: | NOLOG_OUTPUT:  -  Override the value of the "log_output" Default on a per-command basis.

Remember that the “NOEXEC:” TAG only works if the binary was compiled as a shared object binary.  Statically compiled programs (such as “ed”) will not be blocked by this hooking mechanism.  This is why the special “sudoedit” command entry is recommended for any kind of file editing situation.  We covered this here.

I know this was a lot, but it’s not nearly enough.  We’ll go into more detail as we rip apart “bad sudo” policy examples later on.  Before we get to that, though, we need to look at the Defaults, and we’ll begin that next week.

Fun-Day Friday – Book Review – Networking for Systems Administrators chapter 2

Chapter 2 focuses specifically on how Ethernet works.

From defining broadcast domains to dealing with ethernet frame MAC addressing, he begins with the foundational basics.  He talks about duplex and speed for negotiating the connection, which both sides of the link need to agree upon.

He explains MTU (maximum transmission unit) and why mucking with reducing it below the default is almost certainly going to be problematic.  He also suggests ways to deal with situations where you can’t help but do so.

Lucas follows up with a quick explanation about the differences in category numbering for the wires that handle the transmissions.  The higher the number, the better, but higher costs can be prohibitive.  Work with what you can, but plan for higher when you can.

He moves into a quick explanation for using several troubleshooting tools, such as ping, arp, and “neighborhood discovery” (ND.)

Finally, he covers Virtual LANs (VLANs) to add a tag to an Ethernet Frame.  This allows traffic for multiple networks to flow over a single cable, without confusing where the packet should go.

He sprinkles in some more troubleshooting tools such as netstat, as well as tools to configure the ethernet layer (ifconfig and ethtool,) before closing the chapter out.

This chapter is important for the fundamentals of the “Data Link” layer (and to some extent the Physical Layer.)  Next week’s chapter covers “Layer 3” (Network Layer.)  This is mostly the “IP” layer in “TCP/IP” terms.

Thanks for reading!

The Lab – Gear Check – Hak5 Bash Bunny – Network

There are two different network attack modes that come with the Bash Bunny.  Only one of these should be used at a time, since they conflict.  The difference is the type of device it presents when active.

ECM_ETHERNET presents an Ethernet Control Model device, which is more useful when the target is Linux, Mac, or Android.  Probably other unix like systems, but testing will vet this out.

RNDIS_ETHERNET presents a Remote Network Driver Interface Specification device.  This is more useful on Windows, but will work on some Linux distributions.

Both of these present a gigabit false network to the “victim” machine, complete with DHCP server which serves up an IP in the 172.16.64.10 to 172.16.64.12 range.  The IP address of the Bunny itself will be 172.16.64.1 to act as a gateway device.  Presenting this fake network is much like the connection you get from plugging a LAN Turtle into that USB port.  The LAN turtle presents a network, whether it bridges through to a plugged in RJ45 connection or not.  The Bash Bunny’s fake network is faster, however.

If you’re intended attack does not need to be connected to an actual network, the Bash Bunny will likely be a superior option.  If it needs to act as a man in the middle bridged network, the LAN Turtle is the superior option.  You can still tie networking in a host shared internet setup with the Bash Bunny, and instructions are provided to do so, but this requires a bit more work to get set up correctly.  To do this “manually” might take some time.  Of course, you could possibly combine attack modes and use a Ducky script to run some of the commands needed to set this up, as well.

You can connect to the Bash Bunny with SSH while it is in one of these two network attack modes.  The default root password is “hak5bunny” and root is able to do direct SSH login.  This is probably easier to use than the SERIAL mode we will cover next week.

Sudo Policy Fixes and Fails – The Runas Alias

Continuing our Sudo policy series, we’re going to focus on the Runas_Alias label this week.  In many regards, this looks much like the User_Alias in that it takes users and groups and the syntax is the same.

However, its purpose is much different.  Where the User_Alias identifies who CAN run this policy entry, the Runas_Alias defines which users and groups the policy may be executed under.

The typical default entry for this (much like the Host_Alias label) is “ALL” which allows the command to be executed under any user or group identified by the calling user.

Typical sudo calls look like this:

sudo my_command

This defaults to calling “my_command” as the root user.  The policy probably had “(ALL)” as the Runas_Alias label, as mentioned above.  We don’t always want to let a user run a command as root, though.  Sometimes we want to allow one user to call a command as another non privileged user, just because that process belongs to that user.  To do this, we set a Runas_Alias label that restricts the command to being executed under that user, not root, and not “ALL.”

With such a policy in place, the user has to know how to call sudo to execute under someone other than the default “root” user.  The “-u” flag allows this.

sudo -u otheruser my_command

Sometimes, we also need to call the command as a different group.  In order to do this, we can pass the “-g” flag.  A combination of both is valid.

sudo -u otheruser -g othergroup my_command

This allows for more granular control over the policies being written, and enforces safe policy that doesn’t grant access to root except when absolutely necessary.

This is the end goal of any good policy.  Only allow what is strictly necessary, and nothing more than that.

Fun-Day Friday – Book Review – Networking for Systems Administrators chapter 1

Continuing our review of “Networking for Systems Administrators” by Michael W. Lucas, we’ll roll right into Chapter 1.

This chapter focuses on thinking in layers.  There are different network layer models, including the 7 layer OSI model, but Lucas says you really only need 5 layers to represent the network.  There’s the 4 layers of the TCP/IP model, but he splits the lowest layer into the Physical and DataLink layers.  This matches the OSI model’s way of presenting those layers.

The OSI Session, Presentation, and Application layers are all lumped under the TCP/IP “Application Layer.”  Lucas calls this the “your stuff” layer, and it’s true.  The Network Admins won’t really care much beyond the Transport Layer when troubleshooting.

Speaking of troubleshooting, identifying the lowest layer that is broken is crucial for this.  Fix that layer first, and most (if not all) of the other layers will likely start working again.  And those that don’t, go with the next lowest layer, and work your way up.

The rest of the chapter covers specific troubleshooting techniques for each of the lower layers, with a promise for more in depth troubleshooting discussion later in the book.

This chapter is short, but critical for laying the ground work.  Understanding these layers is one of the most important things to know for network troubleshooting.

The Lab – Gear Check – Hak5 Bash Bunny – Storage

Sorry for the late edition.  I got my days mixed up, yesterday.  This week had two Mondays in it, as far as my brain could tell.  I got the short end of the stick on that.

This week, we’re going very quickly look at the “STORAGE” Attack Mode on the Bash Bunny.

This is what it looks like when I plug my Bash Bunny into a Linux Mint 17 laptop:

[ 4966.425800] usb 3-1: new high-speed USB device number 2 using xhci_hcd
[ 4966.444695] usb 3-1: New USB device found, idVendor=f000, idProduct=fff0
[ 4966.444707] usb 3-1: New USB device strings: Mfr=2, Product=3, SerialNumber=7
[ 4966.444713] usb 3-1: Product: RNDIS/Ethernet Gadget
[ 4966.444718] usb 3-1: Manufacturer: Linux 3.4.39 with sunxi_usb_udc
[ 4966.444722] usb 3-1: SerialNumber: ch000001
[ 4966.615123] cdc_acm 3-1:2.0: This device cannot do calls on its own. It is not a modem.
[ 4966.615169] cdc_acm 3-1:2.0: ttyACM0: USB ACM device
[ 4966.615800] usbcore: registered new interface driver cdc_acm
[ 4966.615802] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[ 4966.618621] usb-storage 3-1:2.2: USB Mass Storage device detected
[ 4966.618795] scsi6 : usb-storage 3-1:2.2
[ 4966.618891] usbcore: registered new interface driver usb-storage
[ 4971.629404] scsi 6:0:0:0: Direct-Access                               0000 PQ: 0 ANSI: 2
[ 4971.629670] sd 6:0:0:0: Attached scsi generic sg2 type 0
[ 4971.630115] sd 6:0:0:0: [sdb] 4194304 512-byte logical blocks: (2.14 GB/2.00 GiB)
[ 4971.630264] sd 6:0:0:0: [sdb] Write Protect is off
[ 4971.630266] sd 6:0:0:0: [sdb] Mode Sense: 0f 00 00 00
[ 4971.630405] sd 6:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn’t support DPO or FUA
[ 4971.631847]  sdb:
[ 4971.632512] sd 6:0:0:0: [sdb] Attached SCSI removable disk
[ 4973.119396] FAT-fs (sdb): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.

When we put a payload into Attack Mode STORAGE, the drive presents a 2G drive to the system.  This looks just like the drive that gets presented when plugging the Bash Bunny in via Arming Mode.

This is useful for some attacks, such as what the TwinDuck firmware the USB Rubber Ducky provides, where we use both STORAGE and HID Attack Modes, then use Ducky commands to bring up a command prompt of some sort, type some commands to figure out where our drive is at, and drop files to that location.  This kind of attack is becoming less useful with corporate policies that prevent the use of USB thumb drives, these days, but the Bunny has another way to do this same kind of thing.  We’ll look at that next week when we introduce the networked attack modes.

Sudo Policy Fixes and Fails – The Host_Alias

Last week we looked at the User_Alias label.  This week, we’re going to look at the Host_Alias label.  Within a policy line, the “Host_Alias” is the next section of that policy.  This dictates on which systems/servers this policy will be allowed to run.

When the policy is unique to each server, is not maintained as a centralized monolithic structure that gets shared out to all end points, or isn’t stored in a database such as LDAP, the usual default is the “ALL” entry.  This simplifies figuring out which items to put here for a given server.  It may seem like that answer is simple, but in reality, it’s not, due to the way sudo checks the host when called to execute a policy request.

What do I mean by that?  The below snippet from the sudoers man page addresses this better than my own words ever could.

A Host_List is made up of one or more host names, IP addresses, network numbers, netgroups (prefixed with ‘+’) and other aliases.

If you do not specify a netmask along with the network number, sudo will query each of the local host's network interfaces and, if the network number corresponds to one of the hosts's network interfaces, the corresponding netmask will be used.  The netmask may be specified either in standard IP address notation (e.g. 255.255.255.0 or ffff:ffff:ffff:ffff::), or CIDR notation (number of bits, e.g. 24 or 64).  A host name may include shell-style wildcards (see the Wildcards section below), but unless the host name command on your machine returns the fully qualified host name, you'll need to use the fqdn option for wildcards to be useful.  Note that sudo only inspects actual network interfaces; this means that IP address 127.0.0.1 (localhost) will never match.  Also, the host name “localhost” will only match if that is the actual host name, which is usually only the case for non-networked systems.

As you can see, there is some reliance upon what the “host name” command returns, whether an IP is ever checked based on the actual network interfaces configured, and so on.  The loopback interface is never checked.  It is recommended to create a test policy with different Host_Alias entries that LOOK like they should work before making any assumptions about how your policy will actually behave once installed.  If you frequently change the IP address(es) of your systems, a host name is preferred.  If you change the name frequently, such as during a migration or similar, setting policy by IP might be better for your environment.  Or maybe the name is better, and you include the name change inside your distributed monolithic policy file, or LDAP entry, or what have you.  In the end, you need to figure out what will work best for your environment and be consistent with how you handle things.  It doesn’t hurt to use both host name and IP in a policy, so you can set your alias label for either, or both.

Also, you can do negation with this just as you can with User_Alias entries.  You could say “ALL, !www.example.com” to make this apply to any system that isn’t “www.example.com” (for example.)

The Host_Alias label is less important to change from the almighty “ALL” if you aren’t doing some kind of distributed shared policy, but if you get to more than a few end point servers that are not identical use case machines, you will eventually want to consider such a move.  This is why it is important to learn how the Host_Alias actually behaves for policy on each machine, and test your policy to be sure it does what you expect.

Next week we’ll cover Runas_Alias, as it is the next section of a policy line.

Thanks for reading!

The Lab – Gearcheck – Hak5 Bash Bunny – Ducky Mode

The Bash Bunny is a versatile USB tool.  It comes with several “Attack Modes” which actually are instructions to enable certain devices it should present to the “victim” machine.

The “Attack Modes” are SERIAL, ECM_ETHERNET, RNDIS_ETHERNET, STORAGE, and HID.  Today, we’re going to look specifically at the “HID” type.

Since the Bash Bunny expects a payload in order to perform its duties, we need to create a payload file.  This will be a file actually named “payload.txt” located in one of the switch directories under the payloads directory of the device.

In order to play with this, we’ll present two different payload files that do essentially the same thing, but will identify which switch folder the payload came from.  This will let us validate that the switch positions labeled by the documentation match the “switch” folder name on the device itself.

Our first payload will be located under the “switch1” folder, and our second under the “switch2” folder.  The payloads are below.

#Payload1 = switch1/payload.txt
ATTACKMODE HID
QUACK STRING I am on switch one!

#Payload2 = switch2/payload.txt
ATTACKMODE HID
QUACK STRING I am on switch two
!

After saving both of these, we can unplug the Bash Bunny, click the switch one notch (to the documented “switch2” position,) bring up a notepad or other scratch space typing field, and plug it back in.  We wait a few seconds for the Bunny to initialize/boot, and then we see “I am on switch two!” as we expect to see.

Unplug, click the switch one more notch (to the documented “switch1” position,) and do the same wait for boot, and finally we get “I am on switch one!” as we expected.

If we have a more elaborate DUCKY script we would like to use, we can put that into a file to itself, and change our “QUACK” command to call that file.

#Ducky Script1 = switch1/ducky_payload.txt
#Payload1 = switch1/payload.txt
ATTACKMODE HID
QUACK ducky_payload.txt

#Ducky Script2 = switch2/ducky_payload.txt
#Payload2 = switch2/payload.txt
ATTACKMODE HID
QUACK switch2/ducky_payload.txt

In the examples above, the first payload does not work, but the second payload, does.  This means the “switch#/<filename>” format is necessary in order to load that DUCKY script file.  These are things that need to be considered when working with the Bunny payloads.

These example payloads just mimic the USB Rubber Ducky at this point.  The LED wasn’t manipulated in these examples.  There is no feedback other than the keyboard, and we didn’t utilize any other devices.  The wait time to boot makes this a poor choice when speed is of the essence, so this definitely does not replace the USB Rubber Ducky for straight up HID attacks.  It does, however, provide the ability to produce more feedback (by way of blinking/solid/different colors on the LED) as well as the ability to carry two different payloads without having to “reload” the device by updating the “inject.bin” file in between.  It is easier to use, since the DUCKY script doesn’t have to be converted into an “inject.bin” to begin with.  Once we throw in some other Attack Modes, we’ll be able to do some more elaborate payloads to carry out our needs.

It also has some flexibility in that you can use  “QUACK STRING” followed by a “bash” variable, or a command, in order to see output from such.  You could use this functionality to use a network based attack mode to generate a “loot” file, then follow it up with a HID attack mode to pull up a text editor, and type the contents of the “loot” file for immediate display, if you so desired.

#Ducky Script2 = switch2/ducky_payload.txt
#Payload2 = switch2/payload.txt
ATTACKMODE HID
QUACK STRING $( ls /root/udisk )

One caveat with this is that using “QUACK” with any combination of “switch” followed by “.txt” (no matter what the characters are in between) causes it to NOT display that string.  It seems like a bug, since “QUACK STRING” shouldn’t care what comes after it, but “QUACK switch1/<filename.txt>” matters for loading from a file.  I think it should do a “QUACK STRING” check before it does any decision making on whether to try to load a file, and if it’s not “STRING” then consider the file name from there, but I haven’t looked at the code (if it’s available) to see if there’s an easy fix to offer.

Next week, we’ll look at the STORAGE Attack Mode.

Sudo Policy Fixes and Fails – The User Alias

We covered this on a very basic level last week, but today we’re going to focus on the User_Alias policy entries.

A sudo policy begins with a list of users and/or groups.  This list can be a raw listing, or it can be a label created by a “User_Alias” entry.  Organization of the policy file depends on your needs, but one common way to organize things is to use the aliases to define how pieces of a policy should look, then put all of the policies at the bottom where the alias labels are used to build out those policies.  There are other ways to structure this, as well, and we’ll cover several of them later.  For now, we’ll assume that we are doing one section of the file to cover all User_Alias entries, another section for all Cmnd_Alias entries, and so on.

A User_Alias entry is simply the key word “User_Alias” followed by the label name you would like to use, and equal sign “=” and the list of users and/or groups, comma separated, that the labeled alias will define.

User_Alias U_WEBADMINS = %webslingers

If you want to allow a group, but restrict one member of the group from having the access to the policy, you can modify it like so:

User_Alias U_WEBADMINS = %webslingers, !venom

Less useful in most situations, but still available as an option, is to use UID and GID numbers to represent the users and groups.  If the “webslingers” group has GID 404, and the “venom” user has a UID of 666, the same policy as above could be written this way, instead:

User_Alias U_WEBADMINS = %#404, !666

If you are using yellow pages with net groups, you can also reference a netgroup using a “+” instead of “%” to represent the group.

Finally, non-Unix group names and GIDs are represented with “%:” and “%:#” prefixes, instead of just “%” or “%#” per normal.

This is simple stuff, but I’ve seen poorly constructed “user alias” entries before.  This is why we’re taking it slow and hitting each type separately as we go.  A lot of this will seem redundant, but hopefully it lays it out in a simple and easily understood manner.

Thanks for reading!  Next week will be Host_Alias labels, simply because it is the next piece of the policy entry as read from left to right.