mirror of
https://github.com/QubesOS/qubes-doc.git
synced 2025-01-05 04:31:02 -05:00
275 lines
12 KiB
ReStructuredText
275 lines
12 KiB
ReStructuredText
==========
|
||
CTAP proxy
|
||
==========
|
||
|
||
|
||
The `Qubes CTAP Proxy <https://github.com/QubesOS/qubes-app-u2f>`__ is a
|
||
secure proxy intended to make use of CTAP two-factor authentication
|
||
devices with web browsers without exposing the browser to the full USB
|
||
stack, not unlike the :doc:`USB keyboard and mouse proxies </user/how-to-guides/how-to-use-usb-devices>`
|
||
implemented in Qubes.
|
||
|
||
What is CTAP, U2F, FIDO2?
|
||
-------------------------
|
||
|
||
|
||
CTAP, U2F, and FIDO2 are all related to authentication protocols and
|
||
standards developed by the FIDO Alliance. CTAP has two versions: CTAP1
|
||
and CTAP2:
|
||
|
||
1. `CTAP1/U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`__
|
||
(Universal 2nd Factor): U2F is an earlier protocol developed by the
|
||
FIDO Alliance as part of the FIDO U2F standard. It provides a strong
|
||
second-factor authentication method using dedicated hardware security
|
||
keys. U2F allows users to authenticate to online services by simply
|
||
plugging in a U2F-compliant security key and pressing a button,
|
||
providing a higher level of security compared to traditional
|
||
passwords.
|
||
|
||
2. `CTAP2 <https://en.wikipedia.org/wiki/Client_to_Authenticator_Protocol>`__
|
||
(Client to Authenticator Protocol): CTAP2 is a protocol within the
|
||
FIDO2 framework that enables communication between a client device
|
||
(e.g., a computer or smartphone) and an authenticator (e.g., a
|
||
hardware device). CTAP allows for secure and convenient
|
||
authentication using public key cryptography and strong
|
||
authentication factors.
|
||
|
||
3. `FIDO2 <https://en.wikipedia.org/wiki/FIDO_Alliance>`__: FIDO2 is a
|
||
set of standards and protocols developed by the FIDO Alliance for
|
||
passwordless and strong authentication. It combines two main
|
||
components: CTAP (Client to Authenticator Protocol) and WebAuthn (Web
|
||
Authentication API). FIDO2 enables users to authenticate to online
|
||
services using various authentication methods, such as biometrics,
|
||
PINs, or hardware tokens, instead of relying on passwords.
|
||
|
||
|
||
|
||
The aim of these protocols is to introduce additional control which
|
||
provides `good protection <https://krebsonsecurity.com/2018/07/google-security-keys-neutralized-employee-phishing/>`__
|
||
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 the owner’s control. Nonetheless, it is important to note at the
|
||
outset that CTAP cannot guarantee security when the host system is
|
||
compromised (e.g. a malware-infected operating system under an
|
||
adversary’s control).
|
||
|
||
The CTAP 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,
|
||
authenticators 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. Both CTAP1 and CTAP2 share
|
||
the same underlying transports: USB Human Interface Device (USB HID),
|
||
Near Field Communication (NFC), and Bluetooth Smart / Bluetooth Low
|
||
Energy Technology (BLE).
|
||
|
||
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 CTAP 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 <https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-overview-v1.2-ps-20170411.html#site-specific-public-private-key-pairs>`__).
|
||
Nonetheless, `some attacks are still possible <https://www.wired.com/story/chrome-yubikey-phishing-webusb/>`__
|
||
even with CTAP (more on this below).
|
||
|
||
The Qubes approach to CTAP
|
||
--------------------------
|
||
|
||
|
||
In a conventional setup, web browsers and the USB stack (to which the
|
||
authenticator is connected) are all running in the same monolithic OS.
|
||
Since the CTAP model assumes that the browser is trustworthy, any
|
||
browser in the OS is able to access any key stored on the authenticator.
|
||
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 the token’s keys have been compromised. (This
|
||
problem can be mitigated, however, if the CTAP 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 <https://www.blackhat.com/us-14/briefings.html#badusb-on-accessories-that-turn-evil>`__.
|
||
|
||
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 CTAP 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 CTAP Proxy diagram|
|
||
|
||
The Qubes CTAP 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 ``fido2`` reference
|
||
library. All of our code was written in Python. The standard
|
||
:doc:`qrexec </developer/services/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 CTAP
|
||
Proxy with a software token in an isolated qube rather than a physical
|
||
hardware token. This is similar to the manner in which :doc:`Split GPG </user/security-in-qubes/split-gpg>` allows us to emulate the smart card model
|
||
without physical smart cards.
|
||
|
||
One very important assumption of protocol is that the browser verifies
|
||
every request sent to the authenticator — 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 <https://www.wired.com/story/chrome-yubikey-phishing-webusb/>`__
|
||
this safeguard by connecting directly to the token instead of using the
|
||
browser’s CTAP API.
|
||
|
||
The Qubes CTAP 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 CTAP 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
|
||
CTAP 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 <#advanced-usage-per-qube-key-access>`__ section below.)
|
||
|
||
For even more protection, you can combine this with the :doc:`Qubes firewall </user/security-in-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 CTAP authentication.
|
||
|
||
Installation
|
||
------------
|
||
|
||
|
||
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:
|
||
|
||
.. code:: bash
|
||
|
||
$ sudo qubes-dom0-update qubes-ctap-dom0
|
||
$ qvm-service --enable work qubes-ctap-proxy
|
||
|
||
|
||
|
||
The above assumes a ``work`` qube in which you would like to enable
|
||
ctap. Repeat the ``qvm-service`` command for all qubes that should have
|
||
the proxy enabled. Alternatively, you can add ``qubes-ctap-proxy`` in VM
|
||
settings -> Services in the Qube Manager of each qube you would like to
|
||
enable the service.
|
||
|
||
In Fedora templates:
|
||
|
||
.. code:: bash
|
||
|
||
$ sudo dnf install qubes-ctap
|
||
|
||
|
||
|
||
In Debian templates:
|
||
|
||
.. code:: bash
|
||
|
||
$ sudo apt install qubes-ctap
|
||
|
||
|
||
|
||
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 CTAP authenticator (but see `Browser support <#template-and-browser-support>`__ below).
|
||
|
||
Advanced usage: per-qube key access
|
||
-----------------------------------
|
||
|
||
|
||
If you are using Qubes 4.0, you can further compartmentalise your CTAP
|
||
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 CTAP
|
||
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/policy.d/30-user-ctapproxy.policy`` with the following
|
||
content:
|
||
|
||
.. code:: bash
|
||
|
||
policy.RegisterArgument +u2f.Authenticate 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 CTAP.)
|
||
|
||
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.
|
||
|
||
Non-default USB qube name
|
||
-------------------------
|
||
|
||
|
||
If your USB qube is named differently than ``sys-usb``, then do the
|
||
following in the appropriate template(s):
|
||
|
||
.. code:: bash
|
||
|
||
systemctl enable qubes-ctapproxy@USB_QUBE.service
|
||
systemctl disable qubes-ctapproxy@sys-usb.service
|
||
|
||
|
||
|
||
Replace ``USB_QUBE`` with the actual USB qube name.
|
||
|
||
Do not forget to change the sys-usb qube name in the policy
|
||
``/etc/qubes/policy.d/30-user-ctapproxy.policy``.
|
||
|
||
Template and browser support
|
||
----------------------------
|
||
|
||
|
||
The large number of possible combinations of template (Fedora 37, 38;
|
||
Debian 10, 11) 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 CTAP 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 :doc:`report any bugs you encounter </introduction/issue-tracking>`.
|
||
|
||
.. |Qubes CTAP Proxy diagram| image:: /attachment/doc/ctap.svg
|
||
|