Beating LinkedIn’s Mini Sudoku in 3 Seconds: A Parameter Tampering Case Study
Press enter or click to view image in full sizeOverviewLinkedIn’s Mini Sudoku is a daily puzzle game 2026-6-29 09:55:24 Author: infosecwriteups.com(查看原文) 阅读量:2 收藏

Press enter or click to view image in full size

Overview

LinkedIn’s Mini Sudoku is a daily puzzle game embedded in the platform’s Games feature. Players compete for the fastest completion time, which is displayed publicly alongside badges like “On fire” (win streak) and comparisons like “Smarter than 99% of CEOs.”

I discovered that the game completion time is supplied entirely by the client in the final API request — and the server accepts it without any server-side validation. By intercepting and modifying a single parameter in Burp Suite, I was able to submit a completion time of 3 seconds for a puzzle that realistically takes 1–3 minutes.

Background

LinkedIn Games launched in 2024, adding daily puzzles (Queens, Crossword, Mini Sudoku) directly to the platform. Each game tracks your time and displays the result to your network. The social element — “you beat 99% of people who played today” — creates an implicit competitive layer, which makes the integrity of these scores meaningful to users.

I was testing LinkedIn’s web application while running Burp Suite in the background when I noticed the game’s final submission request.

Discovery

I played Mini Sudoku #321 as normal — filling in cells one by one, down to the last empty cell. Before filling the final cell, I enabled Burp Suite’s intercept.

I filled in the last cell, which triggered a POST request to LinkedIn’s GraphQL API:

POST /voyager/api/graphql?action=execute&queryId=voyagerIdentityDashGames.f8508525e36bee5f9a5ab6b637854d87
Host: www.linkedin.com

Inside the request body, I found the game state payload. One field stood out immediately:

"timeElapsed": 3

The entire completion record — game state, cell values, time elapsed, whether the game was flawless, whether hints were used — was being sent from the client to the server as-is, with no server-side time tracking to verify it.

Proof of Concept

Step 1: Open LinkedIn Mini Sudoku and play until one cell remains.

Step 2: Enable Burp Suite intercept before filling the last cell.

Step 3: Fill the final cell. Intercept captures the game submission request.

Step 4: Locate the timeElapsed field in the request body and modify its value.

Step 5: Forward all requests. LinkedIn processes the submission and displays the manipulated time.

Result: Completion time displayed as 3 seconds.

Full intercepted request (sanitized):

POST /voyager/api/graphql?action=execute&queryId=voyagerIdentityDashGames.f8508525e36bee5f9a5ab6b637854d87 HTTP/2
Host: www.linkedin.com
Content-Type: application/json; charset=UTF-8
Csrf-Token: ajax:1812219885785541610
X-Restli-Protocol-Version: 2.0.0
X-Li-Pem-Metadata: Voyager - Games=game-state-update-post
{
"variables": {
"entity": {
"entity": {
"gameStoredRecord": {
"gamePlayState": "END_SOLVED",
"timeElapsed": 3,
"isFlawless": false,
"completionAttributes": {
"isHintFree": false,
"isMistakeFree": true
},
"gameStateUnion": {
"miniSudokuGameState": [
{"cellIdx": 1, "cellContentUnion": {"cellValue": 5}},
{"cellIdx": 2, "cellContentUnion": {"cellValue": 2}},
{"cellIdx": 3, "cellContentUnion": {"cellValue": 6}},
{"cellIdx": 4, "cellContentUnion": {"cellValue": 4}},
{"cellIdx": 6, "cellContentUnion": {"cellValue": 6}},
{"cellIdx": 8, "cellContentUnion": {"cellValue": 3}},
...
]
}
}
},
"resourceKey": "urn:li:fsd_game:(ACoAAF8BdxgB42sf2t6eedIXpw4zAxwabJ1ZfPA,7,320)"
}
},
"queryId": "voyagerIdentityDashGames.f8508525e36bee5f9a5ab6b637854d87"
}

Press enter or click to view image in full size

Press enter or click to view image in full size

Note on the minimum value: I tested timeElapsed: 1 — the server rejected it. The minimum accepted value was 3. Any value of 3 or above was accepted without question.

Impact

The impact here is scoped to game integrity, not account security or data exposure.

What this allows:

  • Submit any completion time at or above 3 seconds — appearing at the top of daily leaderboards regardless of actual performance
  • Manipulate streak counters and badges (“On fire”, “Flawless”) by controlling the completionAttributes flags
  • Skew the daily average shown to other players (“Today’s avg: 2:01”) since that average likely includes submitted times

What this does not allow:

  • Account takeover or privilege escalation
  • Access to other users’ data
  • Any server-side code execution

The root cause is architectural: the game trusts the client to report the time. A correct implementation tracks game start time server-side when the session begins, and computes elapsed time on submission — making client-supplied time values irrelevant.

Root Cause

The timeElapsed field is a client-supplied integer included in the final POST body. The server accepts it as authoritative. There is no server-side session that records when the game was started, so there is nothing to validate the submitted time against.

This is a textbook case of trusting client-provided state for something that should be computed server-side.

Remediation

The fix is straightforward:

  • Record game start time server-side when the player opens the puzzle (tied to session or user ID)
  • On submission, compute timeElapsed = submission_time - server_recorded_start_time
  • Discard the client-supplied timeElapsed value entirely
  • Apply a reasonable lower bound on valid completion times (a 6-cell Mini Sudoku cannot physically be solved in under ~10 seconds)

Disclosure

Reported to LinkedIn via HackerOne.


文章来源: https://infosecwriteups.com/beating-linkedins-mini-sudoku-in-3-seconds-a-parameter-tampering-case-study-9261b57873a8?source=rss----7b722bfd1b8d---4
如有侵权请联系:admin#unsafe.sh