Tokens are unusable, because DrupalWebTestCase::drupalGetToken() does not use a hash salt, while drupal_get_token() does. This bug makes it impossible to test code that uses tokens.

Core does not use this method. However, I have a contrib patching waiting that does: #1550940: Extend and test payment permissions

Comments

Status: Needs review » Needs work

The last submitted patch, drupalGetToken_hash_salt_00-d7.patch, failed testing.

xano’s picture

Title: DrupalWebTestCase::drupalGetToken » DrupalWebTestCase::drupalGetToken() does not add hash salt
Status: Needs work » Needs review
xano’s picture

Issue tags: +Tests
StatusFileSize
new1.85 KB

This patch adds a test to make sure DrupalWebTestCase::drupalGetToken() and drupal_get_token() return identical tokens. The assertion lives in a test that can be reused for testing other simpletest methods that are 'aliases' of core functionality.

Status: Needs review » Needs work

The last submitted patch, drupalGetToken_hash_salt_02.patch, failed testing.

sun’s picture

Issue tags: -Tests

Why do we have this method in the first place?

xano’s picture

Issue tags: +Tests

The session ID differs between the global one the tests can access and the one available when accessing the site through Simpletest's browser. Because of this, we need a method that matched drupal_get_token(), but uses Simpletest's browser's session_id.

sun’s picture

+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1256,7 +1256,7 @@ class DrupalWebTestCase extends DrupalTestCase {
   protected function drupalGetToken($value = '') {
     $private_key = drupal_get_private_key();
-    return drupal_hmac_base64($value, $this->session_id . $private_key);
+    return drupal_hmac_base64($value, $this->session_id . $private_key . drupal_get_hash_salt());
   }

+++ b/core/modules/simpletest/simpletest.test
@@ -318,6 +318,17 @@ class SimpleTestFunctionalTest extends DrupalWebTestCase {
+  function testAliasCode() {
+    // Test security token generation.
+    $session_id = session_id();
+    session_id($this->session_id);
+    $this->assertEqual(drupal_get_token('foo'), $this->drupalGetToken('foo'), 'DrupalWebTestCase::drupalGetToken() and drupal_get_token() generate identical tokens.');
+    session_id($session_id);
+  }

The problem is: drupalGetToken() does not do what testAliasCode() is doing.

Thus, it'll never work, except if you replicate all of the testAliasCode() code. But if you do that, then you no longer need drupalGetToken(), because you can directly call drupal_get_token().

xano’s picture

Well, there are two ways of generating tokens for use in Simpletest's browser:
1) We fake the session IDs every time and use drupal_get_token()
2) We use an 'alias' to prevent people from having to fake the session ID every time

Currently, core tries to do 2 and it's actually able to do that after applying my patch. You are suggesting approach 1?

sun’s picture

Issue tags: -Tests

Nope, this patch is correct. Can you re-roll (also, without the EOF newline error)?

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new3.25 KB

While this patch fixes drupalGetToken(), there's actually another problem in that $this->session_id gets reset to NULL on subsequently performed requests after drupalLogin().

Curious, what breaks?

sun’s picture

StatusFileSize
new2.36 KB

And once more without irrelevant changes.

andypost’s picture

Not sure that $this->session_id is set by simpletest... let's see
PS: masquerade module tests depends on this issue #1835954: Cleanup code and allow pass tests

sun’s picture

Assigned: xano » Unassigned

$this->session_id is definitely set by WebTestBase's curl methods. That's also why this patch removes an unset() there. ;)

Status: Needs review » Needs work

The last submitted patch, drupal8.test-drupalgettoken.11.patch, failed testing.

andypost’s picture

@sun Not sure about 8.x but in 7.x $this->session_id is empty - try debug($this->session_id)

EDIT: Probably $this->session_name is wrong too

andypost’s picture

