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

Ruby: Add query for insecure mass assignment #15987

Merged
merged 15 commits into from
Apr 12, 2024

Conversation

joefarebrother
Copy link
Contributor

@joefarebrother joefarebrother commented Mar 20, 2024

This query looks for instances of request parameters having permit! called on them, which allows arbitrary parameters to be specified by the request, and then being used for a mass assignment operation.

@github-actions github-actions bot added the Ruby label Mar 20, 2024
@joefarebrother joefarebrother force-pushed the ruby-mass-reassignment branch 2 times, most recently from aa936e2 to a9f49ce Compare March 20, 2024 15:28
Copy link
Contributor

QHelp previews:

ruby/ql/src/queries/security/cwe-915/MassAssignment.qhelp

Insecure Mass Assignment

Operations that allow for mass assignment (setting multiple attributes of an object using a hash), such as ActiveRecord::Base.new, should take care not to allow arbitrary parameters to be set by the user. Otherwise, unintended attributes may be set, such as an isAdmin feild for a User object.

Recommendation

When using a mass assignment operation from user supplied parameters, use ActionController::Parameters#permit to restrict the possible parameters a user can supply, rather than ActionController::Parameters#permit!, which permits arbitrary parameters to be used for mass assignment.

Example

In the following example, permit! is used which allows arbitrary parameters to be supplied by the user.

class UserController < ActionController::Base
    def create
        # BAD: arbitrary params are permitted to be used for this assignment
        User.new(user_params).save!
    end

    def user_params
        params.require(:user).permit!
    end
end

In the following example, only specific parameters are permitted, so the mass assignment is safe.

class UserController < ActionController::Base
    def create
        # GOOD: the permitted parameters are explicitly specified
        User.new(user_params).save!
    end

    def user_params
        params.require(:user).permit(:name, :email)
    end
end

References

  • Common Weakness Enumeration: CWE-915.

@joefarebrother joefarebrother force-pushed the ruby-mass-reassignment branch from 3d7c7ae to 01f7124 Compare March 22, 2024 14:07
@joefarebrother joefarebrother marked this pull request as ready for review March 22, 2024 14:07
@joefarebrother joefarebrother requested a review from a team as a code owner March 22, 2024 14:07
@joefarebrother joefarebrother changed the title [Draft] Ruby: Add query for insecure mass assignment Ruby: Add query for insecure mass assignment Mar 22, 2024
Copy link
Contributor

@hmac hmac left a comment

Choose a reason for hiding this comment

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

This looks great. I have only some minor comments. DCA shows a significant slowdown for one big Rails repo. I think it's worth running against the rails-projects source suite to see if there's a pattern there that we need to look into.

I also noticed in the Rails guide that you can do

params.permit(preferences: {})

which allows arbitrary data inside preferences. We should probably extend the query to cover that case, but that can be a follow-up and doesn't need to block this PR.

Copy link
Contributor

QHelp previews:

ruby/ql/src/queries/security/cwe-915/MassAssignment.qhelp

errors/warnings:

/home/runner/work/codeql/codeql/ruby/ql/src/queries/security/cwe-915/MassAssignment.qhelp:32:29: Open quote is expected for attribute "href" associated with an  element type  "a".
A fatal error occurred: 1 qhelp files could not be processed.

@joefarebrother joefarebrother force-pushed the ruby-mass-reassignment branch from 31adf40 to 9fa0bad Compare March 25, 2024 15:28
Copy link
Contributor

github-actions bot commented Mar 25, 2024

QHelp previews:

ruby/ql/src/queries/security/cwe-915/MassAssignment.qhelp

Insecure Mass Assignment

Operations that allow for mass assignment (setting multiple attributes of an object using a hash), such as ActiveRecord::Base.new, should take care not to allow arbitrary parameters to be set by the user. Otherwise, unintended attributes may be set, such as an is_admin field for a User object.

Recommendation

When using a mass assignment operation from user supplied parameters, use ActionController::Parameters#permit to restrict the possible parameters a user can supply, rather than ActionController::Parameters#permit!, which permits arbitrary parameters to be used for mass assignment.

Example

In the following example, permit! is used which allows arbitrary parameters to be supplied by the user.

class UserController < ActionController::Base
    def create
        # BAD: arbitrary params are permitted to be used for this assignment
        User.new(user_params).save!
    end

    def user_params
        params.require(:user).permit!
    end
end

In the following example, only specific parameters are permitted, so the mass assignment is safe.

class UserController < ActionController::Base
    def create
        # GOOD: the permitted parameters are explicitly specified
        User.new(user_params).save!
    end

    def user_params
        params.require(:user).permit(:name, :email)
    end
end

References

@joefarebrother joefarebrother force-pushed the ruby-mass-reassignment branch from 9fa0bad to fb19288 Compare March 25, 2024 15:46
hmac
hmac previously approved these changes Mar 26, 2024
Copy link
Contributor

@hmac hmac left a comment

Choose a reason for hiding this comment

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

👌

Copy link
Contributor

@asgerf asgerf left a comment

Choose a reason for hiding this comment

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

I came looking out of curiosity, looks great, but I'll defer to @hmac's review. Just a few drive-by comments

ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll Outdated Show resolved Hide resolved
ruby/ql/lib/codeql/ruby/security/MassAssignmentQuery.qll Outdated Show resolved Hide resolved
@@ -52,4 +53,45 @@ module MassAssignment {
result.(DataFlow::PostUpdateNode).getPreUpdateNode() = this.getParamsArgument()
}
}

/** Holds if `h` is an empty hash or contains an empty hash at one if its (possibly nested) values. */
private predicate hasEmptyHash(Expr e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's better to use CFG nodes instead of AST nodes here. I.e., use HashLiteralCfgNode instead of HashLiteral, etc.

@joefarebrother joefarebrother merged commit 5cebcad into github:main Apr 12, 2024
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants