An Ethical Hacking Story — The Yummy Days Case by Héctor Martos

How I found a security issue in The Fork — Yummy Days promotion and how this could have affected their business

As a financial-based web applications developer, I am always concerned about security, but it is also one of my passions. Over the last two years, some of the web applications in which I have worked have been submitted to thorough security checks, to ensure they were completely secure before going into production mode.

In this journey, I have learned a lot about security — authentication, potentially dangerous requests, injections, etc. — and how to design secure applications.

Eating is another of my passions, lunch time is my favorite moment of the day and El Tenedor (in Spain) / The Fork is the best app to reserve an appointment in a restaurant, with lots of discounts, that helps you saving money.

In this story I will show you how I found a security issue with a promotion of The Fork, called The Yummy Days, and how I built a simple automatic client that allowed me to get the prizes of the Yummy Days promotion.

Disclaimer: the opinions expressed in this story are the author’s own and do not reflect the view of The Fork company. The Fork was notified by email of the issue and appropriate measures have been taken to solve it. Also, sensitive information like URLs have been hidden.

Note: Some technical knowledge is needed to understand some parts of this story.


The Yummy Days Case

For those unfamiliar with this, The Yummy Days is a one week promotion, consistent in a daily play where you can win a free meal up to 120€ and a set of prizes in Yums, which will be added to your account and can be exchanged by discounts (1000 Yums are equivalent to 10€ discount in the bill of a restaurant).

While the promotion was live, there was a banner in The Fork app that opened the following window:

To play the daily game, you should insert your email, check the acceptance of the conditions and click the PLAY button. When this form was submitted you had to click a button to fire an animation and check if you won a prize or not.

You can play once a day for 7 days to win prizes

If you were lucky, you would take a Yum from the salad, what meant you won a prize, and you will be given a code that could be used in the next reservation to add the earned Yums to your account. Else you will take from the salad the purple lettuce (or whatever this purple thing was) indicating there was no prize for you. Try again tomorrow.

I played three or four days to the game, and I even won 300 Yums!

I earned 300 Yums making a reservation in a restaurant with that code

A revelation

On the last of the Yummy Days, staring at the form where my email address was asked, it called my attention that the page of the promotion was opened in some kind of embedded browser, and I could easily see the URL that was being accessed (hidden in the image above).

I was curious, so I opened the URL in my computer with Google Chrome and itsDeveloper Tools option enabled to log all the requests being done during my last play in the Yummy Days promotion.

HTTP request with its methods, headers and parameters in Google Chrome Developer Tools

I wasn’t lucky, but I could analyze the requests log to know what happened under the hood during the daily play. It seemed that the User Interface was making requests to a Restful API server, so I saved the requests and responses and I tried to play again with my email address, being redirected to a page that said I had already played the game, as it was expected.

Then, I tried to play again with another email address I own, not registered in The Fork app, to see what happened, and surprisingly I was able to play again!. That meant the API was not validating if inserted email was registered in the app or not. In consequence, I could play the game again and again with random email addresses to try to earn more prizes, something I shouldn’t be able to do.

One may think this is not a serious problem, and it could be true if you think in a person manually filling the form with a random email address, accepting the conditions of the promotion, saving the code in case of being lucky and repeating the whole process again and again. Although this person would catch some prizes, this would not affect very much the result of the promotion, but what if this process could be automated and repeated each second?


The technical stuff

There are a bunch of different ways to automate this process, but my favorite is Postman. Postman is a client that allows us to easily make HTTP request to APIs and execute pieces of code before and after each request.

Do you remember when I log all the requests being done during the game play with Google Chrome Developer Tools? It was time to replicate the Yummy Days game requests. For this purpose I created a collection with three requests, called Get Cookies, Fill Form and Play.

The first request, Get Cookies, was a HTTP GET to the URL of the Yummy Dayspage. In Test tab, where you can put a piece of code that will be executed after the request, I set a couple of Postman environment variables with the value of two of the Cookies that come with the response, in a Set-Cookie header, valid for 15 minutes from the request.

In the second request, Fill Form, I wanted to replicate the form submission, that was an HTTP POST to an URL. I created a simple Pre-request Script, a piece of code executed before the request, to set an environment variable with a randomly generated email address.

I also set the JSON body of the POST using this generated email like this:

The first try returned a 500 status code (Internal Server Error), indicating there was something not good with the request. Looking at the logged request in Google Chrome I set the two previously stored Cookies as headers along with any others and the response was a successful 200 status code, great!

