Skip to content

Create object fails when CLP user pointer create set to true public create set to false #6359

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

Closed
TravisHeaver opened this issue Jan 22, 2020 · 4 comments

Comments

@TravisHeaver
Copy link

Issue Description

Create new object fails when CLP public read/write set to false but pointer to _User (column named user) read/write set to true.

I am able to create objects when public create is set to true, however this leads to a vulnerability that a user can create an object for any user, there is no validation who is creating

Steps to reproduce

schema for the class
{
"_id": {
"$oid": "5e2895a31c9d440000ff973d"
},
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"client": {
"required": false
},
"sku": {
"required": false
},
"note": {
"required": false
},
"currency": {
"required": false
},
"value": {
"required": false
},
"user": {
"required": true
},
"photo": {
"required": false
}
},
"indexes": {
"id": {
"_id": {
"$numberInt": "1"
}
}
},
"class_permissions": {
"get": {},
"find": {},
"count": {},
"create": {},
"update": {},
"delete": {},
"addField": {},
"readUserFields": ["user"],
"writeUserFields": ["user"]
}
},
"client": "Client",
"sku": "string",
"note": "string",
"currency": "string",
"value": "number",
"user": "
_User",
"photo": "file"
}

Screen Shot 2020-01-22 at 1 38 07 PM

Expected Results

When passing a valid session and the pointer to user matches that session users I expect the creation of a new object

Actual Outcome

{code: 119, error: "Permission denied for action create on class Sale."}

Environment Setup

  • Server

    • parse-server version 3.10.0
    • Operating System: MacOS 10.15.2
    • Hardware: MacBook Pro
    • Localhost or remote server? localhost
  • Database

    • MongoDB version: 4.2.2
    • Storage engine: WiredTiger
    • Hardware: M0
    • Localhost or remote server? MongoDB Atlas

Logs/Trace

error: Parse error: Permission denied for action create on class Sale. {"code":119,"stack":"Error: Permission denied for action create on class Sale.
at Function.validatePermission parse-server/lib/Controllers/SchemaController.js:1291:13)\n at SchemaController.validatePermission
parse-server/lib/Controllers/SchemaController.js:1304:29)
at validateClassName.then.then.schemaController

Which brings us here:
// No matching CLP, let's check the Pointer permissions
// And handle those later
const permissionField =
['get', 'find', 'count'].indexOf(operation) > -1
? 'readUserFields'
: 'writeUserFields';

// Reject create when write lockdown
if (permissionField == 'writeUserFields' && operation == 'create') {
  throw new Parse.Error(
    Parse.Error.OPERATION_FORBIDDEN,
    `Permission denied for action ${operation} on class ${className}.`
  );
}

as the note suggests 'handle those later' doesn't seem to get handled

@davimacedo
Copy link
Member

I think it works like this by design as we can see in this test case but I'm not sure why. @dplewis @acinader any idea?

@TravisHeaver in the meantime I suggest you to enable requiresAuthentication for create and write a beforeSave trigger to either attach the current user to the user field or verify if the current user equals to the user field.

@BufferUnderflower
Copy link
Contributor

This is by design, create can not be allowed by column. It just makes no sense, because there is literally no object to inspect it's column for users who are allowed. I mean the object has to exist on server already and have some users stored in its field.

If we allow create by field (pointer permission) examining just the incoming object- I believe this adds zero security, but more importantly it would then allow anyone to create an object, just by putting himself into a field.

If you want to enforce a rule that some field should contain only the person who creates it - this has nothing to do with permissions, and @davimacedo suggestion perfectly covers such a case.

To sum up - if you disable create for * public - you have to allow create using other type of CLP - either some role, or user by id, or all authenticated users (requiresAuhentication) in order to allow creating objects of this class. Pointer permissions can't be used to create for security reasons, there is a line of code checking this exact case in server sources. All other types of CLP are good to go.

@BufferUnderflower
Copy link
Contributor

// Reject create when write lockdown
if (permissionField == 'writeUserFields' && operation == 'create') {
throw new Parse.Error(
Parse.Error.OPERATION_FORBIDDEN,
Permission denied for action ${operation} on class ${className}.
);
}


as the note suggests 'handle those later' doesn't seem to get handled

'handle those later' iirc is about other permissions that pass this validation function (sanity check) and handled later by adding query constraints:

{where : 
  {"$and" : [ 
    // original query 
    { objectId: '0bj3ct1d'  },   
    // added with Pointer permissions
    { $or: [  
      // to cover columns of type Pointer<_User>
       {
          'columnName':  { __type: 'Pointer', className: '_User', objectId: 'us3r1d' },
          objectId: '0bj3ct1d'
       }, 
       // to cover columns of type Array
       { 
          'columnName': 
                {  
                  $all: [ 
                      { __type: 'Pointer', className: '_User', objectId: 'us3r1d' }
                   ]
                },
          objectId: '0bj3ct1d'
        }
     ]
  ]
}

@TravisHeaver
Copy link
Author

ok, thank you for the feedback, I will implement as suggested!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants