skip to content

A RADIUS Access-Request carrying Message-Authenticator (80) is captured off a shared medium: what does that attribute stop, and what does RFC 3579 say it does not?

level: seniorimportance: should knowfreq 38%

answer

  1. keyed, unlike the reply digest
  2. the tag cannot cover itself
  3. integrity and origin, never confidentiality
  4. rogue client and online guessing, per RFC 3579
  5. a capture is still guessed offline

basics

~20 s

Message-Authenticator (80) is an HMAC-MD5 over the packet keyed with the shared secret, so it proves the sender held the secret and nothing was altered in flight. RFC 3579 section 3.2 scopes it to thwarting a rogue access device and online dictionary attacks, and states it affords no protection against an offline attack on a capture.

solid answer

~50 s

`Message-Authenticator (80)` carries 16 octets of HMAC-MD5 in an attribute of `Length 18`. The computation covers `Type`, `Identifier`, `Length`, `Request Authenticator` and `Attributes`, with the attribute's **own 16 value octets set to zero** while it runs, and the shared secret as the HMAC key. Because HMAC is a keyed construction, it gives the packet real integrity and origin authentication: an on-path attacker cannot add, remove or alter attributes, and a device that does not hold the secret cannot produce a packet the server will process. RFC 3579 §3.2 states the benefit narrowly — it thwarts a rogue access device and online dictionary attacks — and says explicitly that it **affords no protection against an offline attack**. An attacker holding a capture has the HMAC input and its output, so candidate secrets can be tested locally at full speed.

code

pseudocode · 13 lines
pseudocode
function compute_message_authenticator(packet, secret):
    working = copy_of(packet)
    set working.attribute(Message-Authenticator (80)).value = 16 zero octets

    input = working.Type
          + working.Identifier
          + working.Length
          + working.RequestAuthenticator
          + working.Attributes            // including the zeroed attribute

    return HMAC-MD5(key = secret, data = input)   // 16 octets, attribute Length 18

// receiver: zero the received value, recompute, compare with the saved 16 octets

go deeper

for a junior

Hold on to one contrast: this attribute is a keyed tag over the whole packet, while the Authenticator field in the header is a plain digest.

for a middle

Be able to state the key, the covered fields and the zeroing rule, and to say that it gives integrity rather than secrecy.

for a senior

Quote the scope as narrowly as the specification does, and explain why a recording defeats it: the attacker owns the whole input and the tag, so guessing runs locally.

for a principal

Use it to size residual risk: the tag closes the on-path forgery class across an estate cheaply, and leaves exactly the exposure that justifies funding a transport migration.

## What the attribute is `Message-Authenticator (80)` is a RADIUS attribute of `Length 18`: one octet of type, one of length, and **16 octets of value**. The value is an HMAC-MD5 tag. Unlike the `Response Authenticator`, which is a raw MD5 digest with the secret appended, this is a proper keyed message authentication code, and the difference matters: HMAC's security does not rest on the underlying hash being collision resistant. ## How it is computed `Message-Authenticator = HMAC-MD5(Type, Identifier, Length, Request Authenticator, Attributes)` with the **shared secret as the key**, and with one rule that trips everyone implementing it for the first time: while the HMAC runs, **the attribute's own 16 value octets are treated as zero**. They have to be — the tag cannot cover itself. The sender zeroes them, computes, and writes the result into the field it just zeroed; the receiver zeroes the received value, recomputes, and compares against what it saved. The `Request Authenticator` in the input is the one in the packet's own header for a request, and the corresponding request's nonce for a reply, so the tag also inherits the binding between a reply and the request it answers. ## What it genuinely stops - **Attribute tampering in flight.** Any change to any attribute — adding one, deleting one, rewriting a value — invalidates the tag. Without it, a RADIUS request has no keyed integrity at all. - **A device that does not hold the secret.** A rogue access device cannot mint a packet the server will accept, so it cannot feed the server credential guesses as though it were a legitimate client. - **Online dictionary attacks** in the sense RFC 3579 §3.2 names them: an attacker cannot use the server as an oracle to test guesses, because they cannot get a well-formed packet past it. - **Collision-based reply forgery.** The 2024 result against the `Response Authenticator` — an on-path attacker injecting a chosen `Proxy-State (33)` blob to collide the MD5 digest and turn an `Access-Reject (Code 3)` into an `Access-Accept (Code 2)` — is defeated by the HMAC, which is why "carry it on everything you can" became the standing advice. ## What it explicitly does not stop RFC 3579 §3.2 states that `Message-Authenticator (80)` **affords no protection against an offline attack**, and the reason is structural rather than a shortcoming of HMAC: 1. The attacker records one exchange. They now hold the complete HMAC **input** — every field and attribute is in the clear — and the 16-octet **output**. 2. Guessing is local: take a candidate secret, key an HMAC-MD5 over the recorded input, and compare with the recorded tag. 3. A match confirms the secret. No packet is sent, nothing is rate limited, and the server records nothing because nothing reached it. The same capture also carries the `Request Authenticator` and the hidden `User-Password (2)`, so a confirmed secret unwraps the password as a by-product. | Threat | Covered by Message-Authenticator (80)? | |---|---| | Attribute added or altered on the path | Yes | | Packet injected by a device without the secret | Yes | | Using the server as a guessing oracle | Yes | | Reply forged via an MD5 collision on the Response Authenticator | Yes | | Reading `User-Name (1)` and the other attributes off the wire | No — they were never confidential | | Guessing the shared secret from a recorded exchange | No — RFC 3579 §3.2 says so outright | ## How to hold the claim correctly The common failure is to widen the guarantee into "the packet is now secure". It is not. `Message-Authenticator (80)` gives **integrity and origin authentication**, and adds **nothing** to confidentiality: the account name, the access device's address, the port type and every returned authorization attribute remain readable. A capture is still a roster, and still an offline guessing target. Read that way, the attribute is exactly what it claims to be — the one piece of modern cryptography in a packet built in 1997 — and the residual risk it leaves is the one that motivated the transport work. RADIUS over TLS on TCP port 2083 (RFC 6614) and RADIUS/DTLS on UDP port 2083 (RFC 7360) remove the capture's value by encrypting the exchange, and RADIUS/1.1 (RFC 9765, Experimental) removes the shared secret that offline guessing targets. Both transport documents are Experimental, which is a real consideration when a field estate is being committed to one.

  • Why is the attribute's own value zeroed during the HMAC computation?
    Because the tag is computed over the packet that will carry it, and a tag cannot cover itself — the input would depend on the output. Zeroing those 16 octets gives sender and receiver one deterministic input they both reproduce, after which the sender writes the result into the space it zeroed.
  • If the Response Authenticator already exists, why add a second keyed field?
    They cover different things and differ in construction. The Response Authenticator protects a reply and is a raw MD5 digest with the secret appended, so a collision attack bites. Message-Authenticator (80) is a keyed HMAC that protects a request's attributes as well, and it is not broken by the same collisions.
  • Does carrying Message-Authenticator (80) reduce the value of a recorded exchange to an attacker?
    Only slightly. It removes the ability to modify or inject packets, but the recording is unchanged: the attributes were never confidential, and the tag itself is one more input-and-output pair to guess the secret against offline. RFC 3579 section 3.2 says so explicitly rather than leaving it to inference.

saying these in an interview costs you the question

  • Says it makes the RADIUS packet confidential
  • Claims it protects the secret against offline guessing
  • Computes the HMAC with the attribute's value left in place
  • Assumes MD5 collisions forge an HMAC-MD5 tag
  • Treats it as interchangeable with the Response Authenticator