Problem/Motivation

PHP 8.2 provides attribute #[SensitiveParameter] to exclude sensitive data from backtraces

https://wiki.php.net/rfc/redact_parameters_in_back_traces

Proposed resolution

- explore where this attribute could be applied (password and private key arguments)
- discus policy on usage

Remaining tasks

- add the attribute to password argument and its hash (both interface and implementation)
- add it for non-string argument of PrivateKey

User interface changes

no

API changes

no

Data model changes

no

Release notes snippet

TBD

Issue fork drupal-3296293

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

andypost created an issue. See original summary.

mfb’s picture

Is there anything preventing #[\SensitiveParameter] from being added now, in 10.x, rather than waiting until 8.2 is required? It wouldn't do anything on 8.1, but could be a nice little security enhancement for those using 8.2

geek-merlin’s picture

> Is there anything preventing #[\SensitiveParameter] from being added now, in 10.x, rather than waiting until 8.2 is required? It wouldn't do anything on 8.1, but could be a nice little security enhancement for those using 8.2

The RFC states:

> 1. The \SensitiveParameter and \SensitiveParameterValue class name will no longer be available to userland code.

which, the other way round, says Yes, we can do it now. So let's do it.

mfb’s picture

Title: Apply SensitiveParameter when core require PHP 8.2 » Apply SensitiveParameter attribute

Retitling then. As far as "explore where this attribute could be applied," to start with this could be helpful for $password parameter; also the unhashed $sid which is functionally similar to password. That stuff is truly sensitive vs. other PII which I'd call less sensitive.

amjad1233 made their first commit to this issue’s fork.

amjad1233’s picture

I am not sure how I messed up, I was using DrupalPod to give it a try but I guess somehow It started a new PR. Well initial change is here https://git.drupalcode.org/issue/drupal-3296293/-/commit/615123b7ae06b98...

amjad1233’s picture

StatusFileSize
new10.54 KB

A traditional patch

_utsavsharma’s picture

StatusFileSize
new9.61 KB

FIxed CCF for #8.
Please review.

solideogloria’s picture

Status: Active » Needs review
smustgrave’s picture

Status: Needs review » Needs work

Patch needs some work for CI failures

smustgrave’s picture

Status: Needs work » Needs review
StatusFileSize
new8.73 KB
new8.09 KB

Removed #[\SensitiveParameter] from the function calls as they appeared to be causing errors in those locations.

Status: Needs review » Needs work

The last submitted patch, 12: 3296293-12.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Needs review

random ckeditor5 failure.

mfb’s picture

Presumably the PasswordInterface $password argument wouldn't be sensitive, that's just the password hashing service

andypost’s picture

StatusFileSize
new6.01 KB
new10.36 KB

Fix #15 and add more places

