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

Default payload validation #48753

Merged
merged 23 commits into from
Nov 15, 2019

Conversation

legrego
Copy link
Member

@legrego legrego commented Oct 21, 2019

This adds a default payload validation for all Legacy Platform routes which do not define their own validate: payload schema.

Since New Platform routes handle and enforce their own validation, they are opted-out of this default behavior.

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@legrego
Copy link
Member Author

legrego commented Oct 21, 2019

retest

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@legrego legrego changed the title trial for default payload validation Default payload validation Oct 23, 2019
@legrego legrego added release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc Team:Security Team focused on: Auth, Users, Roles, Spaces, Audit Logging, and more! v7.6.0 v8.0.0 labels Oct 23, 2019
// TODO: This 'validate' section can be removed once the legacy platform is completely removed.
// We are telling Hapi that NP routes can accept any payload, so that it can bypass the default
// validation applied in ./http_tools#getServerOptions
// (All NP routes are already required to specify their own validation in order to access the payload)
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh thanks for the heads-up! Are we sure we want to allow this behavior? Do we have concrete use cases for disabling the config-schema validation at this time?

Copy link
Contributor

@mshustov mshustov Oct 25, 2019

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

There are some cases when we don't know the shape of an object upfront.

That's a fair point -- we do know that payloads will at least be objects or arrays though, right? Could we at least enforce something like schema.object({}, { allowUnknowns: true }) at route handlers?

We are proposing a followup PR to this one which will incorporate these default validations into the schema.object call itself, so that all NP routes will have these protections in place, unless they explicitly opt-out of them via schema.unsafeObject({}) or similar.

Copy link
Contributor

@mshustov mshustov Oct 25, 2019

Choose a reason for hiding this comment

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

Could we at least enforce something like schema.object({}, { allowUnknowns: true }) at route handlers?

We already enforce. Don't we? Plugins cannot get access to a body without declaring validation
https://github.com/elastic/kibana/blob/master/src/core/server/http/router/request.ts#L106-L109
Although they can lax the validation

schema.any()
schema.object({}, { allowUnknowns: true })

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah sorry I misunderstood. I thought NP provided a way to prevent any validation (not even schema.any(), and still get access to the underlying payload. I think we're OK as-is then. Our followup PR should protect these routes as well.

// This is a default payload validation which applies to all LP routes which do not specify their own
// `validate.payload` handler, in order to reduce the likelyhood of prototype pollution vulnerabilities.
// (All NP routes are already required to specify their own validation in order to access the payload)
payload: value => Promise.resolve(validateObject(value)),
Copy link
Contributor

Choose a reason for hiding this comment

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

what about query validation?

Copy link
Member Author

Choose a reason for hiding this comment

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

We are mostly concerned with payload validation, as that's the most common offender for nested data structures. We may add similar validations for query, path, and header in the future

@legrego
Copy link
Member Author

legrego commented Oct 28, 2019

@elasticmachine merge upstream

@elasticmachine
Copy link
Contributor

💔 Build Failed

@legrego
Copy link
Member Author

legrego commented Oct 28, 2019

@elasticmachine merge upstream

@elasticmachine
Copy link
Contributor

💔 Build Failed

@legrego
Copy link
Member Author

legrego commented Oct 29, 2019

@elasticmachine merge upstream

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@kobelb
Copy link
Contributor

kobelb commented Oct 29, 2019

ACK: reviewing

{ constructor: { foo: { prototype: null } } },
{ prototype: { foo: { constructor: null } } },
].forEach(value => {
['headers', 'payload', 'query', 'params'].forEach(property => {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Ensuring headers, payload, query and params are being checked isn't really relevant anymore. This is a remnant from when we were validating the entire request itself, as opposed to explicitly just doing payload validation.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@legrego
Copy link
Member Author

legrego commented Nov 15, 2019

@elasticmachine merge upstream

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@legrego legrego merged commit 1c415e0 into elastic:master Nov 15, 2019
@legrego legrego deleted the security/route-validation-audit branch November 15, 2019 15:53
legrego added a commit to legrego/kibana that referenced this pull request Nov 15, 2019
* trial for default payload validation

* relaxing default validation

* some cleanup and testing

* update xsrf integration test

* adding API smoke tests

* fixing types

* removing Joi extensions

* updating tests

* documenting changes

* fixing NP validation bypass

* fix lint problems

* Update src/legacy/server/http/integration_tests/xsrf.test.js

* Update src/legacy/server/http/integration_tests/xsrf.test.js

* revert test changes

* simplifying tests


Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
legrego added a commit that referenced this pull request Nov 15, 2019
* trial for default payload validation

* relaxing default validation

* some cleanup and testing

* update xsrf integration test

* adding API smoke tests

* fixing types

* removing Joi extensions

* updating tests

* documenting changes

* fixing NP validation bypass

* fix lint problems

* Update src/legacy/server/http/integration_tests/xsrf.test.js

* Update src/legacy/server/http/integration_tests/xsrf.test.js

* revert test changes

* simplifying tests


Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
const [key, childValue] = entries[i];
if (isObject(childValue)) {
if (seen.has(childValue)) {
throw new Error('circular reference detected');
Copy link
Contributor

Choose a reason for hiding this comment

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

@legrego why did you add a throw here instead of simply a continue statement? Is it because the presence of a circular reference is an indication of a programming error during development?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc Team:Security Team focused on: Auth, Users, Roles, Spaces, Audit Logging, and more! v7.6.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants