Giter Club home page Giter Club logo

usbguard / usbguard Goto Github PK

View Code? Open in Web Editor NEW
1.1K 44.0 131.0 4.04 MB

USBGuard is a software framework for implementing USB device authorization policies (what kind of USB devices are authorized) as well as method of use policies (how a USB device may interact with the system)

Home Page: https://usbguard.github.io/

License: GNU General Public License v2.0

Shell 6.76% C++ 82.97% Makefile 2.20% M4 5.14% C 0.72% Perl 0.10% Jinja 1.15% Dockerfile 0.97% Vim Script 0.01%
usb usb-devices c-plus-plus rule-language security security-hardening whitelist blacklist linux hacktoberfest

usbguard's Introduction

USBGuard

Travis CI
Coverage
License

About

USBGuard is a software framework for implementing USB device authorization policies (what kind of USB devices are authorized) as well as method of use policies (how a USB device may interact with the system). Simply put, it is a USB device allowlisting tool.

Compilation & Installation

Warning
Prior to starting the USBGuard daemon (or service) for the first time (but after installation) we need to generate a rules file for USBGuard so that the currently attached USB devices (in particular mouse and keyboard) keep working so that you will not get locked out of your system. More on that below at Before the First Start.

To compile the source code, you will require at least C++17.
If you are compiling sources from a release tarball, you’ll need the development files for:

Optionally, you may want to install:

  • libseccomp - used to implement a syscall allowlist

  • libcap-ng - used to drop process capabilities

If you are on a Debian based GNU/Linux distribution like Ubuntu 21.10, installation of all build dependencies would be something like this:

$ sudo apt update && \
  sudo apt install --no-install-recommends -V \
    asciidoc autoconf automake bash-completion build-essential catch2 \
    docbook-xml docbook-xsl git ldap-utils libaudit-dev libcap-ng-dev \
    libdbus-glib-1-dev libldap-dev libpolkit-gobject-1-dev libprotobuf-dev \
    libqb-dev libseccomp-dev libsodium-dev libtool libxml2-utils \
    libumockdev-dev pkg-config protobuf-compiler sudo tao-pegtl-dev xsltproc

And then do:

$ ./configure        # for arguments of interest see below
$ make
$ make check         # if you would like to run the test suite
$ sudo make install

Configure arguments that deserve explicit mentioning (quoting ./configure --help output):

--enable-systemd        install the systemd service unit file (default=no)
--with-crypto-library   Select crypto backend library. Supported values:
                        sodium, gcrypt, openssl.
--with-bundled-catch    Build using the bundled Catch library
--with-bundled-pegtl    Build using the bundled PEGTL library
--with-ldap             Build USBGuard with ldap support

If you want to compile the sources in a cloned repository, you’ll have to run the ./autogen.sh script. It will fetch the sources (via git submodules) of PEGTL and Catch. The script will then initialize the autotools based build system, e.g. generate the ./configure script.

Before the First Start

Prior to starting the USBGuard daemon (or service) for the first time (but after installation) we need to generate a rules file for USBGuard so that the currently attached USB devices (in particular mouse and keyboard) keep working so that you will not get locked out of your system.

A rules file can be generated like this:

$ sudo sh -c 'usbguard generate-policy > /etc/usbguard/rules.conf'

After that, you can safely start service usbguard:

$ sudo systemctl start usbguard.service

And you can make systemd start the service every time your boot your machine:

$ sudo systemctl enable usbguard.service

License

Copyright © 2015-2019 Red Hat, Inc.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

usbguard's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

usbguard's Issues

Use shared library versioning

Use the libtool versioning scheme for the public API interface. The 0.x releases don't need to use the versioning as there aren't any guarantees for backward compatibility. However, starting with the v1.0 release, the versioning has to be maintained to prevent applications link to wrong interfaces.

Implement device tagging

Some devices provide not very useful attribute values. An example being a WiFi USB card having ff:ff:ff as device class:subclass:protocol and ff:00:00 as an interface type. ff is vendor specific, i.e. "not so useful values". An interface type based rule wouldn't match such device if we would use the provided values exactly.

Therefore, it would be nice to have a system to handle these exceptions. One option is to have a tag database which would assign tags for known combination of VID:PID + interface types and maybe something more, it could even use the rule language itself. These tags could be then referenced from the rule set using a "tags" attributes. Like so:

