802.1x

WN Blog 026 – 802.1x & EAP

Hey, 

Welcome to our latest WiFi Ninjas Blog – this time we will be covering what is 802.1X & EAP! 

802.1X is a Port Based Network Access Control, defining 3 roles: Supplicant (station, client device), Authenticator (AP or WLC) and Authentication Server (RADIUS).

Extensible Authentication Protocol (EAP) is the authentication framework supporting multiple methods such as PEAP, EAP-TLS, EAP-TTLS & more. It’s a datalink layer protocol, IP is not required. Additionally, Authenticator does not have to understand the authentication method.

RADIUS carries AAA information between Authentication and RADIUS Server.

Supplicant and Authenticator use EAPOL in wireless to exchange authentication data.

Authenticator and Authentication Server talk over RADIUS.

Both parts (EAPOL + RADIUS) form an authentication mechanism called 802.1X.

Let’s see step by step what happens in the 802.1X EAP process:

Open System Authentication:

  1. First the client and the AP go through 802.11 Open System Authentication, that is made up of 2 frame exchanges – client sends open auth to the AP & then the AP responds with open auth success.

802.11 Association:

  1. Next in the frame exchange is 802.11 Association, this is also 2 frame exchanges – client sends association request to the AP & then the AP responds with an association response.

802.1x EAP Authentication (below is based on EAP-TLS, but it will be similar for other EAP methods):

  1. Now we move on to the juicy part of the frame exchanges – “802.1X EAP authentication”. The first frame in this exchange is from the client which sends an “EAPOL start message” to the AP to start EAP authentication.
  2. The client is then asked for its identity in an “EAP Request/Identity” message from the AP.
  3. The client replies with an “EAP Response/Identity” message with its (dummy) user ID and the request to use TLS, which is forwarded to the RADIUS server.
  4. The RADIUS server, upon receiving the RADIUS access request & RADIUS access challenge (EAP Response/Identity message), starts the server-side TLS process by sending an EAP-TLS Start message to the client. 
  5. The client responds with an EAP response – client hello message.
  6. The RADIUS server replies with an EAP Request message— a TLS server hello. It provides its certificate to the client, TLS protocol version, a cipher suite, and the client requests the certificate. 
  7. The client validates the server certificate and responds with an EAP Response message that contains its certificate. This message starts the negotiation for cryptographic specifications – the cipher and compression algorithms.
  8. After the client certificate is validated, the RADIUS server responds with cryptographic specifications for the session. 
  9. The client responds with an EAP-Response packet of EAP-Type = EAP-TLS with no data, notifying the RADIUS server that it has received the cryptographic specifications. 
  10. The RADIUS server sends an EAP-Success message to the AP indicating successful authentication.  
  11. The RADIUS server creates the session Master Key, also known as the PMK (Pairwise Master Key). 
  12. The client also creates the PMK. 

4-Way Handshake:

  1. The client and the AP run the 4-way handshake to create the session keys. Which are:
    • EAPOL Key Packet No.1(Authenticator Nonce) – Client calculated PTK
    • EAPOL Key Packet No.2 (Supplicant Nonce, MIC) – Authenticator calculated PTK
    • EAPOL Key Packet No.3 (Install PTK, MIC, Encrypted GTK)
    • Now we have the GTK (Group Temporal Key) encrypted in the PTK.
    • EAPOL Key Packet No. 4 (MIC)
  2. Voila! We now have fully established an encrypted 802.1X EAP-TLS session!

We have also made a diagram of the process so you can visualise the above a bit easier! 

We hope that you found this blog helpful for you and always give us a shout if you need anything else!

Tons of love,

WiFi Ninjas x 

WN Blog 012 – Can You Crack 802.1X WPA2-Enterprise Wireless Data?

One of our clients has recently approached me with
concerns about their new WiFi network that we were planning to put in. They were coming
from a wired-only environment and were not sure if introducing EAP-TLS based
corporate wireless was a good and safe idea. Additionally, while preparing for
my CWAP exam I heard in one of the course videos that “you can’t decrypt
802.1x EAP, as there is no known key that we can enter to start 4-way handshake”
.
But is it really the case?

I will answer this question by first touching on the 802.1X EAP
authentication framework recap
that will help us understand conditions
that must be met, and steps taken to decrypt WPA2-Enterprise data.

All modern EAP variations are using strong CCMP encryption. Instead of attacking it, we will focus on capturing RADIUS packets on the wire and extract a PMK from this transaction. We will then capture 4-way handshake to get Anonce and Snonce and use it together with PMK, Supplicant MAC and Authenticator MAC to derive PTK (Wireshark can do it for us) used to decrypt our wireless session.

802.1X EAP Recap

