OWASP_Application_Security_Verification_Standard_4.0 - scriptCode

Remote service calls

Treat any parameters entering the ScriptCode as untrusted when sending to services

In practice this means that you must strictly follow the API rules provided by the REST client. Among other things it defines how to construct the path as a list of individual address segments. Such an interface may seem unintuitive, but it provides greater security.

Sample code

Wrong:

const url = "/api/form/" + context.getFirstParameter("form_id") + "/data";
const response = api.rest.v1.get("host", {pathParams: url.split("/")});

Right:

const pathParams = ["api", "form", context.getFirstParameter("form_id"), "data"];
const response = api.rest.v1.get("host", {pathParams: pathParms});
What are we protecting against?

Proper use of the API will protect us from attacks that modify the target address. Let's follow the sample code assuming the form_id parameter comes from a form field. If the user types "abc/def" into the field, the "/" character in the first example will be treated as part of the address and we will end up calling the service at "/api/form/abc/def/data", which in practice can accidentally hit a different service ("/api/form/{x}/{y}/data" instead of "/api/form/{x}/data" — instead of x = "abc/def" we will have x = "abc", y = "def"). The code in the second example will cause that character to be escaped and call the address "/api/form/abc%2Fdef/data" (that is, in the address "/api/form/{x}/data" the variable x will take the value "abc/def").

Handling authorization data for services

Authorization data should never be used directly in ScriptCode. When calling external services (e.g. via api.rest.v1) the platform is responsible for setting the appropriate authorization data in the request to the service. If this is not supported for a given service, a request should be submitted to the PO. For services where implementation is technically impossible or will be time-consuming, consult developers on how to securely provide the authorization data. Regardless of the approach taken, you must absolutely avoid storing authorization data (in code, session variables, process variables, form fields) and sending it to the frontend (form fields — including technical fields, session variables).

How to recognize problematic data? Unfortunately, due to the variety of authentication methods it is difficult to present a complete list of such data — use common sense and pay special attention to data that grants access to services. Below is a short list of terms to help you identify such data — if you encounter them be alert:

  • login/username and password,

  • token,

  • key,

  • Authorization header,

  • API key,

  • API token,

  • bearer token,

  • JWT token.

Retrieving remote resources

All resources we use (e.g.: images, documents, card images, etc.) should come from a trusted source. Most often that source is the eximee platform itself or some banking resource, but it should never be the internet. In most cases eximee restricts the ability to use resources only to trusted ones (e.g.: in the REST service client you can refer only to services defined by the administrator), however there may be places where such a restriction is not implemented (or cannot be implemented). Each time you want to use an external source in the application (in practice some URL) you should verify whether it is a trusted source (comes from the bank's domain, arrived in the requirements) — if the source is not trusted consult its use with the PO. It is unacceptable to use external services to implement functionality that the platform does not provide — in such cases you should request that functionality.

Example problem with external resources and its consequences

On one of the printouts we had a requirement to generate a QR code based on the application data. Because the platform did not have such functionality the developer decided to use an external API https://api.qrserver.com. During document generation the external service began to be called https://api.qrserver.com/v1/create-qr-code/?data=${dataFormatted}&size=140x140 (dataFormatted are the data that were collected on the application), and the result of its call was placed on the printout as an image.

What are the consequences of such conduct:

  1. This is an external service, we do not control it, we have no influence over its downtime periods, it may potentially disappear from the internet

  2. The licensing model was not identified — we expose our client and ourselves to legal and financial consequences for using the service contrary to the license

  3. We do not know how this external service works — it may potentially generate malicious code that we place on the printout (in the PDF) and that will be executed at the client

  4. The variable dataFormatted contained data such as the client's address or the amount of a cash deposit in the bank — these are data protected by GDPR and banking law; by using them in the link we transmitted them to an external entity (causing a data leak) — we expose the bank and ourselves to legal and financial consequences

Sensitive data

Use a sensitive logger for logging sensitive data

Sample code

New loggers (preferred method):

New loggers by default treat every passed parameter as sensitive data. To change this behavior you must explicitly use nonsensitive on the parameter. Additionally new loggers allow placing parameters in a text template (we do not concatenate like with the old loggers).

Wrong:

const pesel = context.getFirstParameter("pesel");
// 1.
Logger.info("Customer's pesel filled in on the form: {}", nonsensitive(pesel));
// 2.
Logger.info("Customer's pesel filled in on the form: " + pesel);

Right:

const pesel = context.getFirstParameter("pesel");
Logger.info("Customer's pesel filled in on the form: {}", pesel)

Last updated

Was this helpful?