Post

BYU CTF 2025 - WEB

BYU CTF 2025 - WEB

Web

Willy Wonka Web

Solvers: 191
Author: Legoclones

Description

Welcome to the world of web! Can you get the flag?

willy wonka

Solution

When starting the challenge, we see a simple webpage displaying “It works!”. After examining the provided source code, we identify two main components:

  1. Backend (server.js) ```js // imports const express = require(‘express’); const fs = require(‘fs’);

// initializations const app = express() const FLAG = fs.readFileSync(‘flag.txt’, { encoding: ‘utf8’, flag: ‘r’ }).trim() const PORT = 3000

// endpoints app.get(‘/’, async (req, res) => { if (req.header(‘a’) && req.header(‘a’) === ‘admin’) { return res.send(FLAG); } return res.send(‘Hello ‘+req.query.name.replace(“<”,””).replace(“>”,””)+’!’); });

// start server app.listen(PORT, async () => { console.log(Listening on ${PORT}) });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2. Frontend (`httpd.conf`)
```conf
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:80>

    ServerName localhost
    DocumentRoot /usr/local/apache2/htdocs

    RewriteEngine on
    RewriteRule "^/name/(.*)" "http://backend:3000/?name=$1" [P]
    ProxyPassReverse "/name/" "http://backend:3000/"

    RequestHeader unset A
    RequestHeader unset a

</VirtualHost>

The backend is a simple Node.js server that listens on port 3000 and returns the flag if the a header is set to admin. The frontend is an Apache server that proxies requests to the backend.

When we try to inject the another header a: admin in the request, it gets:

name

We found that Apache is configured to strip a and A headers before forwarding.

We need to bypass this header filtering mechanism to send the a: admin header to the backend.

After using wappalyzer, we found that the web server is Apache version 2.4.55, search for its CVE and found CVE-2023-25690 which is a vulnerability in mod_proxy module leads to HTTP Request Smuggling.

  • mod_proxy is enabled
  • A RewriteRule with variable substitution (like $1) is used
  • The pattern captures data from user-supplied URLs

→ This vulnerability allows injecting CRLF into the URL, we need to create new headers in the request after it has been processed by Apache.

Let’s modified the burp request to this:

1
GET /name/%0D%0Aa:%20admin%0D%0Aabc:%20edf HTTP/2

name2

Here is the flow of the request:

  • When we send a request to /name/%0D%0Aa:%20admin%0D%0Aabc:%20edf
  • Apache URL-decodes this to /name/\r\na: admin\r\nabc: edf
  • The RewriteRule ^/name/(.*) captures \r\na: admin\r\nabc: edf
  • When rewriting the request to the backend, this becomes:
    GET /name/ HTTP/2
    a: admin
    abc: edf HTTP/2
    Host: backend
    ...other headers...
    
  • The backend receives the a: admin header and returns the flag

Flag: byuctf{i_never_liked_willy_wonka}

This post is licensed under CC BY 4.0 by the author.