IEEE 802.1X is a
standard for Network Access Control. It provides authentication (making sure
that something is what it claims to be) mechanism to devices wishing to connect
to a LAN or WLAN. 802.1X defines the encapsulation of the Extensive
Authentication Protocol (EAP) over IEEE 802, that is known as EAP over LAN
(EAPOL). 802.1X defines 3 roles: Supplicant (client), Authenticator/NAS (AP)
and Authentication Server (RADIUS). Successful EAP transaction starts a process
of 802.11 Security Keys Generation, that I tried to visualise in a
diagram below, together with 802.11 Open Authentication, 802.11
Association
, Tunnelled EAP Authentication and a 4-Way Handshake,
collectively being part of an 802.1X standard.                   

802.1X EAP and 802.11 Security Keys Generation Process
802.1X EAP and 802.11 Security Keys Generation Process

Conditions

The following conditions must
be met to decrypt 802.1X EAP encrypted captures:

1. RADIUS key must be known

  • Brute
    force against the RADIUS capture is an option but strong RADIUS key would make
    it unpractical. Make sure the key is strong!
  • Social
    engineering attack – get network engineer’s contact details and ask him/her
    about a RADIUS key saying you’re from NOC tshooting an issue or a contractor
    working on upgrading RADIUS server and see what happens. Make sure
    staff is trained how to handle social engineering attacks
     and that
    their contact details like phones, mails and positions within the company are
    well secured!
  • Access
    to RADIUS server – some mainstream RADIUS servers (MS NPS, FreeRADIUS) store
    the key unencrypted in a file. Cisco ISE can show you password when you’re
    logged in. Make sure access to the RADIUS servers and logon credentials
    are properly secured!

2. Wireless capture of the session that we want to decrypt must be taken

  • Session
    must include 4-way handshake, so must include both packets coming from the
    client and AP, meaning that the potential attacker would need to be physically
    close to both. 

3. Wired capture of RADIUS authentication must be taken

  • Capture
    of RADIUS authentication on the wire is essential, as PMK is never sent over
    the wireless, so it can’t be eavesdropped. We’ll extract it from RADIUS wired
    captures.
  • Capturing
    RADIUS traffic would require physical access to the LAN to plug a collector
    into or access to the network infra to configure SPAN. Make sure that the
    admin access to the network equipment is secure and that all infrastructure is
    physically locked!

Lab Environment

Here is the lab
setup and capture locations (both wired and wireless):

  • Wireless
    Captures: Cisco AP in sniffer mode placed between my wireless test client and
    client serving AP, configured to send captures to my Windows Server VM running
    Wireshark.
  • Wired
    Captures: Cisco switch with SPAN monitoring session and port facing my ESXi
    server (with Cisco ISE RADIUS VM running there) being a SPAN source and switch
    port facing my laptop being a SPAN destination.
Lab Network Diagram
Lab Network Diagram

Steps

Here is a high-level
summary of what we need to do to decrypt our WPA2-Enterprise wireless session:

  • Extract
    PMK
    with wired RADIUS
    captures; use RADIUS Shared Secret, Request Authenticator from the final
    Access-Request RADIUS frame and MS-MPPE-Recv-Key from the RADIUS Access-Accept
    frame.
  • Capture
    4-Way Handshake
    with
    wireless captures.
  • Use
    extracted PMK and 4-Way Handshake to derive PTK with Wireshark and use
    it to decrypt user data.

Note: PTK is valid
only for the duration of a single session. Session timeout, new association or
re-association (roaming) would require to derive new PTK!

Assuming all conditions are met, let’s crack
on!

1. Obtain RADIUS key

  • Since I’m using ISE, here is where I would look to get it:
RADIUS key configured in Cisco ISE
RADIUS key configured in Cisco ISE

2. Start capturing wireless traffic of interest

  • Position capturing device so it can capture both wireless client and AP
    traffic.

3. Start capturing wired RADIUS traffic between the Authentication Server and the Authenticator

  • Ensure to capture full RADIUS exchange for the wireless device
    authentication.

4. Connect wireless device to the EAP SSID

  • If it’s your test device, disconnect and then connect again.
  • If it’s not your test device, you could try to force the device to re-connect by sending a de-auth; SSID must not use management frames protection mechanism, and they usually don’t for compatibility reasons.

5. Obtain Authenticator from the last Access-Request packet in wired RADIUS capture

  • Go to RADIUS Protocol > Authenticator.
  • Here it’s 00:0d:42:73:f6:19:5c:d3:88:73:cf:b3:2c:76:5d:16 (you
    can copy value in hex straight from the capture).
Authenticator value from Access-Request wired RADIUS capture
Authenticator value from Access-Request wired RADIUS capture