Status: Needs work » Needs review
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.phpundefined
@@ -334,4 +334,30 @@ function asText(SimpleXMLElement $element) {
+    // Verify that session ID is reset upon logout.
+    $this->drupalLogout();
+    $this->assertFalse($this->session_id);
+  }

Also better to have a check that session_id() !== $this->session_id

+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.phpundefined
@@ -921,8 +921,7 @@ protected function curlExec($curl_options, $redirect = FALSE) {
-      $this->session_id = NULL;

This really needs more testing? but actually help to pass tests

andypost’s picture

Status: Needs review » Needs work

The last submitted patch, drupal8.test-drupalgettoken.11.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, drupal8.test-drupalgettoken.11.patch, failed testing.

xano’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, drupal8.test-drupalgettoken.11.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.99 KB
new972 bytes

Fixes tests, still can't find a reason why session tests are broken
Related issue commited #1739986: Fix fallback in drupal_get_hash_salt(), move it to bootstrap.inc, use instead of $GLOBALS['drupal_hash_salt']

Status: Needs review » Needs work

The last submitted patch, 1555862-gettoken-23.patch, failed testing.

xano’s picture

Priority: Normal » Major

A possible problem is that drupalGetToken() still calls drupal_hash_salt(), which defaults to the host site's database to create the salt. Maybe we solve this the same way as we set a custom session ID for the client site, but I'm not sure how that is done.

Moving to major, as this is important for testing some security issues.

xano’s picture

Issue summary: View changes

Ohai

martin107’s picture

Issue summary: View changes
Issue tags: +Needs reroll

Patch no longer applies.

Anonymous’s picture

Issue tags: -Needs reroll
StatusFileSize
new3.57 KB

Reroll, fixing merge conflicts in WebTestBase.php and SimpleTestTest.php.
This should also fix the failed test regarding the summary text. I'm not sure how to fix the one with the session cookie though.

martin107’s picture

Status: Needs work » Needs review

Triggering testbot.

Status: Needs review » Needs work

The last submitted patch, 27: simpletest-add-hash-salt-1555862-27.patch, failed testing.

Anonymous’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 27: simpletest-add-hash-salt-1555862-27.patch, failed testing.

Anonymous’s picture

The failure is probably caused by removing the session id reset in the curlExec() method. What is the reason that line got removed?

- $this->session_id = NULL;

andypost’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 27: simpletest-add-hash-salt-1555862-27.patch, failed testing.

andypost’s picture

Issue tags: +Needs reroll
stefank’s picture

Assigned: Unassigned » stefank
Issue tags: -Needs reroll
StatusFileSize
new2.98 KB

Re-roll of last patch.

stefank’s picture

Assigned: stefank » Unassigned
Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 36: simpletest-add-hash-salt-1555862-36.patch, failed testing.

pfrenssen’s picture

Drupal 7 is also affected by this. Patch contains D7 backport of the fix. I have not backported the test.

daffie’s picture

Version: 8.0.x-dev » 7.x-dev
Status: Needs work » Needs review
Issue tags: -Needs backport to D7
StatusFileSize
new595 bytes

This is never going to be fixed in Drupal 8, because in #2328995: Remove unused and defective WebTestBase::drupalGetToken() the whole function drupalGetToken() has been removed.
Re-uploaded the patch from comment #39 and removed the do-not-test naming part.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

The function drupal_get_token() builds the token is the same way. So for me it is RTBC.

andypost’s picture

+1 here, that's used in test for masquerade module

PS: Currently in D8 there's no way to build csrf token properly, within test, so added tag

xano’s picture

Seeing as this doesn't work in Drupal 8 and we need this to fix #144538: User logout is vulnerable to CSRF, shouldn't we fix this for D8 first and backport to D7?

dave reid’s picture

@Xano: Considering this helper was removed from D8, I would consider them two separate issues at this point. Not having this in D7 core is a major blocker for testing in contrib modules.

pfrenssen’s picture

Status: Reviewed & tested by the community » Needs work

We will need a test for D7 now.

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.