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

Update security best practices document #100814

Merged
merged 11 commits into from
Jun 16, 2021
29 changes: 1 addition & 28 deletions dev_docs/best_practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -245,31 +245,4 @@ It may be tempting to get caught up in the dream of writing the next package whi

Review the following items related to vulnerability and security risks.

- XSS
- Check for usages of `dangerouslySetInnerHtml`, `Element.innerHTML`, `Element.outerHTML`
- Ensure all user input is properly escaped.
- Ensure any input in `$.html`, `$.append`, `$.appendTo`, $.prepend`, `$.prependTo`is escaped. Instead use`$.text`, or don't use jQuery at all.
- CSRF
- Ensure all APIs are running inside the Kibana HTTP service.
- RCE
- Ensure no usages of `eval`
- Ensure no usages of dynamic requires
- Check for template injection
- Check for usages of templating libraries, including `_.template`, and ensure that user provided input isn't influencing the template and is only used as data for rendering the template.
- Check for possible prototype pollution.
- Prototype Pollution - more info [here](https://docs.google.com/document/d/19V-d9sb6IF-fbzF4iyiPpAropQNydCnoJApzSX5FdcI/edit?usp=sharing)
- Check for instances of `anObject[a][b] = c` where a, b, and c are user defined. This includes code paths where the following logical code steps could be performed in separate files by completely different operations, or recursively using dynamic operations.
- Validate any user input, including API url-parameters/query-parameters/payloads, preferable against a schema which only allows specific keys/values. At a very minimum, black-list `__proto__` and `prototype.constructor` for use within keys
- When calling APIs which spawn new processes or potentially perform code generation from strings, defensively protect against Prototype Pollution by checking `Object.hasOwnProperty` if the arguments to the APIs originate from an Object. An example is the Code app's [spawnProcess](https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44).
- Common Node.js offenders: `child_process.spawn`, `child_process.exec`, `eval`, `Function('some string')`, `vm.runIn*Context(x)`
- Common Client-side offenders: `eval`, `Function('some string')`, `setTimeout('some string', num)`, `setInterval('some string', num)`
- Check for accidental reveal of sensitive information
- The biggest culprit is errors which contain stack traces or other sensitive information which end up in the HTTP Response
- Checked for Mishandled API requests
- Ensure no sensitive cookies are forwarded to external resources.
- Ensure that all user controllable variables that are used in constructing a URL are escaped properly. This is relevant when using `transport.request` with the Elasticsearch client as no automatic escaping is performed.
- Reverse tabnabbing - https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing
- When there are user controllable links or hard-coded links to third-party domains that specify target="\_blank" or target="\_window", the `a` tag should have the rel="noreferrer noopener" attribute specified.
- Allowing users to input markdown is a common culprit, a custom link renderer should be used
- SSRF - https://www.owasp.org/index.php/Server_Side_Request_Forgery
- All network requests made from the Kibana server should use an explicit configuration or white-list specified in the `kibana.yml`
TODO: copy content from security.asciidoc when review is complete
178 changes: 126 additions & 52 deletions docs/developer/best-practices/security.asciidoc
Original file line number Diff line number Diff line change
@@ -1,55 +1,129 @@
[[security-best-practices]]
== Security best practices

* XSS
** Check for usages of `dangerouslySetInnerHtml`, `Element.innerHTML`,
`Element.outerHTML`
** Ensure all user input is properly escaped.
** Ensure any input in `$.html`, `$.append`, `$.appendTo`,
latexmath:[$.prepend`, `$].prependTo`is escaped. Instead use`$.text`, or
don’t use jQuery at all.
* CSRF
** Ensure all APIs are running inside the {kib} HTTP service.
* RCE
** Ensure no usages of `eval`
** Ensure no usages of dynamic requires
** Check for template injection
** Check for usages of templating libraries, including `_.template`, and
ensure that user provided input isn’t influencing the template and is
only used as data for rendering the template.
** Check for possible prototype pollution.
* Prototype Pollution
** Check for instances of `anObject[a][b] = c` where a, b, and c are
user defined. This includes code paths where the following logical code
steps could be performed in separate files by completely different
operations, or recursively using dynamic operations.
** Validate any user input, including API
url-parameters/query-parameters/payloads, preferable against a schema
which only allows specific keys/values. At a very minimum, black-list
`__proto__` and `prototype.constructor` for use within keys
** When calling APIs which spawn new processes or potentially perform
code generation from strings, defensively protect against Prototype
Pollution by checking `Object.hasOwnProperty` if the arguments to the
APIs originate from an Object. An example is the Code app’s
https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44[spawnProcess].
*** Common Node.js offenders: `child_process.spawn`,
`child_process.exec`, `eval`, `Function('some string')`,
`vm.runIn*Context(x)`
*** Common Client-side offenders: `eval`, `Function('some string')`,
`setTimeout('some string', num)`, `setInterval('some string', num)`
* Check for accidental reveal of sensitive information
** The biggest culprit is errors which contain stack traces or other
sensitive information which end up in the HTTP Response
* Checked for Mishandled API requests
** Ensure no sensitive cookies are forwarded to external resources.
jportner marked this conversation as resolved.
Show resolved Hide resolved
** Ensure that all user controllable variables that are used in
constructing a URL are escaped properly. This is relevant when using
`transport.request` with the {es} client as no automatic
escaping is performed.
* Reverse tabnabbing -
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing
** When there are user controllable links or hard-coded links to
third-party domains that specify target="_blank" or target="_window", the a tag should have the rel="noreferrer noopener" attribute specified.
Allowing users to input markdown is a common culprit, a custom link renderer should be used
* SSRF - https://www.owasp.org/index.php/Server_Side_Request_Forgery
All network requests made from the {kib} server should use an explicit configuration or white-list specified in the kibana.yml
When writing code for {kib}, be sure to follow these best practices to avoid common vulnerabilities. Refer to the included Open Web
Application Security Project (OWASP) references to learn more about these types of attacks.
Comment on lines +4 to +5
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about including a section on threats here at the top (such as this), but it felt like that might be a bit too much info for our audience, who are mostly not security experts.


