Original report from @Berdir, copied from the private security tracker and made public as this issue requires "administer node" permissions:

This module has a access bypass (?) vulnerability.

I noticed that \Drupal\node\Plugin\views\filter\Access checks the administer nodes permission to bypass node access, but since 7.x, there is actually a dedicated permission for that (bypass node access).

That could be a possible security issue if you have users with administer nodes that are however not allowed to see all content and you use that filter in combination with having the default node access/alter disabled (I guess that filter only makes sense in that scenario).

Discussed with @dawehner a bit, and Views 7.x has basically the same code.

That said, we're not even sure this class works at all in 8.x (it probably does in 7.x), there were no tests that we could see.

Opening this so I don't forget about this. We need to check if the plugin actually works.

Note that administer nodes is a restrict access permission, so you could argue that this is not a security issue, but there is a reason bypass node access was separated into another permission.

Comments

stefan.r created an issue. See original summary.

greggles’s picture

Issue summary: View changes

This was reported and discussed in private and deemed to be OK to be worked on in public given it requires the "attacker" to have administer nodes.

lendude’s picture

Status: Active » Needs review
StatusFileSize
new11.43 KB

I was looking at writing a test for this, but even when the node table is not the base table, node access is checked anyway. Adding this filter to the test view didn't change anything.

So is there a scenario where this filter might actually be useful?

dawehner’s picture

So is there a scenario where this filter might actually be useful?

Its useful for checking edit access.

berdir’s picture

+++ b/core/modules/node/src/Tests/Views/FilterNodeAccess.php
@@ -0,0 +1,112 @@
+ * Tests the node_access filter handler.
+ *
+ * @group node
+ * @see \Drupal\node\Plugin\views\filter\Status
+ */
+class FilterNodeAccess extends NodeTestBase {

not sure but I think we still actually require tests to be suffixed with *Test, no?

berdir’s picture

Status: Needs review » Needs work
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_access.yml
@@ -0,0 +1,250 @@
+          disable_sql_rewrite: false

I think you need to disable this for this to make sense.

berdir’s picture

@dawehner: the filter is hardcoded to view, so you can't really use it for edit checking?

I'd say a use case would to combine it with OR conditions. And for some reason, you only want to respect node access for one of the cases.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new11.45 KB
new1.32 KB

Addressing #5 and #6

Status: Needs review » Needs work

The last submitted patch, 8: incorrect_permission-2799209-8.patch, failed testing.

lendude’s picture

Status: Needs work » Needs review
StatusFileSize
new2.89 KB
new12.49 KB
new13.12 KB

I think you need to disable this for this to make sense.

Ah yeah ok that makes sense, you want to disable all rewriting but still want to use the grant table.

Ok so now with the access filter added to the view and the correct permission set in the fix.

The last submitted patch, 10: incorrect_permission-2799209-10-TEST_ONLY.patch, failed testing.

The last submitted patch, 10: incorrect_permission-2799209-10-TEST_ONLY.patch, failed testing.

dawehner’s picture

  1. +++ b/core/modules/node/src/Tests/Views/FilterNodeAccessTest.php
    @@ -0,0 +1,112 @@
    +    foreach ($this->users as $web_user) {
    +      $this->drupalLogin($web_user);
    +      foreach (array(0 => 'Public', 1 => 'Private') as $is_private => $type) {
    +        $edit = array(
    +          'title[0][value]' => t('@private_public Article created by @user', array('@private_public' => $type, '@user' => $web_user->getUsername())),
    +        );
    +        if ($is_private) {
    +          $edit['private[0][value]'] = TRUE;
    +          $edit['body[0][value]'] = 'private node';
    +        }
    +        else {
    +          $edit['body[0][value]'] = 'public node';
    +        }
    +
    +        $this->drupalPostForm('node/add/article', $edit, t('Save'));
    +        $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
    +        $this->assertEqual($is_private, (int)$node->private->value, 'The private status of the node was properly set in the node_access_test table.');
    +      }
    

    Is there a reason we shouldn't use the API to create those nodes?

  2. +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_access.yml
    @@ -0,0 +1,288 @@
    +base_table: users_field_data
    +base_field: uid
    

    Wait, this is confusing, why are we creating a view of users?

lendude’s picture

13.1 lazy copy/pasting existing tests, so no GOOD reason :) Changed
13.2 Well the help text for the handler says "Not necessary if you are using node as your base table.", so I started with a different base table when I wanted to test this. But the help text is obviously wrong, so now I changed it to a straight up node view. Should we change the help text here too or do a follow up?

dawehner’s picture

Some nitpicks :)

  1. +++ b/core/modules/node/src/Tests/Views/FilterNodeAccessTest.php
    @@ -0,0 +1,111 @@
    +          'body'      => [[
    +            'value' => $type . ' node',
    +            'format' => filter_default_format(),
    +          ]],
    +          'title'     => t('@private_public Article created by @user', ['@private_public' => $type, '@user' => $web_user->getUsername()]),
    +          'type'      => 'article',
    +          'uid'       => $web_user->id(),
    +          'private'   => (bool) $is_private,
    

    Let's get rid of all that whitespace.

  2. +++ b/core/modules/node/src/Tests/Views/FilterNodeAccessTest.php
    @@ -0,0 +1,111 @@
    +        $this->assertEqual($is_private, (int)$node->private->value, 'The private status of the node was properly set in the node_access_test table.');
    

    Nitpick: one more space between (int) and $node

  3. +++ b/core/modules/node/src/Tests/Views/FilterNodeAccessTest.php
    @@ -0,0 +1,111 @@
    +    $admin_user = $this->drupalCreateUser(['access content', 'bypass node access']);
    +    $this->drupalLogin($admin_user);
    

    It is weird to reuse an existing variable name

lendude’s picture

Thanks for the review as always.

Fixed all the feedback.

Status: Needs review » Needs work

The last submitted patch, 16: incorrect_permission-2799209-16.patch, failed testing.

lendude’s picture

Status: Needs work » Needs review
StatusFileSize
new2.92 KB
new10.6 KB

Ok time for bed obviously.....now a patch with some actual content...

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Those were just nitpicks, so I think this is good to go?

dawehner’s picture

+1 for the RTBC

catch’s picture

Uploading a test only patch to see the test fail.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 21: incorrect_permission-2799209-21.patch, failed testing.

catch’s picture

Status: Needs work » Needs review
StatusFileSize
new10.6 KB

Berdir correctly pointed out the other patch wasn't a patch.

The last submitted patch, 21: incorrect_permission-2799209-21-test-only.patch, failed testing.

berdir’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC then...

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.3.x and cherry-picked to 8.2.x. Thanks!

  • catch committed 20cab6d on 8.3.x
    Issue #2799209 by Lendude, Manuel Garcia, Berdir, dawehner: Incorrect...

  • catch committed f1d2f7a on 8.2.x
    Issue #2799209 by Lendude, Manuel Garcia, Berdir, dawehner: Incorrect...

Status: Fixed » Closed (fixed)

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