+++ b/core/modules/basic_auth/tests/src/Traits/BasicAuthTestTrait.php
@@ -22,7 +22,7 @@ trait BasicAuthTestTrait {
-  protected function basicAuthGet($path, $username, $password, array $options = []) {
+  protected function basicAuthGet($path, $username, #[\SensitiveParameter] $password, array $options = []) {

@@ -37,7 +37,7 @@ protected function basicAuthGet($path, $username, $password, array $options = []
-  protected function getBasicAuthHeaders($username, $password) {
+  protected function getBasicAuthHeaders($username, #[\SensitiveParameter] $password) {

+++ b/core/modules/jsonapi/tests/src/Functional/UserTest.php
@@ -318,7 +318,7 @@ public function testPatchDxForSecuritySensitiveBaseFields() {
-  protected function assertRpcLogin(string $username, string $password): void {
+  protected function assertRpcLogin(string $username, #[\SensitiveParameter] string $password): void {

I see no reason to add it to trait and other methods used only in tests

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Ah I gotcha. Changes look good.

andypost’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.9 KB
new8.46 KB

Sorry derailing RTBC but I missed to remove attribute from tests - I find it helpful for debugging

Probably we need change record to notify contrib maintainers

jordanpagewhite’s picture

Could we use #[SensitiveParameter] on the $connection_options of Drupal\mysql\Driver\Database\mysql\Connection::open() to mitigate 3061567?

If that would be an acceptable addition to this patch, I would be happy to add it. It would probably be later this evening though (Pacific time).

solideogloria’s picture

andypost’s picture

@jordanpagewhite Great point, would be great to check how it works for array arguments!

solideogloria’s picture

I think adding the attribute there would be a good addition.

jordanpagewhite’s picture

It seems that 3061567 will/is already resolved by SensitiveParameters in PHP 8.2. The actual backtrace logged is PDO::construct(), and it seems that this is already using SensitiveParameter properly. We can disregard my comment in #19. Thank you.

PDOException: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo for 8b9fb7fd9a14 failed: Name or service not known in /opt/drupal/web/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php on line 79 #0 /opt/drupal/web/core/modules/mysql/src/Driver/Database/mysql/Connection.php(165): PDO->__construct('mysql:host=8b9f...', 'root', Object(SensitiveParameterValue), Array)

Steps to test

Pre-step

  1. Create a local Drupal (drupal:latest) & MariaDB (mariadb:10.3) docker environment using the official images

Positive test case

  1. Apply my patch that adds the #[SensitiveParameter] attribute to the $connection_options parameters of Drupal\mysql\Driver\Database\mysql\Connection::__construct() and Drupal\mysql\Driver\Database\mysql\Connection::open()
  2. Stop the MariaDB container
  3. Verify that a PDOException is thrown BUT it should NOT include the plain-text connection_options

Negative test case

FAILED test: This did NOT include the plain-text connection_options, but instead Object(SensitiveParameterValue).

verify that issue 3061567 still throws the PDOException that includes the plain text connection options

  1. Stop the MariaDB container
  2. Verify that a PDOException still thrown and includes the plain-text connection_options
mfb’s picture

StatusFileSize
new1.04 KB
new9.62 KB

Adding to the unhashed $sid as I suggested in #4

longwave’s picture

  1. +++ b/core/lib/Drupal/Core/Password/PasswordInterface.php
    @@ -34,7 +34,7 @@ public function hash($password);
    +  public function check(#[\SensitiveParameter] $password, #[\SensitiveParameter] $hash);
    

    Is the $hash parameter sensitive?

  2. +++ b/core/lib/Drupal/Core/Session/PermissionsHashGenerator.php
    @@ -43,7 +43,7 @@ class PermissionsHashGenerator implements PermissionsHashGeneratorInterface {
    +  public function __construct(#[\SensitiveParameter] PrivateKey $private_key, CacheBackendInterface $cache, CacheBackendInterface $static) {
    

    This is the PrivateKey service, not an actual private key.

mfb’s picture

I would say it's only necessary to match what php and symfony are doing with their password hashing functions, which is that just the password itself is tagged as SensitiveParameter, not the hash. Of course a hashed password, like lots of data, is still sensitive and there are procedures if there's a breach, just saying it doesn't need to be a "SensitiveParameter".

andypost’s picture

Issue tags: +Needs change record

We should promote it for other module developers

Re #25 both are sensitive, private key has sensitive data ans the RFC mentioned that case, hash of password probably unreversable ATM but very probably not in future, that's why there's #3110670: Increase password hashing iterations

andypost’s picture

mfb’s picture

@andypost The actual string private key is certainly a SensitiveParameter (as would be the hash salt setting if that is a parameter anywhere), but I don't see a need for the PrivateKey service to be a SensitiveParameter; can you explain? That's just a service which doesn't contain any data.

andypost’s picture

StatusFileSize
new883 bytes
new8.75 KB

I was wrong about PrivateKey, checked with fresh head and here's patch

mfb’s picture

Symfony will now apply SensitiveParameter to $sessionId as of https://github.com/symfony/symfony/pull/49016 so now we just need to get this issue committed :) I'm still ambivalent about adding it to hashes since php and symfony do not, but leaked password hashes are both unfortunate and embarrassing so, works for me.

solideogloria’s picture

Thanks for your work on this. Attributes is a cool feature to see finally in PHP (as well as this attribute specifically). I'm excited every time I read the release notes for a new PHP version.

smustgrave’s picture

Status: Needs review » Needs work

Only moving back to NW for the change record

The change it self looks good!

jordanpagewhite’s picture

Status: Needs work » Needs review

I made a first draft/attempt at a change record. https://www.drupal.org/node/3339665

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record +Needs Review Queue Initiative

Not sure what more the change record should include

  • longwave committed 90c51b90 on 10.1.x
    Issue #3296293 by andypost, amjad1233, mfb, smustgrave, _utsavsharma,...
longwave’s picture

Committed and pushed 90c51b9047 to 10.1.x. Thanks!

Also tweaked the change record a little and published it.

longwave’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.