Skip to content

Commit

Permalink
Merge branch 'release/2.0.1' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
JDGrimes committed Jul 22, 2015
2 parents c29a6ac + acf8b0d commit e5c5bc8
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 74 deletions.
2 changes: 1 addition & 1 deletion src/admin/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ function wordpoints_admin_ajax_breaking_module_check() {
$nonce = get_option( 'wordpoints_module_check_nonce' );
}

if ( ! $nonce || $nonce !== $_GET['wordpoints_module_check'] ) {
if ( ! $nonce || ! hash_equals( $nonce, sanitize_key( $_GET['wordpoints_module_check'] ) ) ) {
wp_die( '', 403 );
}

Expand Down
2 changes: 1 addition & 1 deletion src/admin/includes/class-wordpoints-modules-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ public function single_row( $item ) {
switch ( $column_name ) {

case 'cb':
$checkbox_id = 'checkbox_' . md5( $module_data['name'] );
$checkbox_id = 'checkbox_' . sanitize_key( $module_file );

?>
<th scope="row" class="check-column">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ class WordPoints_Points_Logs_Query {
private $_cache_group;

/**
* The MD5 hash of the query for looking it up the the cache.
* The hash of the query for looking it up the the cache.
*
* @since 1.6.0
*
* @type string $_cache_query_md5
* @type string $_cache_query_hash
*/
private $_cache_query_md5;
private $_cache_query_hash;

/**
* The type of select being performed.
Expand Down Expand Up @@ -284,7 +284,7 @@ public function set_args( array $args ) {
$this->_args = array_merge( $this->_args, $args );

$this->_query_ready = false;
$this->_cache_query_md5 = null;
$this->_cache_query_hash = null;
}

/**
Expand Down Expand Up @@ -428,7 +428,7 @@ public function get_page( $page, $per_page = 25 ) {

$this->_select_type = 'SELECT';

unset( $this->_cache_query_md5 );
unset( $this->_cache_query_hash );

$results = $this->get();

Expand All @@ -439,7 +439,7 @@ public function get_page( $page, $per_page = 25 ) {
$this->_limit = '';
$this->_prepare_limit();

unset( $this->_cache_query_md5 );
unset( $this->_cache_query_hash );

return $results;
}
Expand Down Expand Up @@ -646,21 +646,21 @@ private function _cache_get( $type = null ) {
return false;
}

$this->_calc_cache_query_md5();
$this->_calc_cache_query_hash();

if ( ! isset( $cache[ $this->_cache_query_md5 ] ) ) {
if ( ! isset( $cache[ $this->_cache_query_hash ] ) ) {
return false;
}

if ( isset( $type ) ) {
if ( isset( $cache[ $this->_cache_query_md5 ][ $type ] ) ) {
return $cache[ $this->_cache_query_md5 ][ $type ];
if ( isset( $cache[ $this->_cache_query_hash ][ $type ] ) ) {
return $cache[ $this->_cache_query_hash ][ $type ];
} else {
return false;
}
}

return $cache[ $this->_cache_query_md5 ];
return $cache[ $this->_cache_query_hash ];
}

/**
Expand All @@ -676,33 +676,33 @@ private function _cache_set( $value, $type = null ) {

$cache = wp_cache_get( $this->_cache_key, $this->_cache_group );

$this->_calc_cache_query_md5();
$this->_calc_cache_query_hash();

if (
! isset( $cache[ $this->_cache_query_md5 ] )
|| ! is_array( $cache[ $this->_cache_query_md5 ] )
! isset( $cache[ $this->_cache_query_hash ] )
|| ! is_array( $cache[ $this->_cache_query_hash ] )
) {
$cache[ $this->_cache_query_md5 ] = array();
$cache[ $this->_cache_query_hash ] = array();
}

if ( isset( $type ) ) {
$cache[ $this->_cache_query_md5 ][ $type ] = $value;
$cache[ $this->_cache_query_hash ][ $type ] = $value;
} else {
$cache[ $this->_cache_query_md5 ] = $value;
$cache[ $this->_cache_query_hash ] = $value;
}

wp_cache_set( $this->_cache_key, $cache, $this->_cache_group );
}

/**
* Caclulate the MD5 hash of the query.
* Calculate the hash of the query.
*
* @since 1.6.0
*/
private function _calc_cache_query_md5() {
private function _calc_cache_query_hash() {

if ( ! isset( $this->_cache_query_md5 ) ) {
$this->_cache_query_md5 = md5( $this->get_sql() );
if ( ! isset( $this->_cache_query_hash ) ) {
$this->_cache_query_hash = wordpoints_hash( $this->get_sql() );
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/includes/class-breaking-updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ protected function validate_modules( $modules ) {
*/
protected function check_module( $module ) {

$rand_str = str_shuffle( md5( microtime() ) );
$nonce = md5( $rand_str . 'wordpoints_check_modules-' . $module );
$rand_str = str_shuffle( wordpoints_hash( microtime() ) );
$nonce = wordpoints_hash( $rand_str . 'wordpoints_check_modules-' . $module );

if ( 'network' === $this->context ) {
update_site_option( 'wordpoints_module_check_rand_str', $rand_str );
Expand Down
2 changes: 1 addition & 1 deletion src/includes/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @const WORDPOINTS_VERSION
*/
define( 'WORDPOINTS_VERSION', '2.0.0' );
define( 'WORDPOINTS_VERSION', '2.0.1' );

/**
* The full path to the plugin's main directory.
Expand Down
23 changes: 21 additions & 2 deletions src/includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function wordpoints_maintenance_shutdown_print_rand_str() {
$nonce = get_option( 'wordpoints_module_check_nonce' );
}

if ( ! $nonce || $nonce !== $_GET['wordpoints_module_check'] ) {
if ( ! $nonce || ! hash_equals( $nonce, sanitize_key( $_GET['wordpoints_module_check'] ) ) ) {
return;
}

Expand Down Expand Up @@ -143,7 +143,7 @@ function wordpoints_maintenance_filter_modules( $modules ) {
$nonce = get_option( 'wordpoints_module_check_nonce' );
}

if ( ! $nonce || $nonce !== $_GET['wordpoints_module_check'] ) {
if ( ! $nonce || ! hash_equals( $nonce, sanitize_key( $_GET['wordpoints_module_check'] ) ) ) {
return $modules;
}

Expand Down Expand Up @@ -1027,4 +1027,23 @@ function wordpoints_register_scripts() {}
add_action( 'wp_enqueue_scripts', 'wordpoints_register_scripts', 5 );
add_action( 'admin_enqueue_scripts', 'wordpoints_register_scripts', 5 );

/**
* Generate a cryptographically secure hash.
*
* You can use wp_hash() instead if you need to use a salt. However, at present that
* function uses the outdated MD5 hashing algorithm, so you will want to take that
* into consideration as well. The benefit of using this function instead is that it
* will use a strong hashing algorithm, and the hashes won't be invalidated when the
* salts change.
*
* @since 2.0.1
*
* @param string $data The data to generate a hash for.
*
* @return string The hash.
*/
function wordpoints_hash( $data ) {
return hash( 'sha256', $data );
}

// EOF
29 changes: 27 additions & 2 deletions src/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Contributors: jdgrimes
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=TPXS6B98HURLJ&lc=US&item_name=WordPoints&item_number=wordpressorg&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted
Tags: points, awards, rewards, cubepoints, credits, gamify, multisite, ranks
Requires at least: 4.2
Tested up to: 4.3-alpha-32280
Stable tag: 2.0.0
Tested up to: 4.3-beta3-33288
Stable tag: 2.0.1
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Expand Down Expand Up @@ -130,6 +130,27 @@ manage the ranks used on your site.

This plugin adheres to [Semantic Versioning](http://semver.org/).

= 2.0.1 - 2015-07-22 - (~5 hrs) =

##### Fixed

- In the table on the modules screen, the id of each checkbox is now based on the
module's file, instead of on the module name. This avoids duplicate ids when there
are multiple modules with the same name installed. Duplicate ids are not allowed,
and could have caused bugs on the Modules screen. You are now free to install as
many modules with the same name as you want without any fear of bugs ;-).

##### Security

- Use a stronger hashing algorithm to generate the keys for the points logs cache.
The use of a weaker algorithm could possibly have allowed a determined attacker to
view logs which they might not otherwise be able to.
- Use a stronger hashing algorithm to generate the key used to perform a module
compatibility check during a breaking update. This is not really a security concern,
because the time window for exploitation only lasts a few seconds, and all a
successful attacker would be able to do is view a list of modules installed on the
site.

= 2.0.0 - 2015-06-30 - (~70 hrs) =

##### Added
Expand Down Expand Up @@ -341,6 +362,10 @@ choosing the points type to add it to.
* Initial release

== Upgrade Notice ==
= 2.0.1 =
* This is a security hardening release, which fixes a small bug and strengthens two
very minor security weaknesses.

= 2.0.0 =
* This is a breaking update that includes emoji support, some bug fixes, and many
internal code improvements in preparation for new features. Some old code has been
Expand Down
4 changes: 2 additions & 2 deletions src/wordpoints.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Plugin Name: WordPoints
* Plugin URI: http://wordpoints.org/
* Description: Create one or more points systems for your site, and reward user activity.
* Version: 2.0.0
* Version: 2.0.1
* Author: J.D. Grimes
* Author URI: http://codesymphony.co/
* License: GPLv2
Expand Down Expand Up @@ -40,7 +40,7 @@
*
* @package WordPoints
* @author J.D. Grimes <[email protected]>
* @version 2.0.0
* @version 2.0.1
* @license http://opensource.org/licenses/gpl-license.php GPL, version 2 or later.
* @copyright 2013-2015 J.D. Grimes
*/
Expand Down
34 changes: 24 additions & 10 deletions tests/phpunit/tests/ajax/breaking-module-check.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,34 @@
*/
class WordPoints_Breaking_Module_Check_Ajax_Test extends WordPoints_AJAX_UnitTestCase {

/**
* The nonce value used in the tests.
*
* @since 2.0.1
*
* @var string
*/
protected $nonce;

/**
* @since 2.0.1
*/
public function setUp() {

parent::setUp();

$_GET['wordpoints_module_check'] = $this->nonce = sanitize_key( __METHOD__ );

update_option( 'wordpoints_module_check_nonce', $this->nonce );
}

/**
* That that the modules screen is displayed.
*
* @since 2.0.0
*/
public function test_displays_modules_screen() {

update_option( 'wordpoints_module_check_nonce', __METHOD__ );

$_GET['wordpoints_module_check'] = __METHOD__;

try {
$this->_handleAjax( 'nopriv_wordpoints_breaking_module_check' );
} catch ( WPAjaxDieContinueException $e ) {
Expand All @@ -51,12 +68,11 @@ public function test_displays_modules_screen() {
*/
public function test_network_wide() {

update_site_option( 'wordpoints_module_check_nonce', __METHOD__ );
delete_option( 'wordpoints_module_check_nonce' );
update_site_option( 'wordpoints_module_check_nonce', $this->nonce );

$GLOBALS['current_screen'] = WP_Screen::get( 'test-network' );

$_GET['wordpoints_module_check'] = __METHOD__;

try {
$this->_handleAjax( 'nopriv_wordpoints_breaking_module_check' );
} catch ( WPAjaxDieContinueException $e ) {
Expand All @@ -79,8 +95,6 @@ public function test_network_wide() {
*/
public function test_valid_nonce_required() {

update_option( 'wordpoints_module_check_nonce', __METHOD__ );

$_GET['wordpoints_module_check'] = 'invalid';

$this->setExpectedException( 'WPAjaxDieStopException', '' );
Expand All @@ -94,7 +108,7 @@ public function test_valid_nonce_required() {
*/
public function test_nonce_required() {

update_option( 'wordpoints_module_check_nonce', __METHOD__ );
unset( $_GET['wordpoints_module_check'] );

$this->setExpectedException( 'WPAjaxDieStopException', '' );
$this->_handleAjax( 'nopriv_wordpoints_breaking_module_check' );
Expand Down
14 changes: 14 additions & 0 deletions tests/phpunit/tests/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,20 @@ public function test_wordpoints_maintenance_filter_modules_network_wide() {

$this->assertEquals( array( 'test' => 0 ), $modules );
}

/**
* Test wordpoints_hash().
*
* @since 2.0.1
*
* @covers ::wordpoints_hash
*/
public function test_wordpoints_hash() {

$data = __METHOD__;

$this->assertEquals( hash( 'sha256', $data ), wordpoints_hash( $data ) );
}
}

// EOF
Loading

0 comments on commit e5c5bc8

Please sign in to comment.