VYPR
High severity8.1NVD Advisory· Published May 27, 2026

CVE-2026-48064

CVE-2026-48064

Description

pam_usb provides hardware authentication for Linux using ordinary removable media. Prior to 0.9.1, when a PAM service is configured with deny_remote=false in pam_usb (commonly done for display managers such as gdm-password or lightdm to bypass process/TTY heuristics for local sessions), the PAM_RHOST check in pusb_do_auth() is also skipped. PAM_RHOST is set by remote daemons (sshd, XDMCP servers) to identify the remote client address. Because the check is gated inside if (opts.deny_remote), a genuine remote XDMCP connection reaches the USB device authentication step instead of being rejected. This vulnerability is fixed in 0.9.1.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

pam_usb 0.9.0 and earlier skips PAM_RHOST check when deny_remote=false, allowing remote XDMCP authentication with USB device.

Vulnerability

In pam_usb versions prior to 0.9.1, when a PAM service is configured with deny_remote=false (commonly for display managers like gdm-password or lightdm), the PAM_RHOST check is skipped, allowing remote authentication via XDMCP [1][2].

Exploitation

An attacker needs a cloned or stolen USB device and the victim's password. If XDMCP is enabled (non-default) and the display manager service is whitelisted, the attacker can authenticate remotely via XDMCP, bypassing locality enforcement [2].

Impact

Successful exploitation allows remote authentication over XDMCP, gaining access to the system with the victim's privileges. This undermines the hardware authentication mechanism [2].

Mitigation

Update to pam_usb 0.9.1, which removes the if (opts.deny_remote) guard from the PAM_RHOST check so it runs unconditionally [2]. No known workaround exists for unpatched versions.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Patches

1
206fe0bc71ec

[Fix] Make PAM_RHOST check unconditional — decouple from deny_remote (issue #348)

https://github.com/mcdope/pam_usbMcDopeMay 20, 2026Fixed in 0.9.1via llm-release-walk
2 files changed · +31 14
  • src/pam.c+11 14 modified
    @@ -81,21 +81,18 @@ static int pusb_do_auth(
     		return PAM_IGNORE;
     	}
     
    -	if (opts.deny_remote)
    +	retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhost);
    +	if (retval != PAM_SUCCESS)
     	{
    -		retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhost);
    -		if (retval != PAM_SUCCESS)
    -		{
    -			log_error("Unable to retrieve PAM_RHOST.\n");
    -			pusb_conf_free(&opts);
    -			return PAM_AUTH_ERR;
    -		}
    -		else if (rhost != NULL && *rhost != '\0')
    -		{
    -			log_debug("RHOST is set (%s), must be a remote request - disabling myself for this request!\n", rhost);
    -			pusb_conf_free(&opts);
    -			return PAM_IGNORE;
    -		}
    +		log_error("Unable to retrieve PAM_RHOST.\n");
    +		pusb_conf_free(&opts);
    +		return PAM_AUTH_ERR;
    +	}
    +	if (rhost != NULL && *rhost != '\0')
    +	{
    +		log_debug("RHOST is set (%s), must be a remote request - disabling myself for this request!\n", rhost);
    +		pusb_conf_free(&opts);
    +		return PAM_IGNORE;
     	}
     
     	if (print_version)
    
  • tests/unit/c/pam_test.c+20 0 modified
    @@ -157,6 +157,24 @@ static void test_auth_deny_remote_rhost_retrieval_fails(void **state)
     	assert_int_equal(PAM_AUTH_ERR, pam_sm_authenticate(NULL, 0, 0, NULL));
     }
     
    +static void test_auth_rhost_set_deny_remote_false_returns_ignore(void **state)
    +{
    +	(void)state;
    +	reset_mocks();
    +	g_deny_remote = 0;
    +	g_rhost       = "192.168.1.1";
    +	assert_int_equal(PAM_IGNORE, pam_sm_authenticate(NULL, 0, 0, NULL));
    +}
    +
    +static void test_auth_rhost_retrieval_fails_deny_remote_false(void **state)
    +{
    +	(void)state;
    +	reset_mocks();
    +	g_deny_remote  = 0;
    +	g_rhost_retval = PAM_AUTH_ERR;
    +	assert_int_equal(PAM_AUTH_ERR, pam_sm_authenticate(NULL, 0, 0, NULL));
    +}
    +
     static void test_auth_local_login_denied(void **state)
     {
     	(void)state;
    @@ -216,6 +234,8 @@ int main(void)
     		cmocka_unit_test(test_auth_disabled_returns_ignore),
     		cmocka_unit_test(test_auth_deny_remote_rhost_set_returns_ignore),
     		cmocka_unit_test(test_auth_deny_remote_rhost_retrieval_fails),
    +		cmocka_unit_test(test_auth_rhost_set_deny_remote_false_returns_ignore),
    +		cmocka_unit_test(test_auth_rhost_retrieval_fails_deny_remote_false),
     		cmocka_unit_test(test_auth_local_login_denied),
     		cmocka_unit_test(test_auth_device_check_success),
     		cmocka_unit_test(test_auth_device_check_failure),
    

Vulnerability mechanics

Root cause

"The PAM_RHOST check is incorrectly gated inside the `if (opts.deny_remote)` guard, so when `deny_remote=false` (whitelisted services), the remote host detection is skipped entirely."

Attack vector

An attacker must have network access to an XDMCP-enabled display manager (e.g., GDM, SDDM, LightDM) that is configured with `deny_remote=false` in pam_usb, and must possess a valid USB authentication device and the victim's password [ref_id=1][ref_id=2]. Because the PAM_RHOST check is gated inside `if (opts.deny_remote)`, a remote XDMCP connection reaches the USB device authentication step instead of being rejected [ref_id=2]. XDMCP is disabled by default on most distributions, so this requires a non-default configuration [ref_id=1].

Affected code

The vulnerability resides in `src/pam.c` within `pusb_do_auth()`, where the PAM_RHOST retrieval and comparison is wrapped inside `if (opts.deny_remote)` [ref_id=1][ref_id=2]. Additionally, in `src/local.c` lines 329–331, when `deny_remote=false`, `pusb_local_login()` returns 1 immediately, skipping all sub-checks including VNC/RDP/evdev detection [ref_id=1].

What the fix does

The fix removes the `if (opts.deny_remote)` guard from the PAM_RHOST block in `src/pam.c` so the check runs unconditionally [ref_id=2]. The `pusb_local_login()` call remains unconditional in `pam.c`; the early-return for `!deny_remote` stays inside `local.c` and continues to skip the heuristic checks as intended [ref_id=2]. This decouples the PAM_RHOST check from the `deny_remote` config option, ensuring that remote host detection via PAM_RHOST always occurs regardless of the service whitelist entry [ref_id=1].

Preconditions

  • configThe target system must have XDMCP enabled on a display manager (GDM, SDDM, or LightDM) that is configured with deny_remote=false in pam_usb
  • inputAttacker must possess a valid USB authentication device and the victim's password
  • networkAttacker must have network access to the XDMCP service on the target

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.