6. Obtain MS-MPPE-Recv-Key from the Access-Accept packet in wired RADIUS capture

  • Go to RADIUS Protocol > Attribute Value Pairs > AVP: t=Vendor
    Specific (last one)
  • Here it’s cf:6f:b5:06:da:57:b1:9c:e4:6d:76:af:93:51:59:7e:2c:f8:cd:79:c6:2b:e1:a5:4f:ab:28:bd:ed:d3:81:d3:a9:57:dd:74:f8:d1:41:b8:ec:50:ea:d7:27:75:85:d3:1e:d3
MS-MPPE-Recv-Key value from Access-Accept wired RADIUS capture
MS-MPPE-Recv-Key value from Access-Accept wired RADIUS capture

7. Compile PMKextract code, that we will use to extract PMK

  • I used Visual Studio in Windows to build the code mentioned earlier. There are also Python versions of similar code available but since I’ve already had Visual and it worked, I focused on this approach.
  • Create a new C++ project/file in Visual and paste this code:
#include <stdio.h>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#define _WIN32_WINNT 0x0400
#include <wincrypt.h>

typedef unsigned int u32;
typedef unsigned char u8;

//
// This debugging function can be found in wpa_debug.c from the hostap package
//
//extern void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);

#define os_malloc(s) malloc((s))
#define os_free(p) free((p))
#define os_memcpy(d, s, n) memcpy((d), (s), (n))
#define MD5_MAC_LEN 16

static void cryptoapi_report_error(const char *msg)
{
 char *s, *pos;
 DWORD err = GetLastError();

 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
     FORMAT_MESSAGE_FROM_SYSTEM,
     NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) {
   printf("CryptoAPI: %s: %d", msg, (int) err);
 }

 pos = s;
 while (*pos) {
  if (*pos == '\n' || *pos == '\r') {
   *pos = '\0';
   break;
  }
  pos++;
 }

 printf("CryptoAPI: %s: %d: (%s)", msg, (int) err, s);
 LocalFree(s);
}

int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
     const u8 *addr[], const size_t *len, u8 *mac)
{
 HCRYPTPROV prov;
 HCRYPTHASH hash;
 size_t i;
 DWORD hlen;
 int ret = 0;

 if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) {
  cryptoapi_report_error("CryptAcquireContext");
  return -1;
 }

 if (!CryptCreateHash(prov, alg, 0, 0, &hash)) {
  cryptoapi_report_error("CryptCreateHash");
  CryptReleaseContext(prov, 0);
  return -1;
 }

 for (i = 0; i < num_elem; i++) {
  if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) {
   cryptoapi_report_error("CryptHashData");
   CryptDestroyHash(hash);
   CryptReleaseContext(prov, 0);
  }
 }

 hlen = hash_len;
 if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) {
  cryptoapi_report_error("CryptGetHashParam");
  ret = -1;
 }

 CryptDestroyHash(hash);
 CryptReleaseContext(prov, 0);

 return ret;
}

int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
 return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
}

static u8 * decrypt_ms_key(const u8 *key, size_t len,
      const u8 *req_authenticator,
      const u8 *secret, size_t secret_len, size_t *reslen)
{
 u8 *plain, *ppos, *res;
 const u8 *pos;
 size_t left, plen;
 u8 hash[MD5_MAC_LEN];
 int i, first = 1;
 const u8 *addr[3];
 size_t elen[3];

//wpa_hexdump_key(1, "key", key, len);
//wpa_hexdump_key(1, "secret", key, len);
//wpa_hexdump_key(1, "auth", req_authenticator, MD5_MAC_LEN);

 /* key: 16-bit salt followed by encrypted key info */

 if (len < 2 + 16)
  return NULL;

 pos = key + 2;
 left = len - 2;
 if (left % 16) {
  printf("Invalid ms key len %lu\n", (unsigned long) left);
  return NULL;
 }

 plen = left;
 ppos = plain = (u8*)os_malloc(plen);
 if (plain == NULL)
  return NULL;
 plain[0] = 0;

 while (left > 0) {
  addr[0] = secret;
  elen[0] = secret_len;
  if (first) {
   addr[1] = req_authenticator;
   elen[1] = MD5_MAC_LEN;
   addr[2] = key;
   elen[2] = 2; /* Salt */
  } else {
   addr[1] = pos - MD5_MAC_LEN;
   elen[1] = MD5_MAC_LEN;
  }
  md5_vector(first ? 3 : 2, addr, elen, hash);
  first = 0;

  for (i = 0; i < MD5_MAC_LEN; i++)
   *ppos++ = *pos++ ^ hash[i];
  left -= MD5_MAC_LEN;
 }

 if (plain[0] == 0 || plain[0] > plen - 1) {
  printf("Failed to decrypt MPPE key\n");
  os_free(plain);
  return NULL;
 }

 res = (u8*)os_malloc(plain[0]);
 if (res == NULL) {
  os_free(plain);
  return NULL;
 }
 os_memcpy(res, plain + 1, plain[0]);
 if (reslen)
  *reslen = plain[0];
 os_free(plain);
 return res;
}

