2

I encountered this type of vulnerability a couple of times but was not able to fully exploit it.

This vulnerability is a self-xss which is triggered from file names. E.g. If I were to upload a file named [xss-payload].png, it will be executed as javascript and the window will prompt 1. But it only goes as far as that.

[XSS-Payload] = Any XSS payload as file name will be executed when uploading the file. E.g. File Name: <img src=x onerror=alert(1)>.png

The file name stored in the server is randomly generated, therefore this isn't a stored xss.

Is there any way I could exploit this? The Javascript is executed when uploading the file only. I tried chaining with clickjacking, but the website doesn't allow iframe.

And from what I heard, CSRF is not possible since setting a 'pre-filled' file name is not possible when uploading a file.

Any idea where I should go with this? Can I chain this with other vulnerabilities?

8
  • It might be helpful if you add more details and context to your question (by editing the question, not as a comment), i.e. what exactly you've tried as code, what you expected, what you got. At the moment you expect others to already know a lot about the specific problem you are trying to solve. Sep 7, 2020 at 6:08
  • @SteffenUllrich, I noticed that my question got partially trimmed/filtered by the editor since I inputted an XSS payload. But there is the update, any xss payload written as the name of the file would execute when uploading the file. I believe this is clear enough since my question is if there is anything I can do when encountering such vulnerability (Self-XSS triggered when uploading a file, but saved on the server with different name). Sep 7, 2020 at 6:36
  • "got partially trimmed/filtered by the editor " - please use proper code formatting and don't simply paste code anywhere in the text. But just given some filename with XSS at an arbitrary upload will not work - the upload function actually has to be vulnerable. Sep 7, 2020 at 6:42
  • @SteffenUllrich, Noted. I don't really get your what you mean by 'But just given some filename with XSS at an arbitrary upload will not work', mind clarifying more? My observation is that, the file name is being printed out when trying to upload a file (but not sanitized), therefore javascript is executed. Is this as far as it can go? Would it be possible to execute RCE through '<script>' tag? Is there anything that can be achieved from script tag other than XSS? Sep 7, 2020 at 7:09
  • "Is there anything that can be achieved from script tag other than XSS?" - I don't really understand. What else do you want with a script tag apart from executing script (which exactly is the point of XSS). And sure there might be some broken server which executes something local on the server - but like with XSS this would actually require a server vulnerable exactly to this and there is no generic RCE or XSS against some generic upload. Sep 7, 2020 at 7:47

2 Answers 2

1

This may be vulnerable. There are a few conditions that you didn't specify that are needed for it to be vulnerable, though:

  1. No kind of CSRF protection, intentional or otherwise, on the upload endpoint. If so (and it doesn't trust some other page you control and can host script on), you won't be able to launch any kind of cross-site attack at all, and would need a stored way to run script of your control within the target site for a cross-user attack.
  2. Uploading a file either navigates to the page with the reflected name, or the page with the reflected name dynamically updates if an upload happens from another page. In other words, you need to be able to initiate the upload from an external site (that you, the attacker, control), and cause the victim to see the result. The most common case for this is if the file is uploaded directly to the server using an HTML form and file-type input, but it might be possible even if the upload is script-driven, so long as the page that shows the reflected filename can be caused to show it from an external upload (without the user taking action on the vulnerable page).
  3. The file upload must use a content type that can be sent from an external site, such as multipart/form-data (the type used for file uploads from forms, though it can be used for any kind of POST request body data). Technically this requirement is part of condition #1 - if the server strictly enforced that the upload use content type application/json, that is a viable CSRF protection and blocks this attack - but it's not always thought of as CSRF protection.

You might, given #3, see where this is going already. You can submit files via script. There are two ways to do this.

  • The straightforward one is to use a CORS (or non-CORS fetch) request to simulate submission of a <form action="{vulnerable page}" method="post" enctype="multipart/form-data"><input type="file"></form> HTML form. This isn't that hard to do - it's a bit of typing, but fundamentally it's no different from other script-based requests, and because multipart/form-data is an allowed content type for forms, it won't even make your request non-simple and require a CORS pre-flight. The problem is, this doesn't navigate the browser to the response, so it's only useful for XSS if you can send the user to a vulnerable page before or after submitting the attack, and have the payload reflected anyway. That's quite rare.
  • The complicated[1] one is to create an HTML form on a page you control, dynamically set it to upload a blob and "filename" of your choosing, and submit it immediately using script. A lot of people will tell you this can't be done and a lot of file upload endpoints rely on that assumption (which means, among other things, they rarely have CSRF protection), but it's totally possible, just complicated. See https://stackoverflow.com/a/70485949/3909000[2] for the technique.

The full PoC attack page for the second approach - the one you'll probably have to use if this attack is possible at all, since I expect the vulnerable site will require a navigation request - might look something like this (changing any string with "target" in it as appropriate, of course):

<html><body>
    <form action="https://target.site.tld/file/upload/endpoint" method="post" enctype="multipart/form-data">
        <input name="target_input_name" type="file">
    </form><script>
        let dt = new DataTransfer()
        let f = new File(['foo'], "<svg onload=\"alert('XSS!\n'+document.location+'\n'+document.cookie')\">.png", {type: 'image/png'})
        dt.items.add(f)
        document.querySelector('input').files = dt.files
        document.forms[0].submit()
    </script>
</body></html>

[1] I spent way too long researching this. You can't set an HTMLInputElement's files property to anything except a FileList ("HTMLInputElement.files setter: Value being assigned does not implement interface FileList.", you can't construct a FileList ("TypeError: Illegal constructor"), and you can't set the elements of a FileList directly (it has a setter for item but this just fails silently).

[2] The steps are:

  1. Create a DataTransfer object (let dt = new DataTransfer())
  2. Add a File object to its items property (dt.items.add(new File(['fake file contents'], '<img src=x onerror=alert(1)>.png')))
  3. Access the DataTransfer object's items as a FileList through the files property and assign that to an HTMLInputElement's files property (document.querySelector('input').files = dt.files)
0

The XSS payload is only executed in the context of the uploader, so basically the only way to abuse is by social engineering a victim to upload your file.

Of course, you would want to make the payload more interesting first. This is just checking the regular XSS abuse methods. For instance, check if any sensitive cookie is missing the HttpOnly-flag which could be extracted. Your options will be limited since you are restricted to file names, but it may be possible.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .