Skip to content

Commit

Permalink
Merge pull request #433 from WordImpress/issue/432
Browse files Browse the repository at this point in the history
Fixed vulnerability within wp-sessions.php
  • Loading branch information
Devin Walker committed Dec 14, 2015
2 parents 5dab0b0 + d804d96 commit 5bb909e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 23 deletions.
2 changes: 1 addition & 1 deletion give.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ private function setup_constants() {

// Plugin version
if ( ! defined( 'GIVE_VERSION' ) ) {
define( 'GIVE_VERSION', '1.3.2' );
define( 'GIVE_VERSION', '1.3.3' );
}

// Plugin Folder Path
Expand Down
41 changes: 27 additions & 14 deletions includes/libraries/class-wp-session.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* Standardizes WordPress session data using database-backed options for storage.
* for storing user session information.
*
* @package WordPress
* @package WordPress
* @subpackage Session
* @since 3.7.0
* @since 3.7.0
*/

/**
Expand Down Expand Up @@ -66,17 +66,20 @@ public static function get_instance() {
* create a new session with that ID.
*
* @param $session_id
*
* @uses apply_filters Calls `wp_session_expiration` to determine how long until sessions expire.
*/
protected function __construct() {
if ( isset( $_COOKIE[WP_SESSION_COOKIE] ) ) {
$cookie = stripslashes( $_COOKIE[WP_SESSION_COOKIE] );
if ( isset( $_COOKIE[ WP_SESSION_COOKIE ] ) ) {
$cookie = stripslashes( $_COOKIE[ WP_SESSION_COOKIE ] );
$cookie_crumbs = explode( '||', $cookie );

$this->session_id = $cookie_crumbs[0];
$this->expires = $cookie_crumbs[1];
if ( $this->is_valid_md5( $cookie_crumbs[0] ) ) {
$this->session_id = $cookie_crumbs[0];
} else {
$this->regenerate_id( true );
}
$this->expires = $cookie_crumbs[1];
$this->exp_variant = $cookie_crumbs[2];

// Update the session expiration if we're past the variant time
if ( time() > $this->exp_variant ) {
$this->set_expiration();
Expand All @@ -87,9 +90,7 @@ protected function __construct() {
$this->session_id = $this->generate_id();
$this->set_expiration();
}

$this->read_data();

$this->set_cookie();

}
Expand All @@ -114,14 +115,14 @@ protected function __construct() {
*/
protected function set_expiration() {
$this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 );
$this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
$this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
}

/**
* Set the session cookie
*/
protected function set_cookie() {
@setcookie( WP_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant , $this->expires, COOKIEPATH, COOKIE_DOMAIN );
@setcookie( WP_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant, $this->expires, COOKIEPATH, COOKIE_DOMAIN );
}

/**
Expand All @@ -130,7 +131,7 @@ protected function set_cookie() {
* @return string
*/
protected function generate_id() {
require_once( ABSPATH . 'wp-includes/class-phpass.php');
require_once( ABSPATH . 'wp-includes/class-phpass.php' );
$hasher = new PasswordHash( 8, false );

return md5( $hasher->get_random_bytes( 32 ) );
Expand All @@ -149,6 +150,17 @@ protected function read_data() {
return $this->container;
}

/**
* Checks if is valid md5 string
*
* @param string $md5
*
* @return int
*/
protected function is_valid_md5( $md5 = '' ) {
return preg_match( '/^[a-f0-9]{32}$/', $md5 );
}

/**
* Write the data from the current session to the data storage system.
*/
Expand Down Expand Up @@ -188,6 +200,7 @@ public function json_in( $data ) {

if ( is_array( $array ) ) {
$this->container = $array;

return true;
}

Expand Down Expand Up @@ -215,7 +228,7 @@ public function regenerate_id( $delete_old = false ) {
* @return bool
*/
public function session_started() {
return !!self::$instance;
return ! ! self::$instance;
}

/**
Expand Down
18 changes: 10 additions & 8 deletions includes/libraries/wp-session.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* Standardizes WordPress session data and uses either database transients or in-memory caching
* for storing user session information.
*
* @package WordPress
* @package WordPress
* @subpackage Session
* @since 3.7.0
* @since 3.7.0
*/

/**
Expand Down Expand Up @@ -78,6 +78,7 @@ function wp_session_start() {

return $wp_session->session_started();
}

add_action( 'plugins_loaded', 'wp_session_start' );

/**
Expand Down Expand Up @@ -113,6 +114,7 @@ function wp_session_write_close() {
$wp_session->write_data();
do_action( 'wp_session_commit' );
}

add_action( 'shutdown', 'wp_session_write_close' );

/**
Expand All @@ -132,21 +134,19 @@ function wp_session_cleanup() {
if ( ! defined( 'WP_INSTALLING' ) ) {
$expiration_keys = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%'" );

$now = current_time( 'timestamp' );
$now = current_time( 'timestamp' );
$expired_sessions = array();

foreach( $expiration_keys as $expiration ) {
foreach ( $expiration_keys as $expiration ) {
// If the session has expired
if ( $now > intval( $expiration->option_value ) ) {
// Get the session ID by parsing the option_name
$session_id = substr( $expiration->option_name, 20 );

if( (int) -1 === (int) $session_id ) {
if ( (int) -1 === (int) $session_id || ! preg_match( '/^[a-f0-9]{32}$/', $session_id ) ) {
continue;
}

$expired_sessions[] = $expiration->option_name;
$expired_sessions[] = "_wp_session_$session_id";
$expired_sessions[] = esc_sql( "_wp_session_$session_id" );
}
}

Expand All @@ -160,6 +160,7 @@ function wp_session_cleanup() {
// Allow other plugins to hook in to the garbage collection process.
do_action( 'wp_session_cleanup' );
}

add_action( 'wp_session_garbage_collection', 'wp_session_cleanup' );

/**
Expand All @@ -170,4 +171,5 @@ function wp_session_register_garbage_collection() {
wp_schedule_event( current_time( 'timestamp' ), 'twicedaily', 'wp_session_garbage_collection' );
}
}

add_action( 'wp', 'wp_session_register_garbage_collection' );
3 changes: 3 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ We also really like WooCommerce. It's hands-down the most robust eCommerce platf

== Changelog ==

= 1.3.3 =
* Fixed security vulnerability due to WP session IDs

= 1.3.2 =
* New: German/Deutsch translation for Give provided by Konrad - Thanks! :) - https://github.com/WordImpress/Give/issues/383
* New: Polish/Polski translation provided by Emilia - Thanks! :) - https://github.com/WordImpress/Give/issues/418
Expand Down

0 comments on commit 5bb909e

Please sign in to comment.