Wordpress 4.7.2 - Two XSS in Media Upload when file too large.
High
W
WordPress
Submitted None
Actions:
Reported by
skansing
Vulnerability Details
Technical details and impact analysis
Description
-------------------
An attacker can inject a malicious script in to the filename which a victim tries to upload leading to XSS inside the administrators control panel.
Two different "file to large" cases end up in interpolating the file name and appending it into DOM unsanitized leading to XSS.
I have attached pictures of one of the cases, in the attached case the file was 12.4 MB, in a freshly installed environment. For reproduction note that any file type can be used (.jar whatever) as the vuln happens before the type is validated.
PoC
-------------------
Create a 20MB file called
`Dinosaurs secret life<img src=x onerror=alert(1)>.png`
Goto your wordpress site `http://127.0.0.1/wp-admin/media-new.php` and drag`n`drop or use file manager or choose the file via. the "Select Files" button.
A error will appear with `... exceeds the maximum upload size for this site.` along with a alert box to display that the payload has been executed.
Details on XSS
-------------------
The file `script-loader.php` prepares an array of messages for use later.
```
// error message for both plupload and swfupload
$uploader_l10n = array(
...
'file_exceeds_size_limit' => __('%s exceeds the maximum upload size for this site.'),
'big_upload_failed' => __('Please try uploading this file with the %1$sbrowser uploader%2$s.'),
...
);
```
The payload will be injected into the `%s` in the key `file_exceeds_size_limit`.
This happens because the `$uploader_l10n` is passed to `handlers.min.js` (non minified version shown)
and interpolated without escaping the value previously.
First the value passes trough a error case
```
// $uploader_l10n
case plupload.FILE_SIZE_ERROR:
uploadSizeError(uploader, fileObj); // fileObj contains the filename payload in name attribute.
break;
....
if ( max > hundredmb && fileObj.size > hundredmb )
wpFileError( fileObj, pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>') );
```
and lastely interpolated and appended to the dom.
```
function uploadSizeError( up, file, over100mb ) {
var message;
if ( over100mb )
message = pluploadL10n.big_upload_queued.replace('%s', file.name) + ' ' + pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>');
else
message = pluploadL10n.file_exceeds_size_limit.replace('%s', file.name);
jQuery('#media-items').append('<div id="media-item-' + file.id + '" class="media-item error"><p>' + message + '</p></div>');
up.removeFile(file);
}
```
The critical lines are
```
message = pluploadL10n.big_upload_queued.replace('%s', file.name) + ' ' + pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>');
else
message = pluploadL10n.file_exceeds_size_limit.replace('%s', file.name);
```
# Suggested fix:
Remove the filename or escape safely in context.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Cross-site Scripting (XSS) - Generic