Skip to content

Commit 85940b8

Browse files
committed
Add a unique token to the Habari Silo upload form to ensure the validity of the upload
1 parent c43a0eb commit 85940b8

File tree

1 file changed

+67
-28
lines changed

1 file changed

+67
-28
lines changed

plugins/habarisilo/habarisilo.plugin.php

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -506,37 +506,42 @@ public function filter_media_panels( $panel, $silo, $path, $panelname)
506506
break;
507507
case 'upload':
508508
if ( isset( $_FILES['file'] ) ) {
509-
$size = Utils::human_size( $_FILES['file']['size'] );
510-
$panel .= '<div class="span-18" style="padding-top:30px;color: #e0e0e0;margin: 0px auto;"><p>' . _t( 'File: ' ) . $_FILES['file']['name'];
511-
$panel .= ( $_FILES['file']['size'] > 0 ) ? "({$size})" : '';
512-
$panel .= '</p>';
513-
514-
$path = self::SILO_NAME . '/' . preg_replace( '%\.{2,}%', '.', $path ). '/' . $_FILES['file']['name'];
515-
$asset = new MediaAsset( $path, false );
516-
$asset->upload( $_FILES['file'] );
517-
518-
if ( $asset->put() ) {
519-
$panel .= '<p>' . _t( 'File added successfully.' ) . '</p>';
520-
}
521-
else {
522-
$upload_errors = array(
523-
1 => _t( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.' ),
524-
2 => _t( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.' ),
525-
3 => _t( 'The uploaded file was only partially uploaded.' ),
526-
4 => _t( 'No file was uploaded.' ),
527-
6 => _t( 'Missing a temporary folder.' ),
528-
7 => _t( 'Failed to write file to disk.' ),
529-
8 => _t( 'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.' ),
530-
);
531-
532-
$panel .= '<p>' . _t( 'File could not be added to the silo.' ) . '</p>';
533-
$panel .= '<p><strong>' . $upload_errors[ $_FILES['file']['error'] ] . '</strong></p>';
509+
if ( isset( $_POST['token'] ) && isset( $_POST['token_ts'] ) && self::verify_token( $_POST['token'], $_POST['token_ts'] ) ) {
510+
$size = Utils::human_size( $_FILES['file']['size'] );
511+
$panel .= '<div class="span-18" style="padding-top:30px;color: #e0e0e0;margin: 0px auto;"><p>' . _t( 'File: ' ) . $_FILES['file']['name'];
512+
$panel .= ( $_FILES['file']['size'] > 0 ) ? "({$size})" : '';
513+
$panel .= '</p>';
514+
515+
$path = self::SILO_NAME . '/' . preg_replace( '%\.{2,}%', '.', $path ). '/' . $_FILES['file']['name'];
516+
$asset = new MediaAsset( $path, false );
517+
$asset->upload( $_FILES['file'] );
518+
519+
if ( $asset->put() ) {
520+
$panel .= '<p>' . _t( 'File added successfully.' ) . '</p>';
521+
}
522+
else {
523+
$upload_errors = array(
524+
1 => _t( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.' ),
525+
2 => _t( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.' ),
526+
3 => _t( 'The uploaded file was only partially uploaded.' ),
527+
4 => _t( 'No file was uploaded.' ),
528+
6 => _t( 'Missing a temporary folder.' ),
529+
7 => _t( 'Failed to write file to disk.' ),
530+
8 => _t( 'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.' ),
531+
);
532+
533+
$panel .= '<p>' . _t( 'File could not be added to the silo.' ) . '</p>';
534+
$panel .= '<p><strong>' . $upload_errors[ $_FILES['file']['error'] ] . '</strong></p>';
535+
}
536+
537+
$panel .= '<p><a href="#" onclick="habari.media.forceReload();habari.media.showdir(\'' . dirname( $path ) . '\');">' . _t( 'Browse the current silo path.' ) . '</a></p></div>';
538+
} else {
539+
$panel .= '<p><strong>' ._t( 'Suspicious behaviour or too much time has elapsed. Please upload your file again.' ) . '</strong></p>';
534540
}
535-
536-
$panel .= '<p><a href="#" onclick="habari.media.forceReload();habari.media.showdir(\'' . dirname( $path ) . '\');">' . _t( 'Browse the current silo path.' ) . '</a></p></div>';
537541
}
538542
else {
539-
543+
$token_ts = time();
544+
$token = self::create_token( $token_ts );
540545
$fullpath = self::SILO_NAME . '/' . $path;
541546
$form_action = URL::get( 'admin_ajax', array( 'context' => 'media_upload' ) );
542547
$panel .= <<< UPLOAD_FORM
@@ -545,6 +550,8 @@ public function filter_media_panels( $panel, $silo, $path, $panelname)
545550
<p><input type="file" name="file"><input type="submit" name="upload" value="%s">
546551
<input type="hidden" name="path" value="{$fullpath}">
547552
<input type="hidden" name="panel" value="{$panelname}">
553+
<input type="hidden" name="token" value="{$token}">
554+
<input type="hidden" name="token_ts" value="{$token_ts}">
548555
</p>
549556
</form>
550557
<iframe id="simple_upload_frame" name="simple_upload_frame" style="width:1px;height:1px;" onload="simple_uploaded();"></iframe>
@@ -656,6 +663,38 @@ private static function isEmptyDir( $dir )
656663
return ( ( $files = @scandir( $dir ) ) && count( $files ) <= 2 );
657664
}
658665

666+
/**
667+
* Create the upload token based on the time string submitted and the UID for this Habari installation.
668+
*
669+
* @param integer $timestamp
670+
* @return string
671+
*/
672+
private static function create_token( $timestamp )
673+
{
674+
return substr( md5( $timestamp . Options::get( 'GUID' ) ), 0, 10 );
675+
}
676+
677+
/**
678+
* Verify that the token and timestamp passed are valid.
679+
*
680+
* @param string $token
681+
* @param integer $timestamp
682+
*
683+
* @TODO By default this gives the user 5 mins to upload a file from the time
684+
* the form is display and the file uploaded. This should be sufficient,
685+
* but do we a) need this timeout and b) should it be configurable?
686+
*/
687+
private static function verify_token( $token, $timestamp )
688+
{
689+
if ( $token == self::create_token( $timestamp ) ) {
690+
if ( ( time() > ( $timestamp ) ) && ( time() < ( $timestamp + 5*60 ) ) ) {
691+
return true;
692+
}
693+
} else {
694+
return false;
695+
}
696+
}
697+
659698
}
660699

661700
?>

0 commit comments

Comments
 (0)