RADIUS PAP Authentication – RADIUS Frames Verification with WireShark

Decrypt Radius Access Request

This post is about in depth understanding of how the Radius Protocol creates Radius PAP Access Request, also learn how the User-Password and Message-authenticator gets created for the Radius Access Request frame in PAP.

We will have multiple posts about this Radius PAP authentication and RADSEC related posts, so we will refer this post to understand the future posts related to RADIUS over TLS1.2 and TLS1.3. Please make sure that you are able to understand this post better.

Though the RADIUS-PAP is insecure, we will be able to provide the security for these PAP frames if the RADIUS packet is being sent in a RADSEC TLS 1.2/1.3 tunnel. In the future posts we will learn about how the RADSEC tunnels will be created for Radius Frames and we will learn in depth understanding of these RADSEC Tunnels.


We will take the Radius Access request frame from wireshark and we will verify the RADIUS attributes for PAP.

  1. PAP is considered a weak authentication mechanism and should be only used in the trusted/controlled networks. RADIUS PAP uses md5 based authenticators, and it is proven to be insecure.
  2. We will be able to provide security for the PAP frames, if frames are being sent in a RADSEC TLS tunnel.
  3. It uses 2-way Hand Shake.

Below Figure 1 shows the Radius PAP call flow.

Figure 1 : Radius PAP Authentication (2-way Hand Shake)

Now we will take the Radius Access Request for PAP frame and we will check how the password and authenticators get encrypted.

Decrypt Radius Access Request – PAP

The below Figure 2 is the RADIUS PAP request frame. In the below figure observe that only the User-Password is encrypted and most of the attributes are in clear text. Now we will verify the generated password and the Message-authenticator for the full RADIUS frame and compare the result with the wireshark.

Note that Authenticator is different from Message-Authenticator in RADIUS Access Request Frame on PAP. Authenticator is in clear text and it will be randomly generated for each frame, Message-Authenticator is MD-5 checksum for full RADIUS frame.
Figure 2 : RADIUS Access Request – PAP

In our case the shared secret is “praneeth“.

Login credentials for the PAP are

User name : praneeth@123

Password : praneeth@123

In the above Figure 2, we will be able to see that user name attribute is in clear text and most of the attributes are in clear text. The User Password is encrypted. We will use the below program to generate the user password and we will compare the result with wireshark.

Generating and verifying the Encrypted User Password

The below are the input to the function that has been defined in the RFC 2865 to generate the User-Password Attribute.

  1. Password
  2. Shared Secret
  3. Authenticator (This authenticator is not md5 check sum, it is a plain random text, get it from wireshark)

In our example

Password = praneeth@123

Shared Secret= praneeth

Authenticator = Observe the sniffer capture it is (de7d307c4be8ca034f738aed6e0208b4)

Below python code snippet is used to generate the User-Password on PAP Radius Access Request.

password += b'\0' * (16 - (len(password) % 16))

result, last = b'', authenticator
while password:
        hash = md5(secret + last).digest()
        for i in range(16):
            result += chr(ord(hash[i]) ^ ord(password[i]))
        last, password = result[-16:], password[16:]
print("User Password Is :  {} ".format(result))

Once you execute the above program you will get the below output. And observe the User-Password that got generated and compare it with the Wireshark, both matches.

Figure 3 : Output of a python Program and the wireshark capture

This is how the User-Password in RADIUS Access Request frame gets generated.

Generate MD5 Authenticator for RADIUS Access Frame

Now we will verify the the MD5-authenticator for the full RADIUS Frame.

The below are the input to the md5 program.

  1. Full RADIUS Hex Stream (We will get it from Wireshark, replace the already existing Message-Authenticator with all zeros)
  2. Radius Secret (In our case it is “praneeth”)

Execute the below command in any linux terminal, you will be able to generate the MD-5 authenticator of RADIUS Frame.

echo -n '010900a7de7d307c4be8ca034f738aed6e0208b4010e7072616e656574684031323304060a2399bee21f1346462d41412d41412d41412d41412d30311e1330302d31302d46332d32362d43302d30434d17434f4e4e45435420556e6b6f6e776e20526164696f08060a219e1ea6b974d5e37310501200000000000000000000000000000000' | xxd -r -p | openssl dgst -md5 -mac HMAC -macopt key:praneeth

Figure 4 : Output of a RADIUS Frame Authenticator

In case of Wrong User-Password in Request Packet, RADIUS Server will send RADIUS-ACCESS-REJECT to the Radius client.

If the Client is using the wrong shared secret , then there will be Message-Authenticator failure, RADIUS server will simply drop the packets even if Encrypted User-Password is correct.

This is all about Radius Access Request frame construction on PAP.

Decrypt Radius Access Accept/Reject

Till now we have learnt the Radius PAP Access Request Construction. Now we will learn about the Radius Access Responses construction and verification. We will take the example of a Radius Access Accept in this post.

Note that input to the MD5 program is little different in Radius Access Response frames.

Below Figure 5, shows the Radius Access Accept Frame.

Note that Authenticator in in the Radius Access Request is plain text and it is a randomly created data, But the Authenticator in Radius Access Response is md5 hash of a RADIUS frame.

Figure 5 : Radius Access Accept

Below is the input to the Md5 algorithm in Radius Access Response.

We will get RequestAuth from the Radius Access Request frame.

  1. Code
  2. ID
  3. Length
  4. RequestAuth (Radius Access Request Authenticator, get it from sniffer cap on Access Request)
  5. Attributes
  6. Secret

Based on the sniffer captures, Below is the data that we need to send to the Md5 program.

Note the Request Authenticator you can get from the Radius Access request frame shown in Figure 2.

  1. Code = 02
  2. ID= 09
  3. Length=001a
  4. Request Auth = de7d307c4be8ca034f738aed6e0208b4 (ACCESS Request Authenticator from Figure 2)
  5. Attributes = 550600000258 (Get it from Accept Packet)
  6. Secret= 7072616e65657468 (Here Secret is in Hex data, In our case shared secret is “praneeth“)

Now concatenate all the data and send the hex input to the md5 program. We will be able to generate the authenticator in Radius Access Accept Frame.

Execute the below command in any linux terminal, you will be able to generate the md5 authenticator for the Radius Access Frame.

echo -n '0209001ade7d307c4be8ca034f738aed6e0208b45506000002587072616e65657468' | xxd -r -p | openssl dgst -md5

Observe that the output of a md5 program matches with the authenticator seen in the Radius Access Accept frame.

Figure 6 : Md5 Authenticator for Radius Access Accept

In the next post we will learn about creating radius accounting packets request and response frames.