Picture the scene. It's 2012, I'm in my second year of university, and Gangnam Style has just come out. The bar at my university has a digital jukebox of sorts - it'll play the current popular songs over the sound system, with the associated music video displayed on various screens around the bar, and it's got an app to let people request songs too. And I'm a programmer with too much free time.
That jukebox/app was powered by Subtv, a service installed at numerous venues around the UK. You'd install the app on your phone, find your campus on the list, and type in a 4-digit PIN to verify that you were actually at that campus (the screens on-site would periodically display this PIN). Once authenticated, you could browse the song catalog, and add songs to the play queue. The queue order, however, was decided on a vote system - if your friends requested the same song, it'd get bumped up the queue and played sooner. A song with 5 votes will play before a song with 3 votes, even if the 3-vote song was initially requested first.
You might see where this is going already.
So, being a 19-year-old programmer with too much time and a penchant for reverse-engineering and mischief, I rooted my phone, installed the app, extracted the APK, and threw it into a decompiler. I wanted to see what made it tick.
On first boot, you would supply a name, and it would assign you a user ID that would be used for all subsequent requests. The app would retrieve a list of venues (each with a numeric ID) as XML, and display them to the user. Upon selecting one, the app would prompt you for the PIN. The PIN you typed in would be sent up to the server along with the Venue ID, and the server would reply with "success" or "failed". The app would either let you to the song list or keep you on the PIN prompt, respectively.
At this point the app opens a TCP socket connection to the server (all the prior communication has been HTTP). It sends a connection packet with the User ID and Venue ID, and gets back a status code. If the status code is 230, the app proceeds to the song list, otherwise it'll display an error to the user.
When the user requests a song, the app sends a packet over the socket connection, and the song gets added to the play queue. If they request the song again while it's still in the queue, the app will prompt the user, and it won't submit the packet.
I wrote a duplicate of the client-side networking protocol to play with it some more. After a few successful innocuous song requests, I got curious. Is the "you can't request this song twice" check implemented on the server or the client?
Turns out it's on the client.
If you bypass the app and just send the "request X song" packet multiple times in a row, the server will happily accept it as being multiple votes for the same song. This meant I could essentially take complete control of the playlist, out-voting anyone else's song requests.
During class one day at uni, I wrote a script that would request PSY's Gangnam Style every five minutes, put it up on my server, and left it running. My intention was that it'd be a laugh for a bit and then I'd disable it at the end of class. How naive. Three days later, I remembered that I'd done this, and hurriedly disabled the script (and vowed never to do that again).
It wasn't until several months afterward that I ended up in a conversation where it came up that the bar staff had resorted to blacklisting the song to save themselves from going insane (they had an admin panel that let them do that). I sheepishly admitted that I was responsible and apologised profusely.
The app has since had two major rewrites. The first removed the voting system in favor of a "first-come-first-served" request model (though I found some other laughable issues when I decompiled that one). The second occurred after I graduated and I've just not cared enough to pick it apart.