Skip to content

Commit 4b61d83

Browse files
committed
Version 3.2.2
Fixed: Setting of S3 storage class STANDARD | STANDARD_IA | REDUCED_REDUNDANCY Fixed: Potential security problems on log view and file download
1 parent 96784ab commit 4b61d83

13 files changed

+268
-211
lines changed

.htaccess

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<Files *.php>
2+
order allow,deny
3+
deny from all
4+
</Files>

backwpup.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Description: WordPress Backup Plugin
66
* Author: Inpsyde GmbH
77
* Author URI: http://inpsyde.com
8-
* Version: 3.2.1
8+
* Version: 3.2.2
99
* Text Domain: backwpup
1010
* Domain Path: /languages/
1111
* Network: true
@@ -364,7 +364,7 @@ public static function get_registered_destinations() {
364364
'needed' => array(
365365
'php_version' => '5.3.3',
366366
'functions' => array( 'curl_exec' ),
367-
'classes' => array()
367+
'classes' => array( 'XMLWriter' )
368368
),
369369
'autoload' => array( 'Aws\\Common' => dirname( __FILE__ ) .'/vendor',
370370
'Aws\\S3' => dirname( __FILE__ ) .'/vendor',

inc/class-destination-folder.php

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,20 @@ public function edit_form_post_save( $jobid ) {
7373
*/
7474
public function file_delete( $jobdest, $backupfile ) {
7575

76-
if ( is_writeable( $backupfile ) && !is_dir( $backupfile ) && !is_link( $backupfile ) )
77-
unlink( $backupfile );
76+
list( $jobid, $dest ) = explode( '_', $jobdest, 2 );
77+
78+
if ( empty( $jobid ) ) {
79+
return;
80+
}
81+
82+
$backup_dir = esc_attr( BackWPup_Option::get( (int)$jobid, 'backupdir' ) );
83+
$backup_dir = BackWPup_File::get_absolute_path( $backup_dir );
84+
85+
$backupfile = realpath( trailingslashit( $backup_dir ) . basename( $backupfile ) );
7886

87+
if ( $backupfile && is_writeable( $backupfile ) && !is_dir( $backupfile ) && !is_link( $backupfile ) ) {
88+
unlink( $backupfile );
89+
}
7990
}
8091

8192
/**
@@ -84,7 +95,13 @@ public function file_delete( $jobdest, $backupfile ) {
8495
*/
8596
public function file_download( $jobid, $get_file ) {
8697

87-
if ( is_readable( $get_file ) ) {
98+
$backup_dir = esc_attr( BackWPup_Option::get( (int)$jobid, 'backupdir' ) );
99+
$backup_dir = BackWPup_File::get_absolute_path( $backup_dir );
100+
101+
$get_file = realpath( trailingslashit( $backup_dir ) . basename( $get_file ) );
102+
103+
if ( $get_file && is_readable( $get_file ) ) {
104+
while( @ob_end_clean() );
88105
header( "Pragma: public" );
89106
header( "Expires: 0" );
90107
header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
@@ -93,14 +110,12 @@ public function file_download( $jobid, $get_file ) {
93110
header( "Content-Transfer-Encoding: binary" );
94111
header( "Content-Length: " . filesize( $get_file ) );
95112
@set_time_limit( 300 );
96-
//chunked readfile
97-
@ob_end_clean();
113+
//chunked read file
98114
$handle = fopen( $get_file, 'rb' );
99115
if ( $handle ) {
100116
while ( ! feof( $handle ) ) {
101-
echo fread( $handle, 20482048 ); //2MB chunkes
102-
@ob_flush();
103-
@flush();
117+
echo fread( $handle, 10241024 ); //chunks
118+
flush();
104119
}
105120
fclose( $handle );
106121
}
@@ -119,7 +134,7 @@ public function file_download( $jobid, $get_file ) {
119134
*/
120135
public function file_get_list( $jobdest ) {
121136

122-
list( $jobid, $dest ) = explode( '_', $jobdest );
137+
list( $jobid, $dest ) = explode( '_', $jobdest, 2 );
123138
$filecounter = 0;
124139
$files = array();
125140
$backup_folder = BackWPup_Option::get( $jobid, 'backupdir' );
@@ -136,7 +151,7 @@ public function file_get_list( $jobdest ) {
136151
$files[ $filecounter ][ 'downloadurl' ] = add_query_arg( array(
137152
'page' => 'backwpupbackups',
138153
'action' => 'downloadfolder',
139-
'file' => $backup_folder . $file,
154+
'file' => $file,
140155
'jobid' => $jobid
141156
), network_admin_url( 'admin.php' ) );
142157
$files[ $filecounter ][ 'filesize' ] = filesize( $backup_folder . $file );
@@ -161,7 +176,7 @@ public function job_run_archive( BackWPup_Job$job_object ) {
161176
BackWPup_Option::update( $job_object->job[ 'jobid' ], 'lastbackupdownloadurl', add_query_arg( array(
162177
'page' => 'backwpupbackups',
163178
'action' => 'downloadfolder',
164-
'file' => $job_object->backup_folder . $job_object->backup_file,
179+
'file' => basename( $job_object->backup_file ),
165180
'jobid' => $job_object->job[ 'jobid' ]
166181
), network_admin_url( 'admin.php' ) ) );
167182
//Delete old Backupfiles

inc/class-destination-s3-v1.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public function edit_tab( $jobid ) {
175175
<th scope="row"><label for="ids3storageclass"><?php _e( 'Amazon: Storage Class', 'backwpup' ); ?></label></th>
176176
<td>
177177
<select name="s3storageclass" id="ids3storageclass" title="<?php _e( 'Amazon: Storage Class', 'backwpup' ); ?>">
178-
<option value="" <?php selected( 'us-east-1', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Standard', 'backwpup' ); ?></option>
178+
<option value="" <?php selected( '', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Standard', 'backwpup' ); ?></option>
179179
<option value="STANDARD_IA" <?php selected( 'STANDARD_IA', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Standard-Infrequent Access', 'backwpup' ); ?></option>
180180
<option value="REDUCED_REDUNDANCY" <?php selected( 'REDUCED_REDUNDANCY', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Reduced Redundancy', 'backwpup' ); ?></option>
181181
</select>

inc/class-destination-s3.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public function edit_tab( $jobid ) {
190190
<th scope="row"><label for="ids3storageclass"><?php _e( 'Amazon: Storage Class', 'backwpup' ); ?></label></th>
191191
<td>
192192
<select name="s3storageclass" id="ids3storageclass" title="<?php _e( 'Amazon: Storage Class', 'backwpup' ); ?>">
193-
<option value="" <?php selected( 'us-east-1', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Standard', 'backwpup' ); ?></option>
193+
<option value="" <?php selected( '', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Standard', 'backwpup' ); ?></option>
194194
<option value="STANDARD_IA" <?php selected( 'STANDARD_IA', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Standard-Infrequent Access', 'backwpup' ); ?></option>
195195
<option value="REDUCED_REDUNDANCY" <?php selected( 'REDUCED_REDUNDANCY', BackWPup_Option::get( $jobid, 's3storageclass' ), TRUE ) ?>><?php _e( 'Reduced Redundancy', 'backwpup' ); ?></option>
196196
</select>
@@ -416,10 +416,14 @@ public function job_run_archive( BackWPup_Job $job_object ) {
416416
$create_args = array();
417417
$create_args[ 'Bucket' ] = $job_object->job[ 's3bucket' ];
418418
$create_args[ 'ACL' ] = 'private';
419-
if ( ! empty( $job_object->job[ 's3ssencrypt' ] ) )
420-
$create_args[ 'ServerSideEncryption' ] = $job_object->job[ 's3ssencrypt' ]; //AES256
421-
if ( ! empty( $job_object->job[ 's3storageclass' ] ) ) //REDUCED_REDUNDANCY
419+
//encrxption
420+
if ( ! empty( $job_object->job[ 's3ssencrypt' ] ) ) {
421+
$create_args[ 'ServerSideEncryption' ] = $job_object->job[ 's3ssencrypt' ];
422+
}
423+
//Storage Class
424+
if ( ! empty( $job_object->job[ 's3storageclass' ] ) ) {
422425
$create_args[ 'StorageClass' ] = $job_object->job[ 's3storageclass' ];
426+
}
423427
$create_args[ 'Metadata' ] = array( 'BackupTime' => date( 'Y-m-d H:i:s', $job_object->start_time ) );
424428

425429
$create_args[ 'Body' ] = $up_file_handle;
@@ -444,10 +448,12 @@ public function job_run_archive( BackWPup_Job $job_object ) {
444448
'Bucket' => $job_object->job[ 's3bucket' ],
445449
'ContentType' => $job_object->get_mime_type( $job_object->backup_folder . $job_object->backup_file ),
446450
'Key' => $job_object->job[ 's3dir' ] . $job_object->backup_file );
447-
if ( !empty( $job_object->job[ 's3ssencrypt' ] ) )
451+
if ( !empty( $job_object->job[ 's3ssencrypt' ] ) ) {
448452
$args[ 'ServerSideEncryption' ] = $job_object->job[ 's3ssencrypt' ];
449-
if ( !empty( $job_object->job[ 's3storageclass' ] ) )
450-
$args[ 'StorageClass' ] = empty( $job_object->job[ 's3storageclass' ] ) ? 'STANDARD' : 'REDUCED_REDUNDANCY';
453+
}
454+
if ( !empty( $job_object->job[ 's3storageclass' ] ) ) {
455+
$args[ 'StorageClass' ] = empty( $job_object->job[ 's3storageclass' ] ) ? '' : $job_object->job[ 's3storageclass' ];
456+
}
451457

452458
$upload = $s3->createMultipartUpload( $args );
453459

inc/class-job.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,7 @@ public static function read_logheader( $logfile ) {
10841084
//get metadata of logfile
10851085
$metas = array();
10861086
if ( is_readable( $logfile ) ) {
1087-
if ( '.gz' == substr( $logfile, -3 ) )
1087+
if ( '.gz' == substr( $logfile, -3 ) )
10881088
$metas = (array)get_meta_tags( 'compress.zlib://' . $logfile );
10891089
else
10901090
$metas = (array)get_meta_tags( $logfile );
@@ -1094,8 +1094,7 @@ public static function read_logheader( $logfile ) {
10941094
foreach ( $usedmetas as $keyword => $field ) {
10951095
if ( isset( $metas[ $keyword ] ) ) {
10961096
$joddata[ $field ] = $metas[ $keyword ];
1097-
}
1098-
else {
1097+
} else {
10991098
$joddata[ $field ] = '';
11001099
}
11011100
}

inc/class-mysqldump.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public function __construct( $args = array() ) {
114114
if ( ! empty( $args[ 'dbcharset' ] ) && method_exists( $this->mysqli, 'set_charset' ) ) {
115115
$res = $this->mysqli->set_charset( $args[ 'dbcharset' ] );
116116
if ( ! $res ) {
117-
throw new BackWPup_MySQLDump_Exception( sprintf( _x( 'Cannot set DB charset to %s','Database Charset', 'backwpup' ), $args[ 'dbcharset' ] ) );
117+
throw new BackWPup_MySQLDump_Exception( sprintf( _x( 'Cannot set DB charset to %s error: %s','Database Charset', 'backwpup' ), $args[ 'dbcharset' ], $this->mysqli->error ) );
118118
}
119119
}
120120

inc/class-page-backups.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,12 @@ function column_file( $item ) {
309309
if ( ! empty( $item[ 'info' ] ) )
310310
$r .= esc_attr( $item[ 'info' ] ) . '<br />';
311311
$actions = array();
312-
if ( current_user_can( 'backwpup_backups_delete' ) )
312+
if ( current_user_can( 'backwpup_backups_delete' ) ) {
313313
$actions[ 'delete' ] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url( network_admin_url( 'admin.php' ) . '?page=backwpupbackups&action=delete&jobdest-top=' . $this->jobid . '_' . $this->dest . '&paged=' . $this->get_pagenum() . '&backupfiles[]=' . esc_attr( $item[ 'file' ] ), 'bulk-backups' ) . "\" onclick=\"if ( confirm('" . esc_js( __( "You are about to delete this backup archive. \n 'Cancel' to stop, 'OK' to delete.", "backwpup" ) ) . "') ) { return true;}return false;\">" . __( 'Delete', 'backwpup' ) . "</a>";
314-
if ( current_user_can( 'backwpup_backups_download' ) && ! empty( $item[ 'downloadurl' ] ) )
315-
$actions[ 'download' ] = "<a href=\"" . wp_nonce_url( $item[ 'downloadurl' ], 'download-backup' ) . "\">" . __( 'Download', 'backwpup' ) . "</a>";
314+
}
315+
if ( current_user_can( 'backwpup_backups_download' ) && ! empty( $item[ 'downloadurl' ] ) ) {
316+
$actions[ 'download' ] = "<a href=\"" . wp_nonce_url( $item[ 'downloadurl' ], 'download-backup_' . $this->jobid ) . "\">" . __( 'Download', 'backwpup' ) . "</a>";
317+
}
316318
$r .= $this->row_actions( $actions );
317319

318320
return $r;
@@ -411,10 +413,10 @@ public static function load() {
411413
if ( ! current_user_can( 'backwpup_backups_download' ) ) {
412414
wp_die( __( 'Sorry, you don\'t have permissions to do that.', 'backwpup') );
413415
}
414-
check_admin_referer( 'download-backup' );
416+
check_admin_referer( 'download-backup_' . $_GET[ 'jobid' ] );
415417
/** @var BackWPup_Destinations $dest_class */
416418
$dest_class = BackWPup::get_destination( $dest );
417-
$dest_class->file_download( (int)$_GET[ 'jobid' ], $_GET[ 'file' ] );
419+
$dest_class->file_download( (int)$_GET[ 'jobid' ], trim( $_GET[ 'file' ] ) );
418420
die();
419421
}
420422
}

inc/class-page-backwpup.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ private static function mb_last_logs() {
315315
$alternate = FALSE;
316316
}
317317
echo '<td>' . sprintf( __( '%1$s at %2$s', 'backwpup' ), date_i18n( get_option( 'date_format' ) , $logdata[ 'logtime' ] ), date_i18n( get_option( 'time_format' ), $logdata[ 'logtime' ] ) ) . '</td>';
318-
echo '<td><a class="thickbox" href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&logfile=' . basename( $logfile ) .'&_ajax_nonce=' . wp_create_nonce( 'view-logs' ) . '&amp;TB_iframe=true&amp;width=640&amp;height=440" title="' . esc_attr( basename( $logfile ) ) . '">' . $logdata[ 'name' ] . '</i></a></td>';
318+
$log_name = str_replace( array( '.html', '.gz' ), '', basename( $logfile ) );
319+
echo '<td><a class="thickbox" href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&log=' . $log_name .'&_ajax_nonce=' . wp_create_nonce( 'view-log_' . $log_name ) . '&amp;TB_iframe=true&amp;width=640&amp;height=440" title="' . esc_attr( basename( $logfile ) ) . '">' . $logdata[ 'name' ] . '</i></a></td>';
319320
echo '<td>';
320321
if ( $logdata[ 'errors' ] > 0 )
321322
printf( '<span style="color:red;font-weight:bold;">' . _n( "%d ERROR", "%d ERRORS", $logdata[ 'errors' ], 'backwpup' ) . '</span><br />', $logdata[ 'errors' ] );

inc/class-page-jobs.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,11 @@ function column_jobname( $item ) {
182182
}
183183
if ( current_user_can( 'backwpup_logs' ) && BackWPup_Option::get( $item, 'logfile' ) ) {
184184
$logfile = basename( BackWPup_Option::get( $item, 'logfile' ) );
185-
if ( is_object( $this->job_object ) && $this->job_object->job[ 'jobid' ] == $item )
186-
$logfile = basename( $this->job_object->logfile );
187-
$actions[ 'lastlog' ] = '<a href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&logfile=' . $logfile .'&_ajax_nonce=' . wp_create_nonce( 'view-logs' ) . '&amp;TB_iframe=true&amp;width=640&amp;height=440\" title="' . esc_attr( $logfile ) . '" class="thickbox">' . __( 'Last log', 'backwpup' ) . '</a>';
185+
if ( is_object( $this->job_object ) && $this->job_object->job[ 'jobid' ] == $item ) {
186+
$logfile = basename( $this->job_object->logfile );
187+
}
188+
$log_name = str_replace( array( '.html', '.gz' ), '', basename( $logfile ) );
189+
$actions[ 'lastlog' ] = '<a href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&log=' . $log_name .'&_ajax_nonce=' . wp_create_nonce( 'view-log_'. $log_name ) . '&amp;TB_iframe=true&amp;width=640&amp;height=440\" title="' . esc_attr( $logfile ) . '" class="thickbox">' . __( 'Last log', 'backwpup' ) . '</a>';
188190
}
189191
$actions = apply_filters( 'backwpup_page_jobs_actions', $actions, $item, FALSE );
190192
$r .= '<div class="job-normal"' . $job_normal_hide . '>' . $this->row_actions( $actions ) . '</div>';
@@ -319,15 +321,19 @@ function column_last( $item ) {
319321
$r .= __( 'not yet', 'backwpup' );
320322
}
321323
$r .= "<br /><span class=\"last-action-links\">";
322-
if ( current_user_can( 'backwpup_backups_download' ) && BackWPup_Option::get( $item, 'lastbackupdownloadurl' ) ) {
323-
$r .= "<a href=\"" . wp_nonce_url( BackWPup_Option::get( $item, 'lastbackupdownloadurl' ), 'download-backup' ) . "\" title=\"" . esc_attr( __( 'Download last backup', 'backwpup' ) ) . "\">" . __( 'Download', 'backwpup' ) . "</a> | ";
324+
if ( current_user_can( 'backwpup_backups_download' ) ) {
325+
$download_url = BackWPup_Option::get( $item, 'lastbackupdownloadurl' );
326+
if ( ! empty( $download_url ) ) {
327+
$r .= "<a href=\"" . wp_nonce_url( $download_url, 'download-backup_' . $item ). "\" title=\"" . esc_attr( __( 'Download last backup', 'backwpup' ) ) . "\">" . __( 'Download', 'backwpup' ) . "</a> | ";
328+
}
324329
}
325330
if ( current_user_can( 'backwpup_logs' ) && BackWPup_Option::get( $item, 'logfile' ) ) {
326331
$logfile = basename( BackWPup_Option::get( $item, 'logfile' ) );
327332
if ( is_object( $this->job_object ) && $this->job_object->job[ 'jobid' ] == $item ) {
328333
$logfile = basename( $this->job_object->logfile );
329334
}
330-
$r .= '<a class="thickbox" href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&logfile=' . $logfile .'&_ajax_nonce=' . wp_create_nonce( 'view-logs' ) . '&amp;TB_iframe=true&amp;width=640&amp;height=440" title="' . esc_attr( $logfile ) . '">' . __( 'Log', 'backwpup' ) . '</a>';
335+
$log_name = str_replace( array( '.html', '.gz' ), '', basename( $logfile ) );
336+
$r .= '<a class="thickbox" href="' . admin_url( 'admin-ajax.php' ) . '?&action=backwpup_view_log&log=' . $log_name .'&_ajax_nonce=' . wp_create_nonce( 'view-log_' . $log_name ) . '&amp;TB_iframe=true&amp;width=640&amp;height=440" title="' . esc_attr( $logfile ) . '">' . __( 'Log', 'backwpup' ) . '</a>';
331337

332338
}
333339
$r .= "</span>";

0 commit comments

Comments
 (0)