Skip to content

Commit

Permalink
Vulnerabilities Document - PR 3740 (#3747)
Browse files Browse the repository at this point in the history
  • Loading branch information
russelljtdyer authored Sep 30, 2024
1 parent 45672c2 commit 787b359
Showing 1 changed file with 18 additions and 18 deletions.
36 changes: 18 additions & 18 deletions articles/flow/security/advanced-topics/vulnerabilities.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Common Vulnerabilities
description: Descriptions of common vulnerabilities (e.g., SQL injections, cross-site request forgeries, cross-site scripting).
description: Descriptions of common vulnerabilities such as SQL injections, cross-site request forgeries, cross-site scripting.
order: 30
---

Expand All @@ -10,11 +10,11 @@ order: 30
// tag::sql-injections[]
== SQL Injections

Since Vaadin is a backend-agnostic UI framework, it doesn't interact directly with backend access. Instead, choosing a backend framework (e.g., Spring Data) is left to the developer. This page describes common vulnerabilities such as SQL injections, Cross-Site Request Forgeries (CSRF), and Cross-Site Scripting (XSS).
Since Vaadin has a backend-agnostic UI framework, it doesn't interact directly with backend access. Instead, choosing a backend framework (e.g., Spring Data) is left to the developer. This page describes common vulnerabilities such as SQL injections, Cross-Site Request Forgeries (CSRF), and Cross-Site Scripting (XSS).

Vaadin doesn't provide mitigation for SQL injections. This is left to the backend provider and developer. However, following the data validation and escaping guidelines (see the <<xss>> section), as well as standard secure database access practices, SQL injections can be completely blocked in Vaadin applications.
Vaadin doesn't provide mitigation for SQL injections. This is done by the backend provider and developer. However, following the data validation and escaping guidelines (see the <<xss>> section), as well as standard secure database access practices, SQL injections can be blocked fully in Vaadin applications.

Most providers have their own methods of dealing with injections. You should follow those guidelines. However, if you use pure JDBC, you have to deal with injection risks yourself. Here's an example with JDBC, demonstrating an SQL injection mitigation using the value from a `TextField` in a prepared statement:
Most providers have their own methods of dealing with injections. You should follow those guidelines. However, if you use pure JDBC, you'll have to address injection risks yourself. Here's an example with JDBC, demonstrating an SQL injection mitigation using the value from a `TextField` in a prepared statement:
// end::sql-injections[]

[source,java]
Expand Down Expand Up @@ -50,11 +50,11 @@ new TextField("Set new username:", valueChangeEvent -> {

All requests between the client and the server are included with a user-session-specific CSRF token. All communication between them is handled by Vaadin, so you don't have to include and verify CSRF tokens, manually.

Vaadin follows the "Synchronizer Token Pattern". See link:https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern[this article] for more design insights.
Vaadin follows the "Synchronizer Token Pattern". See the link:https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern[Site Request Forgery Prevention article] for more design insights.

UIDL requests are protected by `Vaadin-Security-Key` CSRF token. WebSocket requests are protected with `Vaadin-Push-ID` CSRF token.

This key is generated by Vaadin per UI instance -- Vaadin 10 is an exception: the key is generated per session. It's sent to the browser as a part of UIDL JSON string included in the bootstrap response (i.e., initial HTML page) from the server. The key is sent by the server to the client only once per opened browser tab, and not repeated in each response. When the page is refreshed or the user opens a new tab, another key is generated by Vaadin and sent to the browser.
This key is generated by Vaadin per UI instance -- version 10 is an exception in that the key is generated per session. It's sent to the browser as a part of UIDL JSON string included in the bootstrap response (i.e., initial HTML page) from the server. The key is sent by the server to the client only one time per opened browser tab, and not repeated in each response. When the page is refreshed or the user opens a new tab, another key is generated by Vaadin and sent to the browser.

Here's an example of sending CSRF tokens to the client, with other data omitted:

Expand Down Expand Up @@ -102,7 +102,7 @@ The CSRF token is passed inside the JSON message in the request body. Here's an
}
----

`Vaadin-Push-ID` is generated by Vaadin per user session. `Vaadin-Push-ID` is used to check whether a given push ID in the WebSocket request matches the user's session push ID. If this ID is missing, the request is ignored and the WebSocket connection is closed.
`Vaadin-Push-ID` is generated by Vaadin per user session. `Vaadin-Push-ID` is used to check whether a given push ID in the WebSocket request matches the user's session push ID. If this ID is missing, though, the request is ignored and the WebSocket connection is closed.

In Vaadin services requests, the CSRF token is passed in the `X-CSRF-Token` HTTP header like so:

Expand All @@ -121,7 +121,7 @@ The CSRF token mechanism can be overridden on the server. You might do this, for

Vaadin has built-in protection against cross-site scripting (XSS) attacks. Vaadin uses browser APIs that make the browser render content as text instead of HTML (e.g., using `innerText` instead of `innerHTML`). This negates the chance of inserting, for example, `<script>` tags into the DOM by binding insecure string values.

Some Vaadin components explicitly allow HTML content for certain attributes. As a result, your application needs to ensure the data doesn't contain XSS payloads. Allowing insecure HTML content is never the default. It's an explicit choice by developers. Vaadin recommends using, for example, `jsoup` for sanitation and escaping.
Some Vaadin components explicitly allow HTML content for certain attributes. As a result, you need to ensure that your application's data doesn't contain XSS payloads. Allowing insecure HTML content is never the default: it's an explicit choice by developers. Vaadin recommends using, for example, `jsoup` for sanitation and escaping.

Here are a few examples of built-in escaping, and some in which escaping is left to the developer:
// end::xss[]
Expand All @@ -130,18 +130,18 @@ Here are a few examples of built-in escaping, and some in which escaping is left
----
Div div = new Div();
// These are safe as they treat the content as plain text.
// These are safe as they treat the content as plain text:
div.setText("<b>This won't be bolded.</b>");
div.getElement().setText("<b>This won't be bolded either.</b>");
div.setTitle("<b>This won't be bolded either.</b>");
// These aren't safe
// These aren't safe:
div.getElement().setProperty("innerHTML", "<b>This IS bolded.</b>");
div.add(new Html("<b>This IS bolded.</b>"));
----

// tag::xss-with-helper[]
You can use helpers to mitigate the risk when data isn't trusted. Here's an example that transforms data that might have dangerous HTML to a safe format:
You can use helpers to mitigate the risk when data isn't trusted. Here's an example that transforms data which might have dangerous HTML to a safe format:
// end::xss-with-helper[]

[source,java]
Expand All @@ -158,16 +158,16 @@ Sometimes you may need to run custom scripts inside the application. Running any

[source,java]
----
// The script below can do whatever it wants. Use the method with care.
// The script below can do whatever it wants, so use with care:
UI.getCurrent().getPage().executeJs("window.alert('This method is inherently unsafe');");
// This is especially dangerous.
// You can't know what the script contains, nor can you make it safe.
// This is especially dangerous since you can't be sure
// what the script contains, nor can you make it safe:
String script = getExternalScript();
UI.getCurrent().getPage().executeJs(script);
----

Scripts can't be automatically escaped since any escaping would cause the script not to work. Vaadin can't know which scripts are dangerous and which aren't. It's up to you to make sure the scripts are safe. However, you can safely pass parameters to JS execution by using the following syntax:
Scripts can't be escaped automatically since any escaping would cause the script not to work. Vaadin can't know which scripts are dangerous and which are not. It's up to you to make sure the scripts are safe. However, you can safely pass parameters to JS execution by using the following syntax:

[source,java]
----
Expand All @@ -182,19 +182,19 @@ UI.getCurrent().getPage().executeJs(script, scriptParam);

=== Using Templates

When using Polymer Templates in Vaadin applications, you need to be extra careful when inserting data into the DOM, as well as when using JavaScript. Vaadin automatically uses String values safely when using a `TemplateModel` from the server side. However, the framework has no control over what you do when using HTML or JavaScript inside the template itself. An example is binding a `TextField` with a JavaScript value directly to client-side logic: there's no guarantee that the input is safe; it should be sanitized before use.
When using Polymer Templates in Vaadin applications, you need to be extra careful when inserting data into the DOM, as well as when using JavaScript. Vaadin uses String values safely when using a `TemplateModel` from the server side. However, the framework has no control over what you do when using HTML or JavaScript inside the template itself. An example would be binding a `TextField` with a JavaScript value directly to client-side logic: there's no guarantee that the input is safe; it should be sanitized before use.

Reading values from template models and receiving Remote Procedure Calls (RPC) in server-side methods has the same caveats as discussed in the Data Validation section. You should never trust values sent from the client.


// tag::java-serialization[]
== Java Serialization Vulnerability

A general security issue has been identified in programming language mechanics where the language allows execution of code that comes from serialized objects. Java language isn't immune to this: the Java Serialization framework, Remote Method Invocation (RMI), Java Management Extensions (JMX), and Java Message Service (JMS) features are vulnerable to it.
A general security issue has been identified in programming language mechanics in which the language allows execution of code that comes from serialized objects. Java language isn't immune to this: the Java Serialization framework, Remote Method Invocation (RMI), Java Management Extensions (JMX), and Java Message Service (JMS) features are all vulnerable to it.

If an application is set up to deserialize Java objects (e.g., using the libraries previously mentioned), an attacker can feed the system a malicious payload that may be deserialized into Java objects. The attacker can then execute arbitrary code using specific language features (e.g., reflection).

Vaadin has published https://v.vaadin.com/security-alert-for-java-deserialization-of-untrusted-data-in-vaadin-severity-level-moderate[a security alert for this vulnerability]. It can't be fixed in Vaadin, but you must instead mitigate the risk using the methods described in the alert appendices.
Vaadin has published https://v.vaadin.com/security-alert-for-java-deserialization-of-untrusted-data-in-vaadin-severity-level-moderate[a security alert for this vulnerability]. It can't be fixed in Vaadin, but you can mitigate the risk by using the methods described in the alert's appendices.
// end::java-serialization[]


Expand Down

0 comments on commit 787b359

Please sign in to comment.