=== Cross-site Scripting (XSS) ===

https://owasp.org/www-community/attacks/xss[_OWASP reference for XSS_]

XSS is a class of attacks where malicious scripts are injected into vulnerable websites. {kib} defends against this primarily by widespread
use of the React framework to safely encode data that is rendered to pages, widespread use of the EUI framework to
jportner marked this conversation as resolved.
Show resolved Hide resolved
jportner marked this conversation as resolved.
Show resolved Hide resolved
https://elastic.github.io/eui/#/navigation/link#link-validation[automatically sanitize links], and a restrictive Content-Security-Policy
jportner marked this conversation as resolved.
Show resolved Hide resolved
header.

*Best practices:*
jportner marked this conversation as resolved.
Show resolved Hide resolved

* Check for usage of dangerous functions or assignments that can result in unescaped user input in the browser DOM. Avoid
jportner marked this conversation as resolved.
Show resolved Hide resolved
using these at all costs:
jportner marked this conversation as resolved.
Show resolved Hide resolved
** *React:* https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml[`dangerouslySetInnerHtml`].
** *Browser DOM:* `Element.innerHTML` and `Element.outerHTML`.
* If using any of the aforementioned unsafe functions/assignments is absolutely necessary, follow
jportner marked this conversation as resolved.
Show resolved Hide resolved
https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#xss-prevention-rules[these XSS prevention
rules] to ensure that user input is not inserted into unsafe locations and to make sure that it is escaped properly.
jportner marked this conversation as resolved.
Show resolved Hide resolved
* Use EUI components to build your UI whenever possible, particularly when rendering `href` links. Otherwise, sanitize user input before
jportner marked this conversation as resolved.
Show resolved Hide resolved
rendering links to ensure that they do not use the `javascript:` protocol.

=== Cross-site Request Forgery (CSRF/XSRF) ===
jportner marked this conversation as resolved.
Show resolved Hide resolved

https://owasp.org/www-community/attacks/csrf[_OWASP reference for CSRF_]

CSRF is a class of attacks where a user is forced to execute an action on a vulnerable website that they're logged into, usually without
their knowledge. {kib} defends against this by requiring
https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#use-of-custom-request-headers[custom
request headers] for API endpoints. For more information, see <<api-request-headers, API Request Headers>>.

*Best practices:*

* Ensure all HTTP routes are registered via the <<http-service, {kib} HTTP service>> to take advantage of the aforementioned custom request
jportner marked this conversation as resolved.
Show resolved Hide resolved
jportner marked this conversation as resolved.
Show resolved Hide resolved
header security control.

