BlackHat is one of the world’s largest cybersecurity events which takes place in the USA in Las Vegas every summer (https://www.blackhat.com/us-18/). Those who have attended BlackHat may have noticed that their badge contains an NFC tag. This NFC tag is scanned at booths in the Business Hall so vendors can collect their marketing data including name, address, company, job title, and phone number. Following BlackHat, attendees who have had their badges scanned by various vendors then receive a barrage of marketing emails. One thing I was not aware of initially was what data was actually contained within the tag itself.
During training at BlackHat this year I was getting frustrated with my badge and lanyard making noise around my neck in training, so I took it off and set it down on the table next to me. Later I set my phone on top of it and saw a notification to read the NFC tag. Out of curiosity I downloaded a tag reader app, looked at the data stored on my tag and made a few observations:
- My email address was not on the tag (at least in plaintext).
- My real first and last name were in the tag and in plain text (not the name I had printed on my badge).
- There were a couple of numbers preceding my name, delimited by a non-printable character.
- There is a bunch of unreadable data after my name (maybe encrypted or other binary data?)
- There is a second record which contains a URL that instructs the user to download the BCard app.
An example of the tag data is shown below:
After looking at the data above, I had a few questions: how are vendors getting my email address? Is all my data stored on the card and only some of it is encrypted? Is there an API I could use to pull the rest of my data? A few days later, I decided to revisit this and downloaded the BCard APK. I used the tool Jadx to decompile the APK to Java, and began grepping through the output for any potential API endpoints.
grep -R "http.*://"
The highlighted output above stuck out almost immediately. You can see that a URL is constructed using a badgeID, and eventID value.
Looking in the code below we can see how those values are constructed. First, the string
qrData is split at
\x1E (30) and set to the
String qr variable. We get the badgeID from the first element in that split. In the image above from the NFC scanner, the
\x1E character is the unprinted character following the first set of digits. Next, we get the badgeID as the first element from the next split at
\x1F (31), the unprinted character immediately following the next set of digits.
Though we can prove this in the code shown above, I simply guessed that those values corresponded to the eventID and badgeID parameters by sending the request in Firefox. To my surprise, I was able to pull my attendee data completely unauthenticated over this API.
Next, I did some math to determine the feasibility of brute forcing all BlackHat attendees. After trying a few hundred requests on both 0-100000 and 000000-100000 and receiving no valid badges, I determined that those were likely not going to be valid ID ranges. We could then assume that valid IDs are 100000-999999. This leaves us with 900,000 total requests. With an estimated 18,000 BlackHat attendees, we can then assume that we will enumerate a valid badgeID in approximately 2% of our requests.
Next, Burp was set up as shown below, with a single insertion point on the badgeID parameter, and a payload type of numbers between the value of 100000 and 999999. I ran my initial test with 30 threads to see if the API would keep up, and it indeed did.
The rate at which we were able to brute force the API would mean that we could successfully collect all BlackHat 2018 registered attendees’ names, email addresses, company names, phone numbers, and addresses in only approximately 6 hours.
After the concept was proved successfully, I began the disclosure process. The ITN team was initially difficult to get in contact with as they do not have a security@ or abuse@ email address, but they were extremely polite, professional, and responsive once I was able to get in contact with the right person. Additionally, they had this issue resolved within 24 hours of initial contact.
- August 9, 2018 – Emailed security@ email address and received a bounce reply.
- August 9, 2018 – Sent a message to COO on LinkedIn.
- August 12, 2018 – Sent a message to System Admin on LinkedIn and received a response from the IT director later that night. We exchanged a few emails with details about this issue, and I was informed that they were going to discuss this issue on Monday.
- August 13, 2018 – I was informed the API had been disabled as it was a legacy system. After re-testing the API, I was unable to pull any BlackHat attendee records.