I have discovered a new security issue in the Yubico HSM client-side code. An attacker with control over the data input of the SSH Certificate Signing functionality can cause a stack buffer overflow with arbitrary data in the yubihsm-shell tool. The overflow is mitigated into a denial of service through existing runtime hardening.

This article will describe the issue.

Consulting

I’m a freelance Security Consultant and currently available for new projects. If you are looking for assistance to secure your projects or organization, contact me.

The Vulnerability

Please see some of the previous articles on libyubihsm for the technical background and relevance of this code. Unlike other Yubico HSM client issues, this flaw is specific to the standalone CLI program and doesn’t affect users of the library code.

Let’s talk about the code that leads to the issue.

When yubihsm-shell is called with the sign-ssh-certificate action, it checks the required parameters:

case action_arg_signMINUS_sshMINUS_certificate: {
  if (args_info.template_id_given == 0) {
    fprintf(stderr, "Missing argument template-id\n");
    rc = EXIT_FAILURE;
    break;
  }

  if (args_info.algorithm_given == 0) {
    fprintf(stderr, "Missing argument algorithm\n");
    rc = EXIT_FAILURE;
    break;
  }

// more checks
// [...]

main.c

Once the checks are passed, the SSH certificate file is read in via get_input_data() and stored in the local buf[] buffer. Notably, this buffer accepts up to 8192 bytes of binary input and is generically used for different actions.

The buffer is then passed to the yh_com_sign_ssh_certificate() function, which is defined like this:

int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv,
                                cmd_format in_fmt, cmd_format fmt) {

// [...]

  uint8_t data[YH_MSG_BUF_SIZE + 1024];
  size_t response_len = sizeof(data);

  memcpy(data, argv[4].x, argv[4].len);

command.c

The YH_MSG_BUF_SIZE is set to 2048, so the local data[] buffer holds 3072 bytes. Since the correlating response_len size limit is not used correctly to restrict write operations, the memcpy() operation performs a classic stack buffer overflow beyond the end of data[] if yubihsm-shell is called on SSH certificate input files that are between 3073 and 8192 bytes in length.

Stack buffer overflows with arbitrary binary data of variable length are fairly interesting for attackers since they can be used for reliable stack smashing attacks. If successful, this redirects the program control flow and allows - more or less - arbitrary code execution.

Fortunately for yubihsm-shell users, the existing RELEASE target build steps include the hardening flags -fstack-protector-all and -D_FORTIFY_SOURCE=2 (on non-Windows builds). This instructs the compiler to add runtime checks which detect the buffer overflow and terminate the program before additional harm is done. As a result, the program terminates either directly during the memcpy() or at the end of the yh_com_sign_ssh_certificate() function.

The expected impact therefore is a denial of service of yubihsm-shell.

Attack Scenario and Security Implications

Based on my understanding of the affected CLI functionality, the SSH certificate file is plausibly generated a lower-privileged or untrusted external user and moved to the target system for signing via the HSM by a higher-privileged user. The trust boundary step that is involved makes this vulnerability interesting from a conceptual standpoint. However, the denial of service impact is without major consequences, especially if yubihsm-shell is operated manually.

A notable side effect of the specific CLI crash behavior is that one of the 16 communication session slots of the HSM2 target stays blocked until it times out after 30 seconds. If there is an automated system that can be tricked into processing problematic SSH certificates via yubihsm-shell repeatedly and in quick succession, this can be used to cause a temporary denial of service of the HSM for other client connections, if there are any.

CVSS Score

I have focused on the CVSS score for

  • a local attack
  • enough privileges to influence the SSH certificate file on disk before it is used
  • manual use by the yubihsm-shell operator
  • with an availability impact

There are other ways to score this and Yubico has chosen a slightly different approach. Overall, the issue severity is somewhere between Low and Medium, primarily due to the effective mitigations that prevent more serious effects in practice.

ID CVSS 3.1 Score Parameters
CVE-2021-43399 4.0 (Medium) AV:L/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:H or
AV:L/AC:L/PR:H/UI:R/S:U/C:L/I:L/A:L

Proof-of-Concept

WARNING: use the following code at your own risk. Although not intended, please assume that this will PERMANENTLY overwrite data on the HSM device that you have connected.

Procedure:

  1. Install an affected version of the yubihsm-shell program. There are no custom patches required.
  2. Connect a HSM2 device in factory settings via USB.
  3. Run the commands below.
# create a dummy input file with a problematic filesize
dd if=/dev/zero bs=4242 count=1 of=example1.req
# trigger the affected functionality
sudo ./yubihsm-shell --connector=yhusb:// -v127 -p password -a sign-ssh-certificate --template-id 0x1234 --algorithm rsa-pkcs1-sha1 --in example1.req

Coordinated Disclosure

Overall, my thoughts on the coordinated disclosure are similar to the previous disclosure.

It definitely helped to have an existing communication channel. My impression is that the disclosure coordination was not as fluid as with previous issues, and there were a number of hiccups along the way that required extra attention.

However, I still think it is positive that yubihsm-shell is developed as open source code and available for independent review, even though the release schedule and extra release preparations make it more time consuming than other projects to report security issues in.

Relevant yubihsm-shell Sources

variant source fix references
Yubico upstream GitHub version 2.3.0, bundled in SDK release 2021.12 YSA-2021-04
Fedora Fedora 2.3.0-1 Bug 2030694

Detailed Timeline

Date info
2021-09-15 Disclosure of issue to Yubico
2021-09-23 Yubico acknowledges the issue
2021-09-27 POC sent to Yubico
2021-09 to 2021-10 Communication on issue impact and scoring
2021-11-03 Yubico communicates release date 2021-11-23
2021-11-17 Yubico communicates release date 2021-12-01
2021-12-01 Yubico communicates release date 2021-12-08
this was originally sent on 2021-11-24 but mangled
2021-12-08 Yubico publishes YSA-2021-04
2021-12-08 Publication of this article

Note that the Yubico timeline incorrectly describes 2021-09-04 as the initial disclosure date.

Bug Bounty

Yubico provided two YubiKeys as a hardware bug bounty for this issue.