TryHackMe – Fool’s Mate Walkthrough
Category: Web Security / Client-Side Validation
Difficulty: Easy
Platform: TryHackMe
Date Completed: August 2026
Summary
This room demonstrates one of the oldest lessons in web security:
Never trust client-side validation.
The challenge presents a chess puzzle where a winning move is obvious to both the player and the chess engine. However, attempting to make the checkmating move through the web interface triggers a fake warning instead of sending the move to the server.
The objective isn’t to solve the chess puzzle—it’s to determine whether the restriction actually exists on the backend or only inside the browser.
Initial Enumeration
A quick scan identified only the web service, so I switched to manual inspection.
nmap -Pn -sV <TARGET_IP>
Opening the application revealed an interactive chessboard with a forced mate-in-one position.
Attempting the winning move produced the following message:
“I’ll shut down your PC if you play that.”
That immediately suggested the move might only be blocked by frontend logic.
Inspecting the JavaScript
Using the browser’s Developer Tools (F12), I reviewed the loaded JavaScript files and found the primary application logic inside:
/js/app.js
One function stood out:
function preMoveCheck(from, to, promotion) {
const probe = new Chess(game.fen());
if (probe.isCheckmate()) {
showSystemNotice("I'll shut down your PC if you play that.");
return false;
}
return true;
}
The browser creates a temporary copy of the game state, evaluates the move locally, and refuses to submit it if it results in checkmate.
This is classic client-side validation.
Nothing here guarantees the backend performs the same validation.
Following the Request
Continuing through the JavaScript revealed how moves were actually submitted.
The frontend sends a JSON request similar to:
POST /api/move
{
"from": "a1",
"to": "a8"
}
Rather than interacting with the chessboard, the move could be sent directly to the API.
Capturing the Session
The application used a session cookie (sid) to associate requests with the current game.
Using the browser’s Developer Tools, I copied the session cookie from the active browser session.
Bypassing the Frontend
Instead of clicking the board, I reproduced the request manually with curl.
curl -X POST http://TARGET/api/move \
-H "Content-Type: application/json" \
-H "Cookie: sid=<session_cookie>" \
-d '{"from":"a1","to":"a8"}'
Because the backend accepted the move, the request completed successfully and returned a JSON response indicating the game had ended in checkmate.
The challenge flag was included in that response.
What This Room Teaches
Although the puzzle appears to be about chess, it’s really about understanding the difference between client-side controls and server-side validation.
Key takeaways include:
- Inspect JavaScript instead of assuming the UI tells the whole story.
- Browser validation improves user experience but should never be treated as a security control.
- Developer Tools make it easy to identify hidden API endpoints.
- Reproducing browser requests with tools like
curlis an essential penetration testing skill. - Sensitive business logic should always be validated on the server, regardless of what the frontend enforces.
Final Thoughts
This was a short but excellent reminder that frontend restrictions are not security boundaries. If an application only prevents an action in JavaScript while trusting whatever the client sends afterward, those protections can often be bypassed with nothing more than an intercepted request.
Sometimes the winning move isn’t finding the checkmate—it’s realizing the browser isn’t the one making the final decision.
