The wings of a computer engineer
The wings of a computer engineer

Personal blog for Timothy D Meadows II

ʍɐɔ ʍɐɔ ʍɐɔ

Share


Twitter


Gods Unchained - Sealed API

Timothy D Meadows IITimothy D Meadows II

Summary

On 3/10/2024 the Council of Mortals asked me to audit the sealed portion of the Gods Unchained client to verify if it was actually possible to use cards that where not in your sealed pool, in your sealed deck. This audit was limited in scope to sealed, and validation that the exploit found only affected sealed.

This post is disclosure of that process. It's important to note that before disclosure. This exploit was fixed on 3/20. It's unknown if the method proposed in this audit was used to fix the exploit. However, testing after the 3/20 patch, i can validate this exploit is no longer working at this time.

TLDR

Question: Could you save your sealed deck with cards not in your pool?
Answer: Yes, if you know the proto id of the card, or cards you want.

Question: Can you still do this?
Answer: No.

Exploit

This exploit could be preformed by capturing and saving requests from inside the client, and then replaying those same requests with the new proto ids you want within the time period it's still valid (about 120 seconds).

Note: Fiddler Everywhere was used to capture, modify, and replay the traffic for this audit.

While the scope of this audit was the sealed api, i did take the time to validate if the same injection method was usable in ranked / casual, however, in those modes there is an "ownership" check that prevents this type of injection. Sealed mode does not contain that check so that you can play in sealed with cards you don't own if they are also assigned in your random pool.

Solution

The active sealed sessions API call list's ALL of the cards (proto's) in our random pool. There needs to be a check on the Save Deck API call that double checks that the proto id's (cards) saved in the array are in fact also in the array of proto's (cards) in our pool. If proto's (cards) are contained that DO NOT match, then, AccessDenied should be returned and the deck should not be saved.

Details

Full disclosure this audit was preformed on my personal GU account, no games where played with this modified sealed session. Once proof was gathered, the sealed run was abandoned (RIP 5 gods). This can be verified with the sealed session id in the JSON listed below.

Get Sealed Session

This API call will list the active sealed session for a player. It also includes our card_pool which has a list of all proto id's (cards) that we were randomly assigned at the time of buy in.

→ GET gamemode.prod.prod.godsunchained.com/user/{guid}/gamemode/7/session

Returns

{"id":"0072e0cb-7c09-4e45-8e27-0726368b2dff","user_id":436860,"buy_in_id":"dd58db39-9cb2-4598-85ec-60fc0c2b85e4","game_mode_global_id":7,"god_pool":["nature","death","magic"],"card_pool":[1132,2002,1605,87061,1159,1680,87056,1215,1605,2325,1604,2328,1260,1165,1130,1154,1673,1616,1032,1293,2003,1245,1295,1122,1248,1294,1122,1011,1532,1751,1083,1122,1292,2263,1182,87069,1243,1245,87067,1698,1564,87049,1570,2257,1168,1668,1753,1045,1092,1043,1092,2313,2257,1676,2311,1081,1101,1551,1081,2311],"deck_id":9864282,"god":"","properties":{"paid":true,"max_wins":7,"max_losses":3,"buy_in_cost":5,"buy_in_currency":"gods"},"win":0,"loss":0,"status":"started","created_at":"2024-03-10T21:01:36.781066Z","updated_at":"2024-03-10T21:49:26.542857Z"}

Save Deck

This will save a deck with the information contained in the payload. There is no validation made that cards saved are in the pool list above, at the the time of this audit. I did also test trying to use a god you where not assigned at the time of buy in, but this did not work, if you try and use god not assigned you assigned your first god in the list of gods.

PUT deck.prod.prod.godsunchained.com/user/{guid}/deck/{deckid}

Payload

{"id":9864282,"name":"Nature Deck","god":"nature","deck_type":"restricted","ids":[233795109,228897085,78293701,198293435,73982871,209542666,225424635,142817595,221197551,97683802,192815310,64983360,151796170,33781472,226470054,190607562,247505996,193939540,33781468,222887919,233179866,205775320,64892233,64906060,196212367,206068833,168162048,21083152],"protos":[2003,2311],"timestamp":1710104643994,"game_mode_id":7}

Returns

9864282  

Set Deck

This is used to set the current deck used in sealed. It's mostly a hold over from in the UI from the other modes where you can change decks. You can't actually give a deck id other than the one originally assigned when the session is created.

PUT gamemode.prod.prod.godsunchained.com/user/{guid}/session/{sessionid}/deck

Payload

{
    "deck_id": 9864282
}

Returns

null  

ʍɐɔ ʍɐɔ ʍɐɔ

Comments