Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add check for GET and POST globals for state validation #707

Merged
merged 2 commits into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/WP_Auth0_LoginManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public function init_auth0() {

// Check for valid state nonce, set in WP_Auth0_Lock10_Options::get_state_obj().
// See https://auth0.com/docs/protocols/oauth2/oauth-state for more info.
$state_returned = isset( $_REQUEST['state'] ) ? rawurldecode( $_REQUEST['state'] ) : null;
$state_returned = $this->query_vars( 'state' );
if ( ! $state_returned || ! WP_Auth0_State_Handler::get_instance()->validate( $state_returned ) ) {
$this->die_on_login( __( 'Invalid state', 'wp-auth0' ) );
}
Expand Down Expand Up @@ -625,7 +625,7 @@ public static function build_authorize_url( array $params = array() ) {
}

/**
* Get a value from query_vars or $_REQUEST global.
* Get a value from query_vars or request global.
*
* @param string $key - query var key to return.
*
Expand All @@ -639,6 +639,12 @@ protected function query_vars( $key ) {
if ( isset( $_REQUEST[ $key ] ) ) {
return $_REQUEST[ $key ];
}
if ( isset( $_GET[ $key ] ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function only used in the WP_Auth0_LoginManager above?

I'm wondering if now accepting values from GET or POST as well as the previous objects opens up any kind of exploits. i.e. Perhaps we were validating some parameter we got posted back from auth but now the user could pre-inject a value on the URL so when we get redirected back we take the value from there rather than from the POST...

I think this function is a bit dangerous.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function only used in the WP_Auth0_LoginManager above?

Yes, protected.

I totally understand your concerns here and thought about implications. It's used to:

  • Get an auth0 parameter, which just triggers callback processing
  • Checks for a state param, which is validated one time against a stored value
  • Gets a code parameter which is exchanged immediately for tokens

The existing checks can only be internally set in WordPress, the ones I'm adding would just roll up into those if they are present (if everything goes according to plan) so no additional risk added here.

I'll address this in the upcoming, I agree that we should be looking for these values only where we expect them.

return $_GET[ $key ];
}
if ( isset( $_POST[ $key ] ) ) {
return $_POST[ $key ];
}
return null;
}

Expand Down
45 changes: 45 additions & 0 deletions tests/testLoginManagerInitAuth0.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,51 @@ public function testThatErrorInUrlStopsCallback() {
$this->assertContains( '<a href="https://test.auth0.com/v2/logout?client_id=__test_client_id__', $output );
}

public function testThatQueryVarIsFound() {
self::auth0Ready();
set_query_var( 'auth0', 1 );

$output = '';
try {
$this->login->init_auth0();
} catch ( Exception $e ) {
$output = $e->getMessage();
}

// This error means that the callback was triggered, which is what we are testing for.
$this->assertContains( 'There was a problem with your log in: Invalid state', $output );
}

public function testThatGetVarIsFound() {
self::auth0Ready();
$_GET['auth0'] = 1;

$output = '';
try {
$this->login->init_auth0();
} catch ( Exception $e ) {
$output = $e->getMessage();
}

// This error means that the callback was triggered, which is what we are testing for.
$this->assertContains( 'There was a problem with your log in: Invalid state', $output );
}

public function testThatPostVarIsFound() {
self::auth0Ready();
$_POST['auth0'] = 1;

$output = '';
try {
$this->login->init_auth0();
} catch ( Exception $e ) {
$output = $e->getMessage();
}

// This error means that the callback was triggered, which is what we are testing for.
$this->assertContains( 'There was a problem with your log in: Invalid state', $output );
}

/**
* Test that an error in the URL parameter logs the current user out.
*/
Expand Down