Free Parking for Life
Disclaimer: I am not responsible for anything you do with this information.
This post was originally published in 2017.
As I entered the parking lot, I took out my parking ticket and put a sticker on it to validate my parking. My company buys stickers for parking validation which cost around $10 each. Looking a bit more at the stickers, I realized that if I knew how to generate those stickers, I could just park for free.
Those stickers had a simple “Interleaved 2 of 5” 1D barcode on them. I went home and took a picture of those barcodes, and uploaded them to an online barcode scanner which identified the barcodes automatically and printed out the digits on them. I had a lot of them since we bought those stickers in batches for our guests.
Those were the numbers I got:
To generate an additional barcode, you would need two things:
1) Know the next probable valid serial number you could use.
2) Know how to generate a valid barcode.
In our case, it is easy to see that the first 8 digits are the serial number, and the last 4 digits are sort of a validation mechanism. Doing #1 is easy, we just need to keep on counting to the next one and we would be likely able to generate a barcode in the correct series. However, #2 is a bit tricker.
I had to start investigating the last 4 digits and their connection to the first 8. Two pairs of barcodes did help me to figure that out. The first one is this:
As you can see, the last 4 digits here are the same, whereas the first 8 digits have the same digits. We can probably assume that the algorithm for generating the last 4 digits is “commutative” in nature, meaning that the order of the objects does not change the calculation. Addition and binary gate operations are two examples of such operations. Another thing we can understand is that the calculation is probably done on a per-digit basis.
The second pair which caught my eyes was this one:
This time, the connection is not immediately trivial, but one might ask how come 1 and 9 together are the same as 4 and 6 together? You guessed it, the operation is addition. When adding up the digits we get the same number. In this case, 3+1+9+1+9 = 23.
OK, great. So now we know that f(23) = 0642, but we have no idea what the function f is. It might as well be some sort of salted SHA1 hash which we would never be able to guess. But I was assuming it would be a bit easier.
The column of zeroes made me think a bit, and I realized that the ones who planned it had to cut some digits in order to get those numbers in the range of 0 to 999. Cutting digits is done by using the modulus operator, and in this case, they even misused it a bit. They could have cut the digits using modulus 10,000, but instead, they only used 1,000. Well, at least that was my assumption.
So, assuming they used the modulus operator to cut the digits, we can probably guess that there’s some sort of operation done on the sum of digits. The most trivial way to create such hashes would be to multiply the number (which is how CRC works). Ideally, you’d want to multiply using a large prime number which is larger than the size of the number field.
Therefore, I’m guessing that f(x) translates to:
f(x) = (x * secret) % 1000
We already know that f(23) = 642, so:
642 = (23 * secret) % 1000
If 23 * secret would be less than 1000, then to find secret, we would just need to divide the equation by 23:
secret = 642/23 = 27.913043478
Well, obviously, that’s not it. If it’s not 642, then it might be 1,642, or 2,642, and so forth.
I’m sure there’s a bit more elegant way to find the missing thousand component, but for me, it would be just quicker to do a bit of brute-forcing:
1642/23 = 71.391304348
2642/23 = 114.869565217
18642/23 = 810.52173913
19642/23 = 854
Bingo. A number which the sum divides without any remainder. And it’s not even prime nor larger than the number field. So now our function is:
f(x) = (x * 854) % 1000
Let’s see if we were right. If we were right, we can generate the last 4 digits of the following barcode just by using the first 8.
So sum = 3+1+9+3+5 = 21. f(21) = (21 * 854) % 1000 = 17934 % 1000 = 934.
Nice. So what're the next steps?
1) Buy some stickers
2) Write a simple HTML page that generates barcodes according to the requested series.
3) Print them on the stickers
And we have free parking for life :)
However, there’s one caveat. The parking lot does track the license plate of the car and the barcode numbers used to exit the parking lot. So if they check the database, they can link the cars to the generated numbers, and assuming they are fake, they can probably send your license plate to the police and get you in jail. So I wouldn’t try it at home if I were you :)