=== Remote Code Execution (RCE) ===

https://owasp.org/www-community/attacks/Command_Injection[_OWASP reference for Command Injection_],
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see the text "RCE" is the linked pages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah this one is a bit confusing. Colloquially we lump "Command injection" and "Code injection" together, referring to these types of attacks as "RCE". But OWASP doesn't have an RCE page.

I tried to imply this equivalency below where I stated:

RCE is a class of attacks where an attacker executes malicious code or commands on a vulnerable server.

Do you think there's a better / more clear way I could word this?

https://owasp.org/www-community/attacks/Code_Injection[_OWASP reference for Code Injection_]

RCE is a class of attacks where an attacker executes malicious code or commands on a vulnerable server. {kib} defends against this by using
ESLint rules to restrict vulnerable functions, and by hooking into / hardening usage of these in third-party dependencies.
jportner marked this conversation as resolved.
Show resolved Hide resolved

*Best practices:*
jportner marked this conversation as resolved.
Show resolved Hide resolved

* Ensure no usages of `eval` and `_.template` -- these are restricted by ESLint rules.
jportner marked this conversation as resolved.
Show resolved Hide resolved
jportner marked this conversation as resolved.
Show resolved Hide resolved
* Ensure no usages of dynamic `require`.
jportner marked this conversation as resolved.
Show resolved Hide resolved
* Check for usages of templating libraries; ensure that user provided input isn't influencing the template and is only used as data for
jportner marked this conversation as resolved.
Show resolved Hide resolved
rendering the template.
* Take extra caution when spawning child processes with any user input or parameters that are otherwise user-controlled.
jportner marked this conversation as resolved.
Show resolved Hide resolved

=== Prototype Pollution ===

Prototype Pollution is an attack that is unique to JavaScript environments. Attackers can abuse JavaScript's prototype inheritance to
"pollute" objects in the whole application, which is often used as a vector for XSS or RCE vulnerabilities. {kib} defends against this by
jportner marked this conversation as resolved.
Show resolved Hide resolved
hardening particularly sensitive functions (such as those exposed by `child_process`), and by requiring validation on all HTTP routes by
jportner marked this conversation as resolved.
Show resolved Hide resolved
default.

*Best practices:*

* Check for instances of `anObject[a][b] = c` where a, b, and c are controlled by user input. This includes code paths where the following
jportner marked this conversation as resolved.
Show resolved Hide resolved
logical code steps could be performed in separate files by completely different operations, or recursively using dynamic operations.
* Validate any user input, including API url parameters, query parameters, and payloads. Preferably, use a schema which only allows specific
jportner marked this conversation as resolved.
Show resolved Hide resolved
keys/values. At a very minimum, implement a deny-list that prevents `__proto__` and `prototype.constructor` from being used within object
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
keys/values. At a very minimum, implement a deny-list that prevents `__proto__` and `prototype.constructor` from being used within object
keys and values. At a minimum, implement a deny-list that prevents the `__proto__` and `prototype.constructor` from being used within object

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: I'm applying this change but I am intentionally leaving out the extra "the". It will read:

At a minimum, implement a deny-list that prevents __proto__ and prototype.constructor from being used within object keys/values.

keys.
* When calling APIs which spawn new processes or potentially perform code generation from strings, defensively protect against Prototype
jportner marked this conversation as resolved.
Show resolved Hide resolved
Pollution by checking `Object.hasOwnProperty` if the arguments to the APIs originate from an Object. An example is the defunct Code app's
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Pollution by checking `Object.hasOwnProperty` if the arguments to the APIs originate from an Object. An example is the defunct Code app's
Pollution by checking if `Object.hasOwnProperty` has arguments to the APIs that originate from an Object. An example is the defunct Code app's

The sentence needs some tweaks, but not sure about the edit.

Is the last sentence about the Code app necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the tweaks are good.

As to the last sentence: I like that we have an example for this, and I think it's very useful because this is a complex topic that doesn't have much industry standard literature (such as an OWASP page). However, I wanted to also communicate that Kibana is not vulnerable, which is why I called it the "defunct" Code app.