void processTokens(char*  authenticator,
       u8*   processedAuthenticator,
       char*  recvKey,
       u8*   processedRecvKey )
{
 // Handle authenticator
 char* ptr = strtok( authenticator, ":");
 int i = 0;
 while( ptr )
 {
  processedAuthenticator[i++] = ( u8 ) strtoul( ptr, NULL, 16 );
  ptr = strtok( NULL, ":");
 }

 // Handle key
 ptr = strtok( recvKey, ":");
 i = 0;
 while( ptr )
 {
  processedRecvKey[i++] = ( u8 ) strtoul( ptr, NULL, 16 );
  ptr = strtok( NULL, ":");
 }
}

void dumpPmk( const u8*  pmk )
{
 printf( "PMK is:\n" );
 for( int i = 0; i < 32; i++ )
  printf( "%02x", pmk[i] );
 printf( "\n" );
}

int main(int argc, char*argv[])
{
 if( argc != 4 )
 {
  printf( "Usage: %s secret authenticator recv-key", argv[0] );
  return( 1 );
 }

 if( strlen( argv[2] ) != 47 )
 {
  printf( "Bad authenticator length" );
  return( 1 );
 }

 if( strlen( argv[3] ) != 149 )
 {
  printf( "Bad recv-key length" );
  return( 1 );
 }

 u8 processedAuthenticator[16];
 u8 processedRecvKey[50];
 u8* pmk;
 u32 pmklen = 0;

 processTokens(argv[2], processedAuthenticator, argv[3], processedRecvKey );

 pmk = decrypt_ms_key(processedRecvKey, 50,
      processedAuthenticator,
      (u8*)argv[1], strlen(argv[1]), &pmklen);

 dumpPmk( pmk );

 os_free(pmk);

 return(1);
}
  • Save .cpp file. I saved it as “PMKextract.cpp”:
 Adding PMKextract.cpp to the Solution Explorer
Adding PMKextract.cpp to the Solution Explorer
  • If you try to build it now, you’d probably see the error:
Unsafe function or variable warning
Unsafe function or variable warning
  • To allow project to build successfully, add _CRT_SECURE_NO_WARNINGS
    under Project -> Properties -> C/C++ -> Preprocessor ->
    Preprocessor Definitions
    :
Allow project built by modifying Preprocessor Definitions
Allow project built by modifying Preprocessor Definitions
  • Build > Build project should now be successful:
Successful build of the PMK extracting code
Successful build of the PMK extracting code

I then copied compiled ‘Project1.exe’ file to C:\Geekwifi and renamed it to ‘PMKextract.exe’.

8. Extract PMK

  • Navigate to the location of your PMKextract.exe file. It takes all
    required attributes as shown:
PMKextract usage
PMKextract usage
  • Get the PMK:
Extracting PMK using all values that we gathered: RADIUS secret, authenticator and Recv-Key
Extracting PMK using all values that we gathered: RADIUS secret, authenticator and Recv-Key

9. Specify decryption key in wireless captures in Wireshark

  • Finally, open wireless captures and use our extracted PMK as
    a wpa-psk key.
Provide Wireshark with extracted PMK in ‘Edit > Preferences > Protocols > IEEE 802.11 > Decryption keys > Edit’
Provide Wireshark with extracted PMK in ‘Edit > Preferences > Protocols > IEEE 802.11 > Decryption keys > Edit’

10. Enjoy decrypted wireless captures!

  • We can see all the usual stuff – probes, authentication and association
    requests and responses, EAP process with EAP Success at the end, 4-way
    handshake and then decrypted data. Happy days!
Decrypted 802.1X WPA2-Enterprise session
Decrypted 802.1X WPA2-Enterprise session

Conclusion

Properly configured
and physically secured WPA2-Enterptise wireless network, especially where
client and server certs are involved, is still considered highly secure. Specific
conditions must be met to decrypt 802.1X EAP wireless session captures, where
RADIUS key must be known, and the attacker would have to be able to capture RADIUS
conversation on the wire and 4-Way Handshake on wireless to make it possible. Additionally,
decrypting WPA2-Enterprise session does not necessarily mean we could eavesdrop
on the meaningful user data, as it might be encrypted on a data level, i.e.
using TLS or SSL, that do not rely on WiFi infrastructure encryption.

Literature