Research Blog & News

Hacking Barcodes for Fun & Profit...

Balazs Bucsay / 2024-11-19 09:05:52

Our consultants at Mantra identified a critical flaw in a European Deposit Return System (DRS), which could allow a malicious actor to exploit the system for unlimited monetary gain. This article outlines our investigative process and offers a practical recommendation for addressing this vulnerability. The proposed solution should be technically feasible within the existing framework, enhancing the security and reliability of the DRS.

Disclaimer: The title of this post reflects a common style of naming in the tech community. No fraudulent activity was conducted in this research. Not by us, at least!
Our aim is to highlight potential areas for improvement in this particular collection/recycling environment, with no intent to disrupt or block the existing system. After careful consideration and responsible disclosure to the relevant company, we’re sharing our findings to promote awareness and refinement in barcode-based recycling methods.

The European Union created the Directive 2019/904 that deals with the reduction of certain plastic items including single use plastic (SUP). It demands that the member countries collect the 90% of SUP that are sold for recycling. Sounds great, although PET recycling seems to be a lie (glass and aluminium is not) anyways, but institutionalised collection is definitely the right step forward.

Many EU countries have implemented deposit return systems, where customers pay a small deposit on plastic bottles (and cans) that’s refunded when they return the empty bottles at collection points. This system has existed for years in some regions, while others have adopted it only recently. One particular country introduced the system this year, where our consultants had the chance to collect some experience with the process.

The collection process is straightforward. Customers take undamaged bottles to collection machines, place them on the carousel, and the machine scans the barcode. If the barcode can be found in the internal database, the machine accepts the bottle and adds the deposit to the customer’s balance. The more bottles returned, the higher the balance accumulates. There are several ways to redeem this balance:

  • Donate it to charity
  • Transfer it to a specified bank account
  • Receive a printed voucher for the amount
Option 3, the printed voucher is by far the most popular. The voucher itself is quite simple, alongside the shop’s logo, details of the returned bottles, and the total amount, there’s also a barcode included.

The voucher - irrelevant bits blurred

If you take a closer look at the picture, you’ll notice that the barcode is a simple linear one, which is wider than usual, also right beneath the barcode, there’s a long sequence of numbers. Like most 1-dimension (1D) barcodes, this barcode encodes a sequence of number in a format that is readable by scanners, by using the various thin and thick stripes to represent data. The number below the barcode is the same as the one encoded within, printed for easy reading for humans. If you’ve ever took a look items in a store, you’ve likely seen a similar setup, known as EAN-13.

When looking at the number itself, you might see that part of the barcode (the number) directly corresponds to the voucher’s value.


Value highlighted

Oh, wait, does this mean you can just change that number to alter the balance on the voucher?
Not exactly! At least, not immediately.

After collecting more samples through regular use, we noticed a clear pattern in the barcodes:

  • Digits 01..03: 981 - Identifies this as a GS1-related coupon code
  • Digits 04..09: Shop identifier
  • Digits 10..11: Machine identifier
  • Digits 12..19: A stripped-down epoch timestamp
  • Digits 20..25: Voucher's value (amount)
  • Digit 26: Check digit


The two key parts in the voucher code are the amount and the check digit. For context, a check digit is an error-checking code used to confirm that a sequence of numbers is valid. You might be familiar with this concept from debit or credit cards (Visa, Mastercard, Amex), which use the Luhn algorithm. This algorithm allows you to calculate the last digit of your card number based on the preceding ones, allowing systems to catch errors from mistyped digits before attempting a transaction. Similarly, the final digit in this voucher code serves as an error-checking mechanism, enabling vendors to validate codes at the till.

However, the Luhn algorithm and similar error-checking codes were not designed for security, nor are they capable of it. Since the Luhn algorithm is publicly known and accessible, anyone can easily create valid-looking card numbers (though these cannot be used for real transactions).

These vouchers do not use the Luhn algoritm, but they use something really similar. If someone were able to reverse-engineer the error-checking code for these vouchers, they could theoretically generate valid codes with custom amounts. Challenge accepted!

