CVE-2026-55785: free5GC AUSF uses non-constant-time authentication comparisons and logs XRES* in 5G-AKA
Summary
The AUSF component of free5GC compares authentication response values with normal Go equality helpers instead of constant-time cryptographic comparison functions.
Two authentication flows are affected in internal/sbi/processor/ueauthentication.go:
1. 5G-AKA confirmation compares RES and XRES with strings.EqualFold(). 2. EAP-AKA' confirmation compares ATMAC with bytes.Equal() and compares XRES and RES with ==.
These functions are not designed to be constant-time cryptographic comparators and may return earlier depending on the location of the first mismatch.
Additionally, the 5G-AKA confirmation path logs both the received res and the expected Xres at INFO level immediately before comparing them. The XRES value is authentication material and should not be written to application logs.
The timing side channel was confirmed as a code issue, but practical exploitation over HTTP was not demonstrated in the lab because the comparator-level signal is much smaller than HTTP/SBI noise. The XRES logging issue is directly observable in AUSF logs.
Confirmed on github.com/free5gc/ausf v1.4.4 and current main as of the May 2026 analysis.
Details
5G-AKA: RES / XRES
In Auth5gAkaComfirmRequestProcedure(), the AUSF logs both values and then compares them with strings.EqualFold():
go // internal/sbi/processor/ueauthentication.go logger.Auth5gAkaLog.Infof("res: %x\nXres: %x\n", updateConfirmationData.ResStar, ausfCurrentContext.XresStar)
if strings.EqualFold(updateConfirmationData.ResStar, ausfCurrentContext.XresStar) { ausfCurrentContext.AuthStatus = models.AusfUeAuthenticationAuthResultSUCCESS confirmDataRsp.AuthResult = models.AusfUeAuthenticationAuthResultSUCCESS success = true logger.Auth5gAkaLog.Infoln("5G AKA confirmation succeeded") // ... }
For hexadecimal ASCII strings, strings.EqualFold() performs a character comparison that can terminate when a mismatch is found. It is not a constant-time comparison primitive.
The line immediately before the comparison is more directly exploitable: it writes XresStar to INFO logs. Any operator, compromised sidecar, log collector, SIEM user, or local process with access to AUSF logs can read the expected response value for authentication attempts.
EAP-AKA': ATMAC, XMAC, XRES, and RES
In EapAuthComfirmRequestProcedure(), the AUSF computes the expected MAC and compares it with the received ATMAC using bytes.Equal():
go KautStr := ausfCurrentContext.Kaut Kaut, := hex.DecodeString(KautStr) XMAC := CalculateAtMAC(Kaut, decodeEapAkaPrimePkt.MACInput) MAC := decodeEapAkaPrimePkt.Attributes[ausfcontext.ATMACATTRIBUTE].Value XRES := ausfCurrentContext.XRES RES := hex.EncodeToString(decodeEapAkaPrimePkt.Attributes[ausfcontext.ATRESATTRIBUTE].Value)
if !bytes.Equal(MAC, XMAC) { eapOK = false eapErrStr = "EAP-AKA' integrity check fail" } else if XRES == RES { logger.AuthELog.Infoln("Correct RES value, EAP-AKA' auth succeed") // ... }
bytes.Equal() is not specified as a constant-time cryptographic comparison. The subsequent XRES == RES string comparison is also not constant-time. The correct primitive for comparing authentication tags and secret response values in Go is crypto/subtle.ConstantTimeCompare, after validating and normalizing input length and encoding.
The EAP-AKA' case is harder to exploit remotely than the 5G-AKA case because the XRES == RES comparison is reached only if ATMAC is valid. Producing a valid ATMAC requires session-specific Kaut.
Evidence
Static evidence
Static analysis confirmed:
- strings.EqualFold(updateConfirmationData.ResStar, ausfCurrentContext.XresStar) in the 5G-AKA confirmation path. - logger.Auth5gAkaLog.Infof("res: %x\nXres: %x\n", ...) immediately before the comparison. - bytes.Equal(MAC, XMAC) in the EAP-AKA' confirmation path. - XRES == RES in the EAP-AKA' confirmation path. - crypto/subtle is absent from the AUSF authentication processor code.
Internal evidence:
text hallazgos/finding10-hres-timing/evidencia/20260526-090151-static-analysis/ hallazgos/finding11-eap-mac-timing/evidencia/20260526-094642-static-analysis/
5G-AKA timing and logging evidence
A timing PoC sent 500 iterations per condition over loopback HTTP/SBI:
text Condition A: mismatch near the start Condition B: mismatch in the middle Condition C: mismatch near the end Condition D: full match
The comparator-position signal was not distinguishable from HTTP noise:
text Delta C-A: approximately -1.5 us 2-sigma noise threshold: approximately 557 us Result: SIGNAL NOT CLEAR
This is consistent with the expected signal-to-noise ratio: the comparator-level timing difference is in the nanosecond range, while the HTTP/SBI path adds hundreds of microseconds of variance.
The same lab run confirmed that AUSF logs include XresStar in plaintext at INFO level. This does not require statistical inference.
Internal evidence:
text hallazgos/finding10-hres-timing/evidencia/20260526-093558-timing-poc/
EAP-AKA' timing evidence
A timing PoC sent 500 iterations per condition against the EAP-AKA' confirmation path:
text A: first MAC byte incorrect B: first 8 MAC bytes correct C: MAC correct, XRES incorrect D: MAC correct, XRES correct
Observed medians were all around 464-467 us, and the HTTP-level timing signal was not detectable:
text A: 466.6 us B: 466.5 us C: 464.2 us D: 464.2 us Delta D-A: approximately -2.4 us 2-sigma noise threshold: approximately 716 us Result: SIGNAL NOT CLEAR
This confirms the expected practical limitation of a remote HTTP timing attack.
Internal evidence:
text hallazgos/finding11-eap-mac-timing/evidencia/20260526-103822-timing-poc/
Local CPU benchmark for bytes.Equal()
A direct Go microbenchmark without HTTP overhead measured bytes.Equal() for 16-byte values. The raw benchmark data showed a monotonic increase as more leading bytes matched. The median delta from N=0 matching bytes to N=15 matching bytes was roughly 0.31 ns, or more than 20%.
This confirms that the local comparator is not position-independent at CPU level, even though the signal is too small to exploit remotely over HTTP in normal conditions.
Internal evidence:
text hallazgos/finding11-eap-mac-timing/evidencia/20260526-104842-cpu-benchmark/
Uprobe path confirmation
Linux uprobes on the live AUSF process confirmed that requests reach the relevant comparison paths:
- MAC comparison path is hit for both failing and successful EAP-AKA' attempts. - XRES comparison path is hit only when MAC verification passes.
Internal evidence:
text hallazgos/finding11-eap-mac-timing/evidencia/20260526-053510-ebpf-uprobe/
Impact
There are two impact classes.
Sensitive value in logs
The 5G-AKA path logs XRES, the expected response value, at INFO level. In deployments where AUSF logs are collected centrally or are readable by lower-privileged operators, infrastructure agents, compromised containers, or log-processing systems, this exposes authentication material that should remain internal to the authentication procedure.
The exact exploitability depends on whether the attacker can correlate log access with an active authentication context and submit the confirmation before the context is consumed or failed. Regardless, writing XRES to application logs is an unsafe handling of authentication material.
Timing side channel / cryptographic hardening issue
The non-constant-time comparisons are real code issues and should be fixed, but we did not demonstrate a practical remote timing oracle over HTTP/SBI. The measured comparator signal is too small relative to HTTP noise in the lab.
The risk is higher in environments where an attacker has a lower-noise measurement point, local co-residency, kernel tracing capabilities, or another side channel that can observe the comparison more directly.
Suggested remediation
1. Remove XRES, RES, XRES, RES, Kaut, ATMAC, and derived authentication material from INFO logs. If logging is necessary, log only metadata such as the authentication context ID, SUPI/SUCI in redacted form, result, and failure class.
2. Replace strings.EqualFold() and string == comparisons for authentication values with constant-time comparisons.
3. Normalize encodings before comparison. For hex-encoded values, decode both inputs first, validate expected lengths, and then compare fixed-size byte slices.
Example for 5G-AKA:
go resStar, err1 := hex.DecodeString(updateConfirmationData.ResStar) xresStar, err2 := hex.DecodeString(ausfCurrentContext.XresStar)
if err1 == nil && err2 == nil && len(resStar) == len(xresStar) && subtle.ConstantTimeCompare(resStar, xresStar) == 1 { // success } else { // failure }
Example for EAP-AKA' MAC:
go if len(MAC) != len(XMAC) || subtle.ConstantTimeCompare(MAC, XMAC) != 1 { eapOK = false eapErrStr = "EAP-AKA' integrity check fail" }
Example for EAP-AKA' XRES:
go res, err1 := hex.DecodeString(RES) xres, err2 := hex.DecodeString(XRES)
if err1 == nil && err2 == nil && len(res) == len(xres) && subtle.ConstantTimeCompare(res, xres) == 1 { // success }
4. Add unit tests that ensure authentication values are not written to logs.
5. Consider avoiding a second UDM notification call in the 5G-AKA failure path if the first failure notification already reports the result. In the lab, failure performed two UDM calls while success performed one; this creates a coarse success/failure timing difference, although that result is already visible through the API response.
Prior art / non-duplication note
Known recent free5GC AUSF issues such as CVE-2026-33063 concern different failure modes and code paths. This report concerns cryptographic comparison and logging behavior in internal/sbi/processor/ueauthentication.go.
Other sources
free5GC is an open-source implementation of the 5G core network. Prior to 1.4.5, the AUSF component performs cryptographic authentication comparisons in internal/sbi/processor/ueauthentication.go with ordinary equality helpers. Auth5gAkaComfirmRequestProcedure compares RES and XRES with strings.EqualFold and logs the expected XRES value at INFO level before comparison. EapAuthComfirmRequestProcedure compares ATMAC and XMAC with bytes.Equal and evaluates XRES == RES with ordinary string equality. These comparisons can return at mismatch-dependent times, although testing did not demonstrate a practical remote timing oracle because of HTTP/SBI timing noise. The INFO log exposes authentication material to operators, log collectors, sidecars, or processes able to read AUSF logs. This issue is fixed in version 1.4.5.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
go/github.com/free5gc/ausfto a version that resolves this vulnerability.Fixed in 1.4.5 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 1.4.5 - Configuration
In internal/sbi/processor/ue_authentication.go, update the 5G-AKA confirmation logging so it does not write XRES*/RES* (or XresStar/ResStar-derived values) to application logs; if logging is necessary, log only metadata such as authentication context ID, SUPI/SUCI in redacted form, result, and failure class.
free5GC AUSF (logger.Auth5gAkaLog / INFO logging) Auth5gAkaLog INFO message contents for 5G-AKA confirmation = Remove plaintext authentication material from INFO logs: do not log XresStar/res* values (e.g., the reported logger line: "res*: %x\nXres*: %x\n" and any INFO log that outputs XresStar). - Configuration
In Auth5gAkaComfirmRequestProcedure(), stop using strings.EqualFold(updateConfirmationData.ResStar, ausfCurrentContext.XresStar) for RES*/XRES* comparisons; instead, hex-decode both inputs, validate expected lengths, and compare fixed-size byte slices using subtle.ConstantTimeCompare(...)=1.
free5GC AUSF (internal/sbi/processor/ue_authentication.go) Authentication-value comparison primitive for 5G-AKA (RES* vs XRES*) = Replace strings.EqualFold() with crypto/subtle constant-time comparisons after validating/normalizing input length and encoding. - Configuration
In EapAuthComfirmRequestProcedure(), stop using bytes.Equal(MAC, XMAC) (which this report notes is not specified as constant-time) and stop using ordinary string equality for XRES == RES; instead hex-decode/normalize with length checks and compare using subtle.ConstantTimeCompare(...)=1 for the relevant authentication values.
free5GC AUSF (internal/sbi/processor/ue_authentication.go) Authentication-value comparison primitive for EAP-AKA' (AT_MAC vs XMAC; XRES vs RES) = Replace non-constant-time comparisons: use subtle.ConstantTimeCompare() for AT_MAC/XMAC and validate+constant-time compare for XRES/RES; do not rely on bytes.Equal() or ordinary string equality for these secrets.
Event History
Frequently Asked Questions
Was a practical remote timing attack demonstrated?
No. The non-constant-time comparisons were confirmed as a code issue, but practical exploitation over HTTP/SBI was not demonstrated because the comparator-level timing signal was much smaller than HTTP/SBI noise.
What sensitive data may already be exposed in AUSF logs?
The 5G-AKA confirmation path logs both the received res* value and the expected Xres* value at INFO level before comparison. The XRES* value is authentication material, and its presence in AUSF logs is directly observable.
Which authentication flows contain the affected comparisons?
The 5G-AKA confirmation flow compares RES* and XRES* using strings.EqualFold(). The EAP-AKA' confirmation flow compares AT_MAC using bytes.Equal() and XRES and RES using ==.
Which AUSF versions were confirmed affected?
The issue was confirmed on github.com/free5gc/ausf v1.4.4 and on the current main branch as analyzed in May 2026.