Laundry token hack via DS1992 iButton data backup (and restore)

The system

In the dormitory I was living, they had prepaid laundry machine tokens: You had to charge them by paying real money, and then you could operate all laundry machines by paying with that token.

For operating a machine, you had to hold your token against the machine for some seconds; this transferred a fixed amount of money from your token to the machine. The display showing your temporary credit counted backwards during operation. After the machine had finished, you could place your token on the machine again and the remaining amount was refunded.

Security issue

The security of the whole system is based on the assumption that the user doesn't have access to a soldering iron. The money tokens are just DS1992 iButtons: simple 1-wire-attached 1 kbit memories, with no tamper-proof-counters or authentication measures.

Since the data sheet is publically available, it's not difficult to build a small device that is able to dump the memory of these tokens, and to write these dumps (or, arbitrary data, actually) to the tokens. This allows the user to backup the contents of the token before paying, and restoring this backup afterwards.

However, when looking at the dumps after multiple transactions, there are multiple blocks of data that contain some probably-encrypted data, and a 4-byte-counter which decreases after every transaction. That way, it would be possible for a laundry machine to detect the tampering (by keeping a database of (userid, counter) tuples), and to possibly invalidate the token. I haven't tried whether they actually do this, because there's a way to circumvent that safety measure:

The dorm has multiple laundry machines, and they seem to not communicate with each other (at least, they don't have a LAN connection or similar, and they look too old for WiFi). The tokens contain, except for the always-decreasing counters, not enough non-constant fields to have one encrypted anti-tamper-counter for each machine, so I assume that the tamper detection algorithm is like this:

when machine #i sees token #j:
    if token.counter <= machine.last_known_counters[j]:
        somehow decrypt the probably-encrypted area
        check some kind of checksum
        if checksum ok:
            perform the transaction
            token.counter--
            machine.last_known_counters[j] = token.counter
        else:
            tampering detected!
        end if
    else
        tampering detected!
    end if

Using a single counter, combined with no communication between the machines, is a fatal security flaw. That way, it's possible for a user to do the following:

This allows for infinite free laundries, and might even allow you to charge your tokens "for free".

Proof of concept

With a small ATmega8 board, the token can be read from and written to. The firmware is here.

For documentation, please refer to the source code and the README file

The actual interesting part about this was that I had no proper hardware at hand. This resulted in a "creative" setup using a tiny USB AVR Lab board and some hacks regarding the 1wire implementation.

Possible fixes

It would be quite easy to store one counter for each machine in the probably-encrypted area, if they would use the full 1 kbit the chip offers. That way, restoring any backup would permanently block the token on one machine, effectively limiting the amount of free laundrys to the number of machines available. This could have been done without any changes in hardware, just by software.

Alternatively, they could, as recommended by the data sheet, have used a DS1994 instead, which offers tamper-proof counters, which can only be counted down, but not up. This would at least prevent a simple restore-attack. However, a mildly talented person could still build a device that acts like the DS1994, but allows to actually tamper with the tamper-proof counters.