Lockerz.com, and the importance of data validation.
Many popular web applications are left susceptible to Cross site request forgery (CSRF) and request alteration due to the lack of request validation. This form of validation is vital to ensuring the origin of a request, to ensuring the authenticity of the data within the request.
About a week ago I stumbled upon a perfect example exemplifying the importance of request validation and data authenticity. I was invited to a website called Lockerz.com. Lockerz offers its users different ways to earn points on their account by answering questions on their website daily and by inviting other friends to sign-up. Users can then redeem those points for amazing products ranging from iPod Touches, Apple TVs, Mac Book Pros all the way to concert tickets, expensive pocket books, and jewelry.
After I registered, I was directed to a page welcoming me to Lockerz. My points counter showed up at the bottom right of the screen and was populated with 2 points for just signing up. I was then directed to a breakout type game that each user plays once, right after they sign-up. The objective was to catch as many falling money squares before time runs out. The more you catch, the more bonus points you get for signing up. The game began and I started moving my cursor around the screen trying to catch the falling sqaures. Time ran out and my point counter incremented by my total winnings. Below is a screen shot of the game.
Like usual, my curiosity got the best of me and I decided to take a deeper look at the operation of the game. I set up a local proxy and tunneled all HTTP traffic through it so that I could take a closer look at the requests being made throughout game-play. I noticed that only one post request was made at the end of the game by the embedded SWF, which was used to increment my point counter. But I noticed something peculiar about the POST variables; there was no form of authentication being used to validate my score sent from the SWF to their server. Below is an example of the post request that the SWF sent to their server.
POST /asset/submit/1 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:188.8.131.52) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)
Cookie: __utma=27552625.3926623737007597500.1250522678.1250623832.1250640033.3; __utmz=27550625.1224322678.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); SESSd61c2d9c6510db589245293749ed3b01=7ea8d55f367ebfad59b14e936c5be67c; __utmb=275506184.108.40.2060640033; __utmc=27550625; has_js=1
By simply changing the value of the “score” variable to 9000 and altering the Content-Length to 39, my score counter incremented to 9,002 points. I would then be able to redeem prizes with high point prices instantly. I immediately notified Lockerz about the vulenrablity and that I encourage they use some form of encryption or token based validation to authenticate the legitimacy of the score sent off by the SWF to the server. I received an email shortly after telling me that the team has been notified. I checked back two days later and they did just what I suggested. They added several more variables to the POST request validating the score before it is entered into their database. The new POST variables are listed below.
As you can see, a few new variables have been added, the most important being scoreCheck and gameToken. After much discussion with a good friend and colleague of mine, Praveen, we both settled on the idea that it seemed highly likely that they are using some form of salted hash for the scoreCheck value to verify the score received by the server to the request made by the SWF since the score is still being sent through the request which would be useless if encryption was being used. I am also assuming that they added in the gameToken value to authenticate the origin of request and to make sure that the SWF that is making the request is actually embedded on their website.
The idea of using request validation tokens to avoid CSRF and data alteration is nothing new. But it cannot be stressed enough, especially in the case of point based sites like Lockerz, where an attacker can exploit the system to steal expensive prizes with little to no effort. In Lockerz’s case, using a hash made a lot of sense, since you can’t really store the SWF score in a session prior to sending it off to the server for validation. But in PHP, setting a simple session token on the server and sending it through a request that you would like to protect can be simply accomplished by using the $_SESSION associative array. You can check out this article for more information and easy to understand examples demonstrating the proper use of the $_SESSION associative array in relation to avoiding CSRF attacks and validating request data in PHP.