Finally, in Play request, I wanted to replicate the behavior of the button that fired the animation to check if you won a prize. That was a simple GET to an URL, using the same headers of the previous request.

I added a test to check if a prize had been won, filtering tries without any prize or duplicated email addresses. If there was a prize in that try, the response to this request would be logged in the Postman Console.

I already had a collection of three request that can be executed in order to play the Yummy Days game with a random email address, so I could execute this requests in an iteration of N executions.

This was time for Postman Collection Runner.

With the Collection Runner, I ran 100 times the game, with no luck, so I tried with a higher number of iterations and I could see the test of one the Playrequest passing, and the following JSON was logged into the console, indicating I had won a prize!

{
 “id”: 16490,
 “code”: “******”, //Code has been hidden
 “date_to_win”: “2018–06–10 17:36:56”,
 “type”: “300”, //300 Yums price
 “value”: 5, 
 “user_id”: 217467,
 “country_id”: 1,
 “created_at”: null,
 “updated_at”: “2018–06–10 17:36:57”
}

At this point, I had demonstrated I could automatically win a prize of the Yummy Days promotion, which seems to be time-based and country-based (look at date_to_win and country_id attribute), and seriously affect the results of the promotion (look at updated_at attribute, it is just one second after date_to_win!).


Angel or Demon

Imagine an evil scenario:

What if I could execute this requests for all the time the promotion is active? What if I could do this for all countries?

If I could, I will be able to get a great quantity of prizes of the Yummy Dayspromotion, making this issue, in my humble opinion, potentially dangerous for The Fork business.

Once you have started a hack like this —although you want to do it ethically —there is a demon on your left shoulder that always wants more. I needed to know if there was some kind of control over a high number of requests coming from the same IP; to know if this issue could be really harmful.

Hearing to the demon, I created a simple script that runs the exported Postman collection in an infinite loop in a shell using Newman:

while true; 
do newman run TheForkYummyDays.postman_collection.json; 
done

I executed this command uninterruptedly for almost 45 minutes, and I thought that if the server didn’t already block me, it wouldn’t block me anytime. In this time, I got 35 prizes of 300 Yums, 1 prize of 1000 Yums and 1 prize of 2000 Yums.

After this discovery, the angel of my right shoulder convinced me it was time to stop and inform The Fork about the vulnerability, so they can fix this issue. I sent them an email with some codes of the different prizes I had won and the technical details to replicate the issue.

A couple of days later I received a response to my email informing that the incidence had been reported to the technical department to be solvedand they even thanked me the details to replicate the issue with a 1000 Yumsdiscount code!


What can be done to fix this issue?

That was the following question I made myself, and applying the knowledge I have on this area, here are a few things I think would minimize or solve the problem:

Check in the server side that the email was registered on The Fork

That’s for sure the best way of solving this issue, security checks should be always done on the server side, no matter what checks are being done on the UI. Making this check the server will not allow any non-registered email address to participate in the promotion.

Embed the page of the promotion in The Fork app

If the Yummy Days promotion page would have been embedded in The Forkapp in an iframe, instead of being opened in a embedded browser, it would have been more difficult to see the URL of The Yummy Days. If you are embedding an iframe I recommend using the X-Frame-Options headers to be able to embed this page only in an allowed URL, preventing in this way Clickjacking attacks.

Block an IP address that has exceeded a limit number of requests

This one will involve the DevOps team, by limiting or at least firing any kind of alert if the same IP address has exceeded a certain number of requests in an stipulated period of time, also preventing DDoS attacks.


Conclusion

Security is not always taken seriously, but it could lead to several kinds of risks, not only related to technology. Although this issue has no impact on the economy of The Fork, and it can not be considered critical, its probability of materialization and its ease of exploitation make this issue relatively dangerous for The Fork business.

Imagine how different would have been if I had been evil and I had published a large list of discounts codes, along with the instructions to get them, instead of notifying the issue first. Probably, the security of The Fork would have been questioned and this could lead to a big reputational risk, affecting negatively to their business.


Originally posted: https://medium.com/@h_martos/an-ethical-hacking-story-the-yummy-days-case-a083b57a352c

February 26, 2019

3
Leave a Reply

avatar
3 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
0 Comment authors
Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
trackback

[…] *参考来源:hakin9,FB小编secist编译,转载请注明来自FreeBuf.COM […]

trackback

[…] *参考来源:hakin9,FB小编secist编译,转载请注明来自FreeBuf.COM […]

trackback

[…] *参考来源:hakin9,FB小编secist编译,转载请注明来自FreeBuf.COM […]

© HAKIN9 MEDIA SP. Z O.O. SP. K. 2013