A bit of mathematical knowledge goes a long way with challenges like these. After some focused work, we cracked the error-checking code and implemented it in Python. By providing any code from a voucher (excluding the check digit), the program will calculate the correct check digit, therefore generating a valid code. This means that we could change the amount in the voucher code and generate a new valid voucher. Of course the barcode itself, the stripes can be generated using open-source tools or online resources.

For example, here is a barcode we found on Facebook, posted publicly by a fustrated user who was displeased with the system:

This voucher shows that 21 bottles were returned, with a total value of 1050 and the error-checking code is 6. To test our Python script, we input all the numbers except for the last digit to verify the correctness of our error-checking code calculation:

Following this logic, we generated another valid sequence with a value of 105 instead of 1050. This adjustment purely demonstrates that such manipulation is possible without any intent to exploit the system. Our goal is to highlight this flaw responsibly and advocate for improved security measures:

We do not plan to release neither the Python script nor the underlying mathematical formula, as doing so could facilitate fraudulent activity within the system. Recreating these tools from scratch would require substantial research and advanced knowledge. At Mantra, we are committed to ethical research practices and oppose any form of system abuse. Our investigation was purely theoretical, based on empirical evidence and aimed solely at identifying potential vulnerabilities for responsible disclosure.
Furthermore it's important to note that exploiting the current system requires more than just generating valid number sequences. For example, the vouchers are printed on special, watermarked paper, which adds another layer of security to prevent misuse.

Solution to the Problem

The issue originates from the fact that the value of the voucher is hardcoded directly into the barcode. This setup lacks any security mechanisms to prevent offline attacks. Essentially, if someone is able to generate or manipulate the barcode, they can alter the voucher's value without any immediate detection. The most viable solution would involve replacing the hardcoded value with random identifiers that don't carry any inherent meaning. These random numbers would be generated at the time of printing and stored securely in a central database. When a voucher is presented, the shop's system could verify its validity by checking the central database online, ensuring that only legitimate vouchers are accepted. While this approach could require additional resources and time to implement, it would significantly enhance security and prevent unauthorized manipulation of voucher values.

Responsible Disclosure

We have reached out to the company responsible for maintaining the machines and the underlying infrastructure. After a significant wait, they acknowledged the flaw and stated that they monitor all transactions. However, further questioning revealed that the codes are not monitored online in real-time, which raises concerns about the effectiveness of this defense mechanism. In our final communication, the company reassured us that their team is continuously working on solutions to reduce abuse of the system. Hopefully, this means they will implement our suggested fix, which could lead to the system being operated with minimal abuse in the future.

Conclusion

Barcodes alone are insufficient for secure data protection and should not encode sensitive details, such as a voucher’s value. A secure approach would involve generating a unique random identifier for each transaction when a voucher is issued, which could then be verified upon redemption. Although this suggestion, along with other potential solutions, was raised with the company, we have yet to receive a response addressing its feasibility within the current infrastructure. Additionally, a review of vouchers from other EU countries suggests that this issue might be more widespread than initially anticipated.

Timeline

  • 18/07/2024 - Initial contact made on their contact address.
  • 29/07/2024 - Follow-up sent, as no response was received.
  • 09/08/2024 - Second follow-up sent.
  • 12/08/2024 - Our initial email was forwarded to the customer service
  • 26/08/2024 - Received a generic email response, which did not address the issue specifically.
  • 29/08/2024 - Original questions were resent once more.
  • 02/09/2024 - Company confirmed they do not track transactions online, only monitor machine usage.
  • 02/09/2024 - Reiterated the issue with a different approach to emphasize the security risks.
  • 06/09/2024 - Received a non-specific response.

  • 04/11/2024 - News released regarding delays in voucher redemption. This may be relevant to the vulnerability report findings.



Contact

Contact Us

Location:

London, United Kingdom

Loading
Your message has been sent. Thank you!