Tag: web academy

  • Remote code execution via polyglot web shell upload – Portswigger Web Security Academy Lab Walkthrough

    Remote code execution via polyglot web shell upload – Portswigger Web Security Academy Lab Walkthrough

    In this lab, we will bypass simple file validation to upload PHP code. I found this lab particularly interesting because the bypass involved injecting code into an image’s metadata. This is a technique I was unfamiliar with before attempting to solve this lab and I thought it was pretty cool. So, let’s get into my thought process for solving this lab!

    The task at hand

    The description of the lab is as follows:

    “This lab contains a vulnerable image upload function. Although it checks the contents of the file to verify that it is a genuine image, it is still possible to upload and execute server-side code. To solve the lab, upload a basic PHP web shell, then use it to exfiltrate the contents of the file /home/carlos/secret. Submit this secret using the button provided in the lab banner. You can log in to your own account using the following credentials: wiener:peter

    In the directions, we’re given the hint that the code validates an image based on its contents. The first thing that came to mind was changing the magic bytes of my PHP web shell to pass it off as an image. So, I set out to do just that!

    Magic Bytes

    Magic Bytes are file signatures used to identify files. They are used in UNIX-based operating systems to distinguish different file types from each other. Operating systems need to know this because different file types need to be handled differently. For example, an image file must be treated differently than an executable file. Windows, on the other hand, relies on file extension names instead.

    So, if the server that is doing the file validation is running Linux, we might be able to trick it into thinking that our PHP file is an image by changing the leading bytes.

    Let’s craft the payload!

    Since we’re given the directory of the secret, my PHP code just outputs the file’s contents to the browser. For convenience’s sake, it’s not a full-blown web shell:

    <?php
    $file = '/home/carlos/secret';
    $contents = file_get_contents($file);
    echo $contents;
    ?>

    I have it saved as webshell.php (super low profile). Using the file command in my terminal, we can see that it gets recognized as a text file with PHP code written in it:

    Even after we change the extension, it’s still recognized as a PHP script. Magic Bytes!

    Let’s see what happens when we change the leading bytes of the file to the file signature of a JPEG.

    First, let’s use xxd to see what the original bytes look like:

    For this to be recognized as a JPEG, we’ll have to change the leading bytes to FF D8 FF E0. I got that magic number from this wiki article.

    To edit the file, I’m going to use a tool called hexedit. Before editing, I’ll add a few new lines to preserve the original code (4 to be exact because the signature is 4 bytes):

    Now, after saving, the file should be recognized as a JPEG:

    Just like magic!

    Logging into our lab’s account with wiener:peter, we are met with an option to upload an avatar image. Proxying my traffic with Burp, I try to upload the web shell:

    No dice! Looks like the file checker doesn’t just check file’s signature…

    Enter EXIF!

    We need to find another way to pass our PHP code off as an image file. My second thought was to somehow inject the PHP code into a valid image instead of trying to make my PHP file mimic an image.

    A quick Google search on “injecting PHP code into an image” lead me to this excellent article. Apparently, code written into the metadata of an image can be executed!

    If you don’t know what EXIF data is, it’s basically metadata, or extra data written to an image to provide information about the context of the image. This can include the device used to snap the photo, the resolution, and even more revealing information like the location the image was taken.

    For this reason, examining EXIF data is a powerful recon technique. Let’s take a look at an example of a random picture I downloaded online:

    This information is not only readable but writeable as well.

    We can add comments in the metadata with a tool called jhead. Using the command jhead -ce <image>, we can edit the EXIF comment field:

    Saving this, our metadata now stores our PHP code in the comment section of the metadata:

    This has no impact on the integrity of the file and will bypass most image upload checks:

    The only caveat is that most servers aren’t configured to execute image files (makes sense). So, in order for the code to run, we’ll have to change the filename to have a .php extension.

    Success!

    Inspecting the uploaded image with dev tools tells us where the file was uploaded to:

    Browsing to this location gives us the secret! Of course, I’m not going to show this to you. You’ll have to take my word for it and solve the lab on your own 😉

    Conclusion

    Solving this lab helped me to learn a powerful code smuggling technique. This method should be flexible and open a world of possibilities for you. I can only imagine trying this with other languages like Javascript for stored XSS.

    Of course, this would only work if the server doesn’t validate files based on their extension. There are workarounds to bypass this even in the event that the server does make this check (like exploiting a race condition) so it is up to you to get creative with this and find some critical bugs.

    Anyways, thanks for reading! I hope you learned something because I certainly have! Until next time 🙂

  • Reflected DOM XSS Lab – Portswigger Web Academy

    Lately, I’ve been participating in some bug bounty programs and have been doing Portswigger’s web security labs as a refresher. This lab was particularly interesting to me because it forced you to use dev-tools to debug the application to figure out where exactly to inject. So in the post, I’ll walk you through how to use Firefox’s dev-tools to dig deeper into an application.

    DOM XSS

    For those of you who aren’t familiar with XSS (Cross-site Scripting), it’s a web vulnerability that allows unauthorized users to inject javascript code into a web application. This can be through form inputs, url parameters, or pretty much anywhere that gives the user a chance to pass input that is then rendered by the browser.

    There are three types of XSS:

    • Reflected: the current HTTP(s) request triggers the malicious JavaScript
      • Ex: A maliciously crafted link the user has to click on to execute the code
    • Stored: the malicious script is rendered after it is pulled from a database
      • Ex: JavaScript stored in the comment section of a blog post.
    • DOM: malicious JavaScript is stored in the client-side in the document object model (DOM)
      • Ex: User input is fed directly to document.innerHTML

    DOM XSS is usually the hardest to spot and wrap your head around because it occurs during runtime. So, in this post, I’m going to be running through one of Portswigger’s Labs to expose you to testing for these vulnerabilities using browser dev-tools.

    The Lab

    The lab I’m going to be walking you through is the Reflected DOM XSS lab, so feel free to follow along with me!

    To solve this lab, we’re going to need to trick the site into calling the alert()function. First things first, we need to find out where this site is reflecting user input. The most immediate place to try passing user input is the big search bar on the homepage. So, I type a unique string (test12345) and use the dev tools to search for it.

    To open up my dev tools, I right-clicked on the reflected value and selected “Inspect Element.” This value looks like it’s inserted directly into the <h1> tag but what stood out to me even more is the search('search-results') function call.

    Let’s head to the debugger to see what that’s all about. Clicking on the link to searchResults.js took me to the debugger. Right away, this line stood out to me:

    eval methods are notoriously vulnerable to XSS because they evaluate strings to JavaScript code. Whenever you’re testing for XSS be on the lookout for eval functions because they are often a golden ticket to XSS if input isn’t sanitized. The innerHTML attribute of should also be considered a red flag because it is used to directly insert HTML code inbetween tags. There were no lines containing innerHTML (only innerText and setAttribute handled our input) so let’s focus on the eval method for now.

    So, I set a break point on the line containing the eval function (line 5) and ran another search. Once execution is paused, expanding the panel on the right for this reveals that response.responseText stores:

    The same can be achieved by just hovering over the line in the code (but this was easier to screenshot). As you can see, responseText gets evaluated as a JSON object. Let’s try escaping the JSON with "}; and then calling the alert() function after:

    It looks like a \ was used to escape the quote. Let’s try inserting a \ to see if we can escape the escape…

    Not exactly what I was expecting but it looks like the logic of the code tried to escape the back-slash with a back-slash then tried to escape the one that was trying to escape the "…? Either way, it looks like they all canceled each other out.

    Resuming the code and…nothing happened… That’s because I forget about the trailing "}! Adding a simple // should do the trick. Now our full payload looks like test\"}; alert(1); //:

    Much better! Resuming the execution gives us an alert!

    We did it!

    Conclusion

    Developer tools are often overlooked when web application testing but they are actually incredibly powerful. Taking the time to dive deeper into the application will allow you to look for mistakes that those who rely on automated tools and scanners will definitely miss! So, it’s important to examine the code and understand what it is the application is actually doing. This will put you 10 steps ahead against other bug bounty hunters!