Exploiting Ikariam: Persistent XSS and weaponization WriteUp

DISCLAIMER: EVERYTHING IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGE OR OTHER LIABILITY.

This is a writeup for a serious vulnerability I found on the popular web and mobile game Ikariam

Game Analysis 🔍

Ikariam is a purely web-based game and was released in 2009, when browser games were at a peak of popularity. Later, with the rise in popularity of smartphones, the developer created iOS and Android versions of the game. On this game you control an Island and your aim is to achieve growth by managing the different resources available. The business model is based on micro-transactions and a special “premium” resource.

One of the peculiarities of the game once you advance is your growing-rate, which increases if you join an alliance, or make friends. Thus the game has a messaging system which allows you to either contact your friends or all the people in your alliance, or even people who are not yet your contact (enemies, possible allies, etc). I decided to fuzz this messaging system to find vulnerabilities.

Usually I would use the Burp Suite but this game did not present many protection techniques like encrypting or obscuring sensitive data of the petitions so I quickly took a glance with Firefox Inspector and network monitor:

Firstly I sent a simple message saying “Hello” to some person and analysed the petition:

{"action":"Messages",
"function":"send",
"receiverId":"13279",
"msgType":"50",
"content":"Hello\n",
"isMission":"0",
"closeView":"0",
"allyId":"0",
"backgroundView":"city",
"currentCityId":"13755",
"templateView":"sendIKMessage",
"actionRequest":"310725177c5713e52f6c217c09f7ac86",
"ajax":"1"}

Quickly I inferred that:

  • action: defines the in-game action (sending a message, demolishing a building, attacking someone, etc).
  • function: indicates more information regarding the action.
  • receiverId: receiver of the message
  • content: body of our message
  • actionRequest: unique per-session per-action token

The other values are not really important.

After this I proceed to manually tamper the different values. Usually we would use two accounts under our control, but I rapidly found that, by changing the receiverId value to my own userId I could send messages to my own account and test further without alerting any other user!

In fact the game is confused and thinks Ikariam? has sent me the message. Let’s get down to business!

Persistent Cross Site Scripting 🔥

Having a stable and comfortable way of messing with the messaging system I proceeded to search vulnerabilities. The most obvious target would be the content field, which contains the message body.

Before that, one could believe we must obtain the new actionRequest token. This is true for 99% of the POST and GET requests done in Ikariam but.. for some reason, it is not in the messaging requests! I can reuse the same actionRequest for sending messages and it won’t be refreshed unless another different kind of request is done (exiting the messages window, changing the map, attacking someone..) so that measure is completely broken here.

I tried the simplest XSS payload of them all to see if there was some sort of sanitizing in place:

<script> alert(1) </script>

And indeed the <script> tag (and any variation of it) are being filtered.

So I decided to go on and try one sightly more complex payload:

<img src="" onload=alert(1)>

And voilá! I got javascript code execution when receiving and opening the message:

Whole Petition:

action=Messages&function=send&receiverId=10760&msgType=50&content=First,Part<img src="" onerror=alert(1)>SecondPart&isMission=0&closeView=0&allyId=0&backgroundView=city&currentCityId=23155&templateView=sendIKMessage&actionRequest=310725177c5713e52f6c217c09f7ac86&ajax=1

This payload is extremely simple but useful. It uses an <img> tag to try to load an image, but the src value is empty src="" therefore the loading will always fail, which executes the inline code in the onerror= field.

It is possible to execute almost any javascript inline statement, which is enough to perform any kind of attack. Furthermore different calls can be chained with the ; character:

<img src="" onload=alert(1);alert('Hacked')>

After analysing the behaviour of the page I found the vulnerability is even more serious than it seems.

  • Firstly: the XSS is executed before the message is opened, just by opening the message list (as the web pre-loads the content of the first 10 messages or so in the page).
  • Secondly: It also works without modifications in the mobile version!

The code will be executed any time the user opens the message list or the message itself. In addition, the injected payload is totally invisible to the user, which can still receive a legit-looking message.

Weaponizing the exploit 💣

So far, the vulnerability discovered would allow an attacker on a web browser to:

  • Steal Cookies
  • Redirect the page to a malicious site
  • Inject further scripts (adverts, crypto miners,…)
  • Interact with the game session

The first three kind of post attacks are well known and there are hundreds of examples of payloads on the web. Therefore I decided to explore a different aftermath. Interacting with the victim’s game session and gaining in-game advantage of the exploit.

To do so, I built my own tool to weaponize the vulnerability and make the process fast and automatic. After reversing for some hours the mobile version of the game I found, among other things, that it uses a different API endpoint with sightly different requests, this is going to be important later.

But for now, to launch attacks and send payload we need a user account on the server where our “victim” is, thus we need a pair of user:password for the tool to work with. I used the browser API endpoint which has similar requests to the one shown earlier.You can see the whole code of DarkRagweed here.

DarkRagweed is the name of this Python tool to weaponize the Ikariam exploit. It requires the requests and BeautifulSoup Python modules.

After being logged in, you can search for users, send them messages with payloads, etc. There are some technical details I won’t get much into. For example, as I mentioned before every time you perform a request you need to provide a unique value which changes, thus it is necessary to scrap the website after each request to gather the new value and build the new requests. DarkRagweed does this automatically.

In addition, if the target is the mobile WebView version, the context is different and you will need to adapt payloads. This is why the API endpoint is important. Once your code is executing on the target device, it must first detect wether it is running on WebView or in a PC browser, and use the corresponding endpoint accordingly, as the session from one endpoint cannot be used in the other. There are examples available in the repository which show how to differentiate between the webview and other browsers and extract the so called requestAction unique token. These scripts can be used as a template.

NOTE: As of November 2019, Gameforge is redesigning their login system, so DarkRagweed login no longer works. The exploit is still unpatched.

Conclusions

On this writeup you have been able to see how I found a serious persistent cross site scripting vulnerability. More importantly, how this vulnerability was customized and exploited in a particular case. It can be easy to find errors and vulnerabilities in systems, but not everyone can do the post-research to further investigate the application or system and develop customized, targeted exploits. This is, by the way, a nice trick for bug bounties, as the bounty can be higher if you show that the vulnerability can be used to take advantage over other users. In the Ikariam case, this exploit allows you to obtain massive advantage over other users, as just by sending them a message you can force them to send you all their precious resources, force them to demolish their own city, leave their alliance, and almost whatever you can imagine.

Leave a Reply