block tags any-of { #network #foobar #baddevice }

[RFE] usbguard-generate-policy: generate hash-only policy

Once the contents of a policy get leaked (accidentally or by a targeted attack), it's much easier to bypass the policy using fake devices as one knows the set of allowed devices and their attributes. Maintaining a hash-only policy would make it much harder, because the exact values of the devices attributes cannot be retrieved from a hash value.

Rule::toString() generates wrong rules if there's just one USB interface

Reproducer:

allow 17ef:6016 name "ThinkPad USB Laser Mouse" with-interface "03:01:02" hash "b2b49929ddce325f217adc89cd2b6c20"

Corrected rule (no quotes around the numeric USB interface specification)

allow 17ef:6016 name "ThinkPad USB Laser Mouse" with-interface 03:01:02 hash "b2b49929ddce325f217adc89cd2b6c20"

Device hashing needs to be smarter

The set of device attributes used currently for computing a device hash is not reliable. Only one field is currently handled as optional and it's the iSerial value. The manufacturer attribute may be missing too, and I guess so might the others...

The code should throw an exception only if the vendor and product id values cannot be read. Everything else should not be required to be preset and if missing, the value should be treated as empty.

Add support for matching various conditions in the rule language

It would be nice if one could somehow express that a rule should match only if some conditions are met. For example a rule which allows a keyboard interface would match only if no other keyboard interfaces are active. Or expressing that a rule should match only in a specific time range (not sure about the use case of this yet...).

Allow to insert new devices only when the user authenticates himself

This is closely related to the "condition" feature tracked in a separate ticket #24. One use case of such a feature would be to implement a condition that matches an authentication state -- either some sort of a global one and/or user-specific(?). Using that, one could write a policy that allows to connect devices only if the user authenticates himself (password, signature -- smart card device connected, etc.)

[RFE] Integrate usbguard into Freeipa

Freeipa (www.freeipa.org) is centralized management tool for maintaining identity and access policy like HBAC or SUDO with help of sssd on client machines. I think that managing sudo policies is very similar to usbguard policies and thus having IPA user interface for usbguard could simplify management on large deployments (government, enterprises) and could extend freeipa's functionality. I think that this RFE is blocked by issue no. 30, because we need to be able to allow usb devices based on users and computers.

For example user1 is allowed to use USB Flash on computer1, but is not allowed to use it on computer2.
Another example could be, there is some USB device which is allowed on all computers.

Integration with Freeipa could be managed by creating Freeipa module. https://www.freeipa.org/images/5/5b/FreeIPA33-extending-freeipa.pdf

Create an alternative, human-friendly form of interface type representation in the rule language

From the numeric form, it's not immediately clear what interface type the device supports, as one would have to carry a database of USB class, subclass and protocol numbers in his head...

So, it would be nice to have an option to write an interface type as a string of some form. Maybe even allow aliases like "keyboard", "network card", "flash disk", etc.

And as always, external help with thinking about this would be appreciated! But nobody probably reads this anyway...

[RFE] Support for external/non-local rule sources (LDAP, SSSD, ...)

Non-local rule sources configured via /etc/nsswitch.conf would allow centralized management of usbguard policies.

Implementation steps draft:

  1. /etc/nsswitch.conf parsing
  2. Creating an internal nss source interface
  3. Reimplementing the current local file source on top of the nss interface
  4. Defining an LDAP schema for rulesets strored in LDAP
  5. Implementing the LDAP source (and others)

Add setting for configuring how to handle devices present when the daemon is started

There are at least two options:

  • ignore the devices, set their target to allowed/blocked based on the current authorization value
  • or apply the policy

For dynamic use cases, applying the policy too early might result in blocking of devices that the users doesn't want to block, e.g. keyboards and pointing devices -- the user might not be able to interact with the system after the start of the USBGuard daemon.

Test suite coverage is pretty bad

At the moment, I don't spent much time on writing tests, which is not a good practice :D API test should be the priority for now. The areas that would be nice to have covered are:

  • API unit test
  • rule parsing tests -- valid + invalid inputs
  • policy tests (requires the ability to simulate devices + udev events?)
  • USB descriptor parsing tests
  • fuzzing tests (related: https://github.com/schumilo/vUSBf)
  • IPC/DBus interface tests

Implement a priviledged process for executing actions

To implement the "actions" part of a rule, the daemon will have to spawn a privileged process before dropping capabilities and setting up a seccomp whitelist. Otherwise, the executed programs would be limited by the same set of capabilities and syscalls as the daemon.

Appending a rule as permanent doesn't work

The following is in the debug logs:

[2015-04-08 10:58:30.766] [logger] [debug] Allowing device: 2
[2015-04-08 10:58:30.766] [logger] [debug] Appending rule: allow 1050:0011 name "Yubikey" hash "5c787aff316375cd5fe0e12ffed3e12a" with-interface <MATCH> { 03:01:01 }
## Disable this message by compile option
##        '-DQUEX_OPTION_ASSERTS_WARNING_MESSAGE_DISABLED'
##
## Asserts activated! Lexical analyzer is 'paranoid'!
## => Even smallest misbehavior causes program exit.
##    This helps to find subtile errors.
##
## Note however: the paranoia is a heavy load on performance!
##
## Disable asserts by '-DQUEX_OPTION_ASSERTS_DISABLED'
##
## Report any bug at
##        http://sourceforge.net/tracker/?group_id=168259&atid=846112
Lexer.cpp:2535: [2015-04-08 10:58:30.767] [logger] [error] Exception: 
   Match failure in mode 'RULE'.
  No 'on_failure' section provided for this mode.
   Proposal: Define 'on_failure' and analyze 'Lexeme'.

Looks like the device rule is generated with an invalid interface set operator because "" isn't a valid keyword and the lexer doesn't recognize it.

[RFE] Implement block device signing and verification

The block device (filesystem) label attribute could be used to implement device signing and signature verification. Consider/Research whether it would be possible to store a device signature inside the label and verify the block device before it's contents are accessed in any way (incl. mounting).

The original idea comes from the Linux kernel USB authorization feature documentation at https://www.kernel.org/doc/Documentation/usb/authorization.txt. However, the examples inside require mounting of the device and accessing a file inside.

This feature should automatically turn read-only mode for the block device. Devices which will fail to verify should be handled according to the specified target (block, reject, ...).

[RFE] Merge the usbguard-applet-qt and usbguard projects

The Qt applet was initially thought just as a PoC project. However, it attracts users because it provides a convenient way to use USBGuard on their system. The maintenance and development will be also somewhat easier because it'll be much easier to integrate and test new features that require modification of both the applet and the library.

Building of the applet should be optional so as not to force any GUI dependencies on users/developers who are not interested in the GUI component(s).

Implement a CLI client

Implement a CLI client tool for interacting with the daemon. Support at least these features:

  • all IPC methods
  • listing devices
  • signal watcher

Implement usbguard-oneshot component

Some users may prefer not to run an additional daemon for various reasons:

  • their USB device usage policy doesn't need to be dynamic (no user interaction, fully defined by a static rule set)
  • minimize always running components on the system
  • low USB device "traffic" (i.e. using a USB device once a month, etc.)

A "oneshot" component which would be triggered on-demand (by the user, via a udev rule) would load rules, apply them on devices currently connected to the system and exit.

Implement IPC authentication

The idea is to use PKI for IPC authentication where the user authenticates itself using IPC message signing. Allowing a user/app to use the IPC would require to register a public key with the daemon.

Device rules are always generated without port attribute

Looks like I've made a mistake when implementing API modifications for the generate policy tool. Device rules seems to be generated without the port attribute and the whole rule then doesn't match anything that matches on the port attribute.

Note for myself: spend more cycles on a testing suite so that these bugs are discovered before a release is made.

[RFE] Protected Mode is missing (GRSecurity support)

Hi,

currently the USB protection for bad usb only protects userspace attacks. Not kernelspace driver !
In order to support something like a protected mode (disabled usb stack) which can be enabled/disabled via qt applet.
I recommend to integrate the grsecurity DENY_USB feature which can be controlled via sysctl.
Pull request will follow in few days ;)

Regards Zaolin

[RFE] network bound usb disk encryption

Use case brought up by [email protected]. We should consider whether this is a valid use case for usbguard and whether something actually needs to be done by usbguard to extend FreeIPA's capabilities to usb disks/sticks.

The idea is that a usb disk/stick usage would be network bound by encrypting it with a key provided by the FreeIPA (or similar?) infrastructure. Such a disk could be used to transfer files between managed machines only since only they can decrypt and mount the disk. This assumes that the user has limited access to the machines and he/she cannot extract the key used to decrypt the disk.

Related: http://www.freeipa.org/page/Network_Bound_Disk_Encryption

Any ideas, opinions on this? (Is anyone actually reading these RFEs?)

Parse error - 1 is not a number

I have set up usbguard following the guide here.

When I run usbguard-applet-qt I get this message on terminal:

"sni-qt/5139" WARN 13:46:05.401 void StatusNotifierItemFactory::connectToSnw() Invalid interface to SNW_SERVICE

When I insert a USB flash drive I get following error on terminal and applet stops:

terminate called after throwing an instance of 'std::invalid_argument'
what(): parse error - 1 is not a number
Aborted

This system:

Description: Linux Mint 17.2 Rafaela
Release: 17.2

Provide a package bundle for users of non-RPM distributions

Until the usbguard tools and their dependencies are available as official packages in other distributions, we should provide an installable package bundle that includes all the necessary stuff to run the usbguard framework.

There were several request for instructions how to install usbguard on Ubuntu/Debian based systems.

Implement USB device descriptor decoder

A USB device descriptor decoder is needed for getting information about the interfaces that a USB device provides.

We could link to libusb, but there's AFAIK no possibility to instantiate a usb device structure directly without calling the "get list" function which enumerates all devices. However, it might be possible to extract just the decoder from the code and simplify it to the bare minimum.

Another possibility is to implement the decoder from scratch...

[RFC] Rule language: device matching

The rule language (described here) needs some modification to be able to support various "device matching use cases". Here's a proposal for a revised set of attributes usable for matching a device:

  • hash "[0-9a-f]{32}": Match a hash of the device attributes (the hash is computed for every device by USBGuard).
  • name "device-name": Match the USB device name attribute.
  • serial "serial-number": Match the iSerial USB device attribute.
  • via-port "port-id": Match the USB port through which the device is connected.
  • via-port [operator] { "port-id" "port-id" ... }: Match a set of USB ports.
  • with-interface interface-type: Match an interface the USB device provides.
  • with-interface [operator] { interface-type interface-type ... }: Match a set of interface types against the set of interfaces the USB device provides.

operator is one of:

  • all-of: The associated device attribute set must contain all of the specified values for the rule to match.
  • any-of: The associated device attribute set must contain a combination of the specified values for the rule to match.
  • one-of: The associated device attribute set must contain one of the specified values for the rule to match.
  • none-of: The associated device attribute set must not contain any of the specified values for the rule to match.
  • equals-set-of: The associated device attribute set must contain exactly the same set of values for the rule to match.
  • equals-ordered-set-of: The associated device attribute set must contain exactly the same set of values in the same order for the rule to match.

port-id is a platform specific USB port identification. On Linux it's in the form "b-n" where b and n are unsigned integers (e.g. "1-2", "2-4", ...).

interface-type represents a USB interface and may be expressed either in a numeric form or as an interface type string.
The numeric form is expressed as three 8-bit numbers in hexadecimal base delimited using a colon: xx:xx:xx. The numbers represent the interface class, subclass and protocol as assigned by the USB-IF (List of assigned classes, subclasses and protocols).
The string form is human-readable translation of the numeric form and it's USBGuard specific. It's expressed as a string with three colon delimited substrings. The three substrings represent the number-to-string translation of the interface class, subclass and protocol as defined by a USBGuard specific file.

Implement a group based IPC ACL

Before a more fine grained authentication/authorization is implemented using public keys or whatever (policy kit?), implement a simple group based ACL. That is, allow only application that are run by users in a certain (configurable) group to use the IPC interface.

For distribution packages, install a "usbguard" group and configure it as the required one.

[RFE] When explicitly asked for using a rule, monitor the traffic to/from a USB device

Since it is usually hard to differentiate between a real keyboard and a faked one (no iSerial value exported, mobile users tend to use several keyboard and leave them at the places they move from/to, ...) we could at least look for clues in the USB traffic, i.e. behaviour of the device. The Linux kernel provides a facility to monitor USB traffic, usbmon.

Rogue keyboard devices usually try to perform their task fast (with some initial delay, or when triggered by an external event -- lighting conditions, RF remote control, ...) so as not to be noticed by the user of the targeted computer. And they use a limited set of characters (scan codes).

A normal keyboard on the other hand, when used by a human, sends all kinds of characters -- the statistical properties of such traffic probably highly depend on the operator.

USBGuard could monitor the traffic of selected devices and notify the user when something unusual happens or when it classifies the traffic as originating from a rouge device. Some learning step might be necessary to prevent a lot of false positives...

Gentoo Linux support

Hi,

I wrote for usbguard and the qt applet version specific gentoo packages. They can be found inside the stuge-overlay via https://gpo.zugaina.org/Overlays/stuge in few days.
It would be nice if you can update your README and add Gentoo as supported distribution.
I will reply on this thread asap if they are online.

Hide implementation details from the shared library

A shared library is provided to abstract the details of IPC implementation and to allow developing clients for the usbguard daemon (applets, control apps, etc). However, since the public IPCClient class contains private members of types which need to be defined (qb types, json, etc.), it's needed to ship a lot of third-party files. This could be avoided by using a "d-pointer" (pimpl, opaque pointer, whatever...).

Consider using libusb for usb device handling

Currently, we're are tied to the /sys (sysfs) filesystem and UDev and that's not a very good solution from a portability POV. The drawback of using libusb would be that we would have to enumerate all devices on every device insert/remove as it doesn't have an event-like interface. More investigation is needed in this area.

I'm probably going to split the USB device handling into two separate classes. A device monitor (base on whatever is the best on the host OS) and device manager (based on libusb). The device monitor will trigger a rescan of device in the manager (or point to the particular device if libusb is able to instantiate it's device representation instance without enumerating all devices).

This should improve portability of the code to other platforms. Device authorization need also to have a portable interface.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.