mirror of
https://github.com/QubesOS/qubes-doc.git
synced 2025-01-13 16:29:59 -05:00
Add initial Qubes U2F Proxy documentation
This commit is contained in:
parent
b2525ae87c
commit
99492ad6a2
1
doc.md
1
doc.md
@ -102,6 +102,7 @@ Security Guides
|
||||
* [Installing Anti Evil Maid](/doc/anti-evil-maid/)
|
||||
* [Using Multi-factor Authentication with Qubes](/doc/multifactor-authentication/)
|
||||
* [Using GPG more securely in Qubes: Split GPG](/doc/split-gpg/)
|
||||
* [The Qubes U2F Proxy](/doc/u2f-proxy/)
|
||||
* [How to Set Up a Split Bitcoin Wallet in Qubes](/doc/split-bitcoin/)
|
||||
* [[Unofficial] Split dm-crypt](https://github.com/rustybird/qubes-split-dm-crypt)
|
||||
* [Configuring YubiKey for user authentication](/doc/yubi-key/)
|
||||
|
210
security/u2f-proxy.md
Normal file
210
security/u2f-proxy.md
Normal file
@ -0,0 +1,210 @@
|
||||
---
|
||||
layout: doc
|
||||
title: The Qubes U2F Proxy
|
||||
permalink: /doc/u2f-proxy/
|
||||
---
|
||||
|
||||
# The Qubes U2F Proxy
|
||||
|
||||
The [Qubes U2F Proxy] is a secure proxy intended
|
||||
to make use of U2F two-factor authentication devices with web browsers without
|
||||
exposing the browser to the full USB stack, not unlike the [USB keyboard and
|
||||
mouse proxies][USB] implemented in Qubes.
|
||||
|
||||
## What is U2F?
|
||||
|
||||
[U2F], which stands for "Universal 2nd Factor", is a framework for
|
||||
authentication using hardware devices (U2F tokens) as "second factors", i.e.
|
||||
*what you have* as opposed to *what you know*, like a passphrase. This
|
||||
additional control provides [good protection][krebs] in cases in which the
|
||||
passphrase is stolen (e.g. by phishing or keylogging). While passphrase
|
||||
compromise may not be obvious to the user, a physical device that cannot be
|
||||
duplicated must be stolen to be used outside of the owner's control.
|
||||
Nonetheless, it is important to note at the outset that U2F cannot guarantee
|
||||
security when the host system is compromised (e.g. a malware-infected operating
|
||||
system under an adversary's control).
|
||||
|
||||
The U2F specification defines protocols for multiple layers from USB to the
|
||||
browser API, and the whole stack is intended to be used with web applications
|
||||
(most commonly websites) in browsers. In most cases, tokens are USB dongles.
|
||||
The protocol is very simple, allowing the devices to store very little state
|
||||
inside (so the tokens may be reasonably cheap) while simultaneously
|
||||
authenticating a virtually unlimited number of services (so each person needs
|
||||
only one token, not one token per application). The user interface is usually
|
||||
limited to a single LED and a button that is pressed to confirm each
|
||||
transaction, so the devices themselves are also easy to use.
|
||||
|
||||
Currently, the most common form of two-step authentication consists of a numeric
|
||||
code that the user manually types into a web application. These codes are
|
||||
typically generated by an app on the user's smartphone or sent via SMS. By now,
|
||||
it is well-known that this form of two-step authentication is vulnerable to
|
||||
phishing and man-in-the-middle attacks due to the fact that the application
|
||||
requesting the two-step authentication code is typically not itself
|
||||
authenticated by the user. (In other words, users can accidentally give their
|
||||
codes to attackers because they do not always know who is really requesting the
|
||||
code.) In the U2F model, by contrast, the browser ensures that the token
|
||||
receives valid information about the web application requesting authentication,
|
||||
so the token knows which application it is authenticating (for details, see
|
||||
[here][u2f-details]). Nonetheless, [some attacks are still possible][wired] even
|
||||
with U2F (more on this below).
|
||||
|
||||
## The Qubes approach to U2F
|
||||
|
||||
In a conventional setup, web browsers and the USB stack (to which the U2F token
|
||||
is connected) are all running in the same monolithic OS. Since the U2F model
|
||||
assumes that the browser is trustworthy, any browser in the OS is able to access
|
||||
any key stored on the U2F token. The user has no way to know which keys have
|
||||
been accessed by which browsers for which services. If any of the browsers are
|
||||
compromised, it should be assumed that all of the token's keys have been
|
||||
compromised. (This problem can be mitigated, however, if the U2F device has a
|
||||
special display to show the user what's being authenticated.) Moreover, since
|
||||
the USB stack is in the same monolithic OS, the system is vulnerable to attacks
|
||||
like [BadUSB].
|
||||
|
||||
In Qubes OS, by contrast, it is possible to securely compartmentalise the
|
||||
browser in one qube and the USB stack in another so that they are always kept
|
||||
separate from each other. The Qubes U2F Proxy then allows the token connected to
|
||||
the USB stack in one qube to communicate with the browser in a separate qube. We
|
||||
operate under the assumption that the USB stack is untrusted from the point of
|
||||
view of the browser and also that the browser is not to be trusted blindly by
|
||||
the token. Therefore, the token is never in the same qube as the browser. Our
|
||||
proxy forwards only the data necessary to actually perform the authentication,
|
||||
leaving all unnecessary data out, so it won't become a vector of attack. This is
|
||||
depicted in the diagram below (click for full size).
|
||||
|
||||
[![Qubes U2F Proxy diagram](/attachment/wiki/posts/u2f.svg)](/attachment/wiki/posts/u2f.svg)
|
||||
|
||||
The Qubes U2F Proxy has two parts: the frontend and the backend. The frontend
|
||||
runs in the same qube as the browser and presents a fake USB-like HID device
|
||||
using `uhid`. The backend runs in `sys-usb` and behaves like a browser. This is
|
||||
done using the `u2flib_host` reference library. All of our code was written in
|
||||
Python. The standard [qrexec] policy is responsible for directing calls to the
|
||||
appropriate domains.
|
||||
|
||||
The `vault` qube with a dashed line in the bottom portion of the diagram depicts
|
||||
future work in which we plan to implement the Qubes U2F Proxy with a software
|
||||
token in an isolated qube rather than a physical hardware token. This is similar
|
||||
to the manner in which [Split GPG] allows us to emulate the smart card model
|
||||
without physical smart cards.
|
||||
|
||||
One very important assumption of U2F is that the browser verifies every request
|
||||
sent to the U2F token --- in particular, that the web application sending an
|
||||
authentication request matches the application that would be authenticated by
|
||||
answering that request (in order to prevent, e.g., a phishing site from sending
|
||||
an authentication request for your bank's site). With the WebUSB feature in
|
||||
Chrome, however, a malicious website can [bypass][wired] this safeguard by
|
||||
connecting directly to the token instead of using the browser's U2F API.
|
||||
|
||||
The Qubes U2F Proxy also prevents this class of attacks by implementing an
|
||||
additional verification layer. This verification layer allows you to enforce,
|
||||
for example, that the web browser in your `twitter` qube can only access the U2F
|
||||
key associated with `https://twitter.com`. This means that if anything in your
|
||||
`twitter` qube were compromised --- the browser or even the OS itself --- it
|
||||
would still not be able to access the U2F keys on your token for any other
|
||||
websites or services, like your email and bank accounts. This is another
|
||||
significant security advantage over monolithic systems. (For details and
|
||||
instructions, see the [Advanced usage] section below.)
|
||||
|
||||
For even more protection, you can combine this with the [Qubes firewall] to
|
||||
ensure, for example, that the browser in your `banking` qube accesses only one
|
||||
website (your bank's website). By configuring the Qubes firewall to prevent your
|
||||
`banking` qube from accessing any other websites, you reduce the risk of another
|
||||
website compromising the browser in an attempt to bypass U2F authentication.
|
||||
|
||||
## Installation
|
||||
|
||||
The Qubes U2F Proxy tool can be installed in Qubes 3.2 and 4.0. (However, the
|
||||
[Advanced usage] features are only available in 4.0.) These instructions assume
|
||||
that there is a `sys-usb` qube that holds the USB stack, which is the default
|
||||
configuration in most Qubes OS installations.
|
||||
|
||||
In dom0:
|
||||
|
||||
```
|
||||
$ sudo qubes-dom0-update qubes-u2f-dom0
|
||||
$ qvm-service --enable work qubes-u2f-proxy
|
||||
```
|
||||
|
||||
In Fedora TemplateVMs:
|
||||
|
||||
```
|
||||
$ sudo dnf install qubes-u2f
|
||||
```
|
||||
|
||||
In Debian TemplateVMs:
|
||||
|
||||
```
|
||||
$ sudo apt install qubes-u2f
|
||||
```
|
||||
|
||||
Repeat `qvm-service --enable` (or do this in VM settings -> Services in the Qube
|
||||
Manager) for all qubes that should have the proxy enabled. As usual with
|
||||
software updates, shut down the templates after installation, then restart
|
||||
`sys-usb` and all qubes that use the proxy. After that, you may use your U2F
|
||||
token (but see [Browser support] below).
|
||||
|
||||
## Advanced usage: per-qube key access
|
||||
|
||||
If you are using Qubes 4.0, you can further compartmentalise your U2F keys by
|
||||
restricting each qube's access to specific keys. For example, you could make it
|
||||
so that your `twitter` qube (and, therefore, all web browsers in your `twitter`
|
||||
qube) can access only the key on your U2F token for `https://twitter.com`,
|
||||
regardless of whether any of the web browsers in your `twitter` qube or the
|
||||
`twitter` qube itself are compromised. If your `twitter` qube makes an
|
||||
authentication request for your bank website, it will be denied at the Qubes
|
||||
policy level.
|
||||
|
||||
To enable this, create a file in dom0 named
|
||||
`/etc/qubes-rpc/policy/policy.RegisterArgument+u2f.Authenticate` with the
|
||||
following content:
|
||||
|
||||
```
|
||||
sys-usb @anyvm allow,target=dom0
|
||||
```
|
||||
|
||||
Next, empty the contents of `/etc/qubes-rpc/policy/u2f.Authenticate` so that it
|
||||
is a blank file. Do not delete the file itself. (If you do, the default file
|
||||
will be recreated the next time you update, so it will no longer be empty.)
|
||||
Finally, follow your web application's instructions to enroll your token and use
|
||||
it as usual. (This enrollment process depends on the web application and is in
|
||||
no way specific to Qubes U2F.)
|
||||
|
||||
The default model is to allow a qube to access all and only the keys that were
|
||||
enrolled by that qube. For example, if your `banking` qube enrolls your banking
|
||||
key, and your `twitter` qube enrolls your Twitter key, then your `banking` qube
|
||||
will have access to your banking key but not your Twitter key, and your
|
||||
`twitter` qube will have access to your Twitter key but not your banking key.
|
||||
|
||||
## TemplateVM and browser support
|
||||
|
||||
The large number of possible combinations of Qubes version (3.2, 4.0),
|
||||
TemplateVM (Fedora 27, 28; Debian 8, 9), and browser (multiple Google Chrome
|
||||
versions, multiple Chromium versions, multiple Firefox versions) made it
|
||||
impractical for us to test every combination that users are likely to attempt
|
||||
with the Qubes U2F Proxy. In some cases, you may be the first person to try a
|
||||
particular combination. Consequently (and as with any new feature), users will
|
||||
inevitably encounter bugs. We ask for your patience and understanding in this
|
||||
regard. As always, please [report any bugs you encounter].
|
||||
|
||||
Please note that, in Firefox before Quantum (e.g. Firefox 52 in Debian 9), you
|
||||
have to install the [U2F Support Add-on][ff-u2f-addon]. In Firefox post-Quantum
|
||||
you may have to enable the `security.webauth.u2f` flag in `about:config`. Chrome
|
||||
and Chromium do not require any special browser extensions.
|
||||
|
||||
|
||||
[Qubes U2F Proxy]: https://github.com/QubesOS/qubes-app-u2f
|
||||
[USB]: /doc/usb/
|
||||
[U2F]: https://en.wikipedia.org/wiki/U2F
|
||||
[krebs]: https://krebsonsecurity.com/2018/07/google-security-keys-neutralized-employee-phishing/
|
||||
[u2f-details]: https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-overview-v1.2-ps-20170411.html#site-specific-public-private-key-pairs
|
||||
[wired]: https://www.wired.com/story/chrome-yubikey-phishing-webusb/
|
||||
[BadUSB]: https://www.blackhat.com/us-14/briefings.html#badusb-on-accessories-that-turn-evil
|
||||
[qrexec]: /doc/qrexec3/
|
||||
[Split GPG]: /doc/split-gpg/
|
||||
[Qubes firewall]: /doc/firewall/
|
||||
[Advanced usage]: #advanced-usage-per-qube-key-access
|
||||
[Browser support]: #templatevm-and-browser-support
|
||||
[report any bugs you encounter]: /doc/reporting-bugs/
|
||||
[ff-u2f-addon]: https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/?src=api
|
||||
[qubes-devel]: /support/#qubes-devel
|
||||
|
Loading…
Reference in New Issue
Block a user