https://github.com/elastic/kibana/blob/b49192626a8528af5d888545fb14cd1ce66a72e7/x-pack/legacy/plugins/code/server/lsp/workspace_command.ts#L40-L44[`spawnProcess`]
function.
** Common Node.js offenders: `child_process.spawn`, `child_process.exec`, `eval`, `Function('some string')`, `vm.runInContext(x)`,
`vm.runInNewContext(x)`, `vm.runInThisContext()`
** Common client-side offenders: `eval`, `Function('some string')`, `setTimeout('some string', num)`, `setInterval('some string', num)`

See also:

* https://portswigger.net/daily-swig/prototype-pollution-the-dangerous-and-underrated-vulnerability-impacting-javascript-applications[Prototype
pollution: The dangerous and underrated vulnerability impacting JavaScript applications | portswigger.net]
* https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf[Prototype
pollution attack in NodeJS application | Olivier Arteau]

=== Server-side Request Forgery (SSRF) ===
jportner marked this conversation as resolved.
Show resolved Hide resolved

https://owasp.org/www-community/attacks/Server_Side_Request_Forgery[_OWASP reference for SSRF_]

SSRF is a class of attacks where a vulnerable server is forced to make an unintended request, usually to an HTTP API. This is often used as
a vector for information disclosure or injection attacks.

*Best practices:*

* Ensure that all outbound requests from the {kib} server use hard-coded URLs if possible.
jportner marked this conversation as resolved.
Show resolved Hide resolved
* If user input is used to construct a URL for an outbound request, ensure that an allow-list is used to validate the endpoints and that user input is escaped properly. Ideally
jportner marked this conversation as resolved.
Show resolved Hide resolved
this allow-list should be set in `kibana.yml` so only server administrators can change it.
** This is particularly relevant when using `transport.request` with the {es} client, as no automatic escaping is performed.

=== Reverse Tabnabbing ===
jportner marked this conversation as resolved.
Show resolved Hide resolved

https://owasp.org/www-community/attacks/Reverse_Tabnabbing[_OWASP reference for Reverse Tabnabbing_]

Reverse Tabnabbing is an attack where a link to a malicious page is used to rewrite a vulnerable parent page. This is often used as a vector
jportner marked this conversation as resolved.
Show resolved Hide resolved
for phishing attacks. {kib} defends against this primarily by widespread use of the EUI framework, which automatically adds the `rel`
jportner marked this conversation as resolved.
Show resolved Hide resolved
attribute to anchor tags, buttons, and other vulnerable DOM elements.

*Best practices:*

* Use EUI components to build your UI whenever possible. Otherwise, ensure that any DOM elements that have an `href` attribute also have the
`rel="noreferrer noopener"` attribute specified. For more information, see the
jportner marked this conversation as resolved.
Show resolved Hide resolved
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#tabnabbing[OWASP HTML5 Security Cheat
Sheet].
* Allowing users to input markdown is a common culprit. If using a non-EUI markdown renderer, use a custom link renderer for rendered links.
jportner marked this conversation as resolved.
Show resolved Hide resolved

=== Information Disclosure ===
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Everything else here is a class of attacks, but Information Disclosure is a generic threat. I opted to leave this here as I think it's a good concern for folks to keep top-of-mind.

jportner marked this conversation as resolved.
Show resolved Hide resolved

Information Disclosure is not an attack, but it describes whenever sensitive information is accidentally revealed. This can be configuration
jportner marked this conversation as resolved.
Show resolved Hide resolved
info, stack traces, or other data that the user has not been authorized to access. This is a widespread concern that cannot be addressed
jportner marked this conversation as resolved.
Show resolved Hide resolved
with a single security control, but at a high level {kib} relies on the Hapi framework to automatically redact stack traces and detailed
jportner marked this conversation as resolved.
Show resolved Hide resolved
error messages in HTTP 5xx response payloads.

*Best practices:*

* When writing your code, look for instances where sensitive information may be accidentally revealed, particularly in error messages, in
jportner marked this conversation as resolved.
Show resolved Hide resolved
the UI, and in URL parameters that are exposed to users.
jportner marked this conversation as resolved.
Show resolved Hide resolved
* Make sure that sensitive request data is not forwarded to external resources. For example, copying client request headers and using them
to make an another request could accidentally expose the user's session cookie.
jportner marked this conversation as resolved.
Show resolved Hide resolved