White Paper

TECHNICAL REPORTS

Secure Engineering Guidelines

By WSO2 Platform Security Team
October 2018 | TR-001

Table of Contents

A. WSO2 Secure Coding Guidelines

Version: 2.1 Date: October 22, 2018

1. Introduction

This document summarizes the "Secure Coding Guidelines" that should be followed by WSO2 engineers while engineering WSO2 products, as well as applications used within the organization.

The purpose of this document is to increase the security awareness and make sure the products and the applications developed by WSO2 are inherently secure, by making sure security best practices are followed throughout the Software Development Life Cycle.

1.1 Organization of the Document

"OWASP Top 10 - 2017 Prevention" section of the document categorizes different attacks or security threats that engineers must focus on while engineering a product or an application. Prevention techniques are discussed in generic form, and there are sections that discuss programming language specific prevention techniques.

“OWASP Top 10 - 2013 Prevention” section of the document categorizes OWASP Top 10 2013 list of the most critical application security risks. But OWASP has updated its top 10 list in 2017. Please refer to OWASP Top 10 2017 for updated list.

“OWASP Mobile Top 10 Prevention” section of the document categorizes different attacks or security threats that engineers must focus on while engineering mobile applications. Prevention techniques are discussed in generic form, and there are sections that discuss mobile platform specific prevention techniques.

"General Recommendations for Secure Coding" section of the document discusses any security threats that are not captured within OWASP Top 10 and several generic recommendations that summarize prevention mechanisms which address multiple security threats. For example, the "Cryptographic Algorithms" section discusses general recommendations on selecting cryptographic algorithms, and sections such as "Security Related HTTP Headers" and "Securing Cookies", summarize prevention techniques used across preventing multiple attacks.

"Tooling Recommendations for Secure Coding" section brings together all the documentations relevant to security related tooling used within WSO2, and recommendations relevant to usage of such tools in the engineering process.

1.2 Formatting of the Document

Formatting for "example incorrect usage":

Example Incorrect Usage:
Code block goes here. Any highlight should use this formatting.

Formatting for "example correct usage":

Example Correct Usage:
Code block goes here. Any highlight should use this formatting.

Formatting for documenting items that require Platform Security Team's approval:

Alert - Approval Required: If any component requires that, [example security control should be skipped], the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

Formatting for documenting sample code blocks or sample code outputs used in explanations (not incorrect or correct usage samples, but general code or output used for explanations):

Code block or sample result of a program used in explanations.

Formatting for documenting example scenarios used in explanations:

Example: User input is the API description. The user might have to add some special characters in the description. However, the application is not expecting any HTML syntax in the description.

In the example scenario, output encoding will convert special characters to respective HTML character entity references.

Formatting for referencing to other documents owned by WSO2.

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Example Document"[ref].

1.3 Revision History

Version Release Date Contributors / Authors Summary of Changes
1.0 Jan 2016 Kasun Balasuriya, Dulanja Liyanage, Prakhash Sivakumar, Milinda Wickramasinghe, Tharindu Edirisinghe, Malithi Edirisinghe, Rasika Perera, Ayoma Wijethunga Initial version of Secure Coding Guidelines
1.8 May 28, 2017 Ayoma Wijethunga, Tharindu Edirisinghe Initial version of Secure Coding Guidelines - 2nd Edition
1.8.1 Nov 13, 2017 Ayoma Wijethunga Minor modification to XML External Entity (XXE) prevention sample.
1.9 Nov 16, 2017 Kasun Dharmadasa, Ayoma Wijethunga, Charitha Goonetilleke Adding initial version of Secure Coding Guidelines for Mobile Applications
2.0 Sep 4, 2018 Mathuriga Thavarajah, Ayoma Wijethunga Updating OWASP Top 10 list to OWASP Top 10 Application Security Risks - 2017 list
2.1 Oct 22, 2018 Kasun Dharmadasa Adding the Zip Slip Vulnerability prevention

2. OWASP Top 10 - 2017 Prevention

2.1 A1 - Injection

2.1.1 SQL Injection

A SQL injection attack consists of insertion or "injection" of a SQL query via the input data from the client to the application. A successful SQL injection exploit can read sensitive data from the database, modify database data (Insert/Update/Delete), execute administration operations on the database (such as shutdown the DBMS), recover the content of a given file present on the DBMS file system and in some cases issue commands to the operating system. SQL injection attacks are a type of injection attack, in which SQL commands are injected into data-plane input in order to effect the execution of predefined SQL commands 1.

2.1.1.1 Prevention Techniques

Use secure language constructs (Example: PreparedStatement in Java) when executing SQL statements. Use language specific best practices when using secure language constructs to avoid any possible misuses.

Restructure the methods so that the application does not accept table names, column names, ordering information, offset details or any other value that cannot be parameterized using language specific best practices.

Example: In Java context, ORDER BY column name of below query can not be provided as a PreparedStatement parameter.

SELECT ID,NAME FROM EXAMPLE_TABLE WHERE AGE > ? ORDER BY DYNAMIC_COLUMN_NAME;

If user input must be used in sections that cannot be parameterized using secure language constructs, perform allowlisting against the user input.

Example: A allowlist should be maintained which includes an acceptable list of inputs for "DYNAMIC_COLUMN_NAME". User input should be rejected if provided input is not within expected set of values.

2.1.1.2 Java Specific Recommendations

Use PreparedStatements to prevent SQL injections. The statement will be compiled and the user variables will be assigned to the query parameters in the runtime. Since user variables are being set to a precompiled SQL statement, this approach avoids possibility of SQL injections.

Example Incorrect Usage:
String query = "SELECT account_balance FROM user_data WHERE user_name = " + request.getParameter("customerName");
try {
Statement statement = connection.createStatement( ... );
ResultSet results = statement.executeQuery( query );
}
//Catch block...

Example Correct Usage:
String customerName = request.getParameter("customerName");
//Validations. Etc...

String query = "SELECT account_balance FROM user_data WHERE user_name = ?";
try {
PreparedStatement preparedStatement = connection.prepareStatement( query );
preparedStatement.setString( 1, customerName );
ResultSet results = preparedStatement.executeQuery();
}
//Catch block...

When processing dynamic query segments that cannot be set as PreparedStatement parameters (table names, column names, ordering information, offset details), validate user input against a allowlist. This approach avoids the risk of providing end user the ability to append anything uncontrolled to the SQL query.

Example 1:

Example Incorrect Usage:
String customerType = request.getParameter("customerType");
String order = request.getParameter("order");
//Validations. Etc...

String query = "SELECT user_name, account_balance FROM user_data WHERE user_type = ? ORDER BY " + order;
try {
PreparedStatement preparedStatement = connection.prepareStatement( query );
preparedStatement.setString( 1, customerType );
ResultSet results = preparedStatement.executeQuery();
}
//Catch block...

Example Correct Usage:
//Class level static map maintaining "user input to database column" mapping
private static final Map<String, String> validOrderColumns = new HashMap<String, String>();
validOrderColumns.add("accountBalance", "account_balance");
validOrderColumns.add("userName", "user_name");

//Method definition...
String customerType = request.getParameter("customerType");
String orderColumn = request.getParameter("orderColumn");
String orderDirection = request.getParameter("orderDirection");

if (orderDirection.equalsIgnoreCase("DESC")) {
orderDirection = "DESC";
} else {
orderDirection = "ASC";
}

orderColumn = validOrderColumns.get(orderColumn);
//Validations. Etc...

String query = "SELECT user_name, account_balance FROM user_data WHERE user_type = ? ORDER BY " + orderColumn + " " + orderDirection;
try {
PreparedStatement preparedStatement = connection.prepareStatement( query );
preparedStatement.setString( 1, customerType );
ResultSet results = preparedStatement.executeQuery();
}
//Catch block...

Example 2:

Example Incorrect Usage:
//...
query = "SELECT * FROM " + columnFamily + " WHERE " +
APIUsageStatisticsClientConstants.API_PUBLISHER + " = ?";

if (selectRowsByColumnName != null) {
query = query + " AND " + selectRowsByColumnName + " = ? ";
}

try {
PreparedStatement preparedStatement = connection.prepareStatement( query );
preparedStatement.setString( 1, publisher );
if (selectRowsByColumnName != null) {
preparedStatement.setString( 2, selectRowsByColumnValue );
}
ResultSet results = preparedStatement.executeQuery();
}
//Catch block

Example Correct Usage:
//Class level static map maintaining user input to column mapping
private static final Map<String, String> validSelectColumns = new HashMap<String, String>();
validSelectColumns.add("apiName", "api_name");
validSelectColumns.add("apiId", "api_id");

private static final Map<String, String> validColumnFamilies = new HashMap<String, String>();
validSelectColumns.add("commonApis", "COMMON_APIS");
validSelectColumns.add("corporateApis", "CORPORATE_APIS");

//Method definition...
String columnFamily = validSelectColumns.get(columnFamilyUserInput)
if(columnFamily == null) {
//Throw required exceptions or errors.
return;
}

query = "SELECT * FROM " + columnFamily + " WHERE " +
APIUsageStatisticsClientConstants.API_PUBLISHER + " = ?";

if (selectRowsByColumnName != null) {
String columnName = validSelectColumns.get(selectRowsByColumnName);
if(columnName != null) {
query = query + " AND " + columnName + " = ? ";
} else {
selectRowsByColumnName = null;
}
}

try {
PreparedStatement preparedStatement = connection.prepareStatement( query );
preparedStatement.setString( 1, publisher );
if (selectRowsByColumnName != null) {
preparedStatement.setString( 2, selectRowsByColumnValue );
}
ResultSet results = preparedStatement.executeQuery();
}
//Catch block...

2.1.1.3 PHP Specific Recommendations

Use PHP Data Objects (PDO) Extension or MySQL Improved Extension when executing queries that include user inputs. Make sure to use parameterizing capabilities of the extensions.

Example Incorrect Usage:
<?php
$query = "SELECT id, name, inserted, size FROM products WHERE size ='$size'";
$result = odbc_exec($conn, $query);
?>

Example Incorrect Usage:
<?php
$query = "SELECT id, name, inserted, size FROM products WHERE size = '$size'";
$result = pg_query($conn, $query);
?>

Example Incorrect Usage:
<?php
$query = "SELECT id, name, inserted, size FROM products WHERE size = '$size'";
$result = mssql_query($conn, $query);
?>

Using PHP Data Objects (PDO) Extension2,3

Example Correct Usage:
<?php
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array('name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
?>

Using MySQL Improved Extension 4,3

Example Correct Usage:
<?php
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);

$stmt->execute();

$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
?>

Example with query segments that cannot be parameterized with PDO or MySQL Improved Extension5:

Example Incorrect Usage:
<?php
$offset = $argv[0]; // beware, no input validation!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
?>

Example Correct Usage:
<?php
settype($offset, 'integer');
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";

// please note %d in the format string, using %s would be meaningless
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",$offset);
$result = pg_query($conn, $query);
?>

2.1.2 LDAP Injection

LDAP Injection is an attack used to exploit web based applications that construct LDAP statements based on user input. When an application fails to properly sanitize user input, it's possible to modify LDAP statements using a local proxy. This could result in the execution of arbitrary commands such as granting permissions to unauthorized queries, and content modification inside the LDAP tree. The same advanced exploitation techniques available in SQL Injection can be similarly applied in LDAP Injection 6,7.

All user inputs that are getting directly appended to any LDAP queries should be filtered through an encoding function that does proper encoding for LDAP8.

Example Incorrect Usage:
String grpSearchFilter = searchFilter.replace("?",role);
groupResults = searchInGroupBase(grpSearchFilter,...)

Example Correct Usage:
String grpSearchFilter = searchFilter.replace("?", escapeSpecialCharactersForFilter(role));
groupResults = searchInGroupBase(grpSearchFilter,...)

2.1.3 OS Command Injection

Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In this attack, the attacker-supplied operating system commands are usually executed with the privileges of the vulnerable application. Command injection attacks are possible largely due to insufficient input validation9.

2.1.3.1 Prevention Techniques

Products or applications should not use user inputs in constructing OS commands.

Alert - Approval Required: If any component requires that, user input to be appended to an OS command or to be interpreted as OS command, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

2.1.3.2 Java Specific Recommendations

WSO2 Products should not use java.lang.Runtime.getRuntime(), java.lang.ProcessBuilder or any other method to execute OS commands, constructed based on user input.

Example Incorrect Usage:
java.lang.Runtime.getRuntime().exec(userInput);

Example Incorrect Usage:
java.lang.Runtime.getRuntime().exec("curl -v -k " + userInput);

Example Incorrect Usage:
java.lang.ProcessBuilder processBuilder = new java.lang.ProcessBuilder("curl", "-v", "-k", userInput);

2.1.3.3 PHP Specific Recommendations

PHP applications should not use "exec" function10, "WScript.Shell"11 or any other method to execute OS commands, constructed based on user input.

Example Incorrect Usage:
<?php
echo exec(userInput);
?>

Example Incorrect Usage:
<?php
echo exec("curl -k " . userInput);
?>

Example Incorrect Usage:
<?php
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("cmd " . userInput, 7, false);
?>

2.1.4 HTTP Response Splitting (CRLF Injection)

Including unvalidated data in an HTTP header allows an attacker to specify the entirety of the HTTP response rendered by the browser. When an HTTP request contains unexpected CR (carriage return, also given by %0d or \r) and LF (line feed, also given by %0a or \n) characters, the server may respond with an output stream that is interpreted as two different HTTP responses (instead of one). An attacker can control the second response and mount attacks such as cross-site scripting and cache poisoning attacks16.

For example, if below snippet was used to set cookie value, malicious value "Wiley Hacker\r\nContent-Length:45\r\n\r\nHTTP/1.1 200 OK\r\n...." can result in generating two HTTP responses17.

String author = request.getParameter(AUTHOR_PARAM);
...
Cookie cookie = new Cookie("author", author);
cookie.setMaxAge(cookieExpiration);
response.addCookie(cookie);

HTTP/1.1 200 OK
Set-Cookie: author=Wiley Hacker
Content-Length:45

HTTP/1.1 200 OK
...

2.1.4.1 Prevention Techniques

With regards to WSO2 Carbon 4 based products, Apache Tomcat will handle this internally, by disallowing "carriage return" and "line feed" characters from the header names or values18,19.

If HTTP response generation is done in any other component, or any other HTTP transport implementation, it should be reviewed and confirmed to have a mechanism similar to Tomcat 618 and Tomcat 719 that performs necessary filtering. If such mechanism is not present in transport implementation, a central filter should be used to read all the headers and do the necessary sanitization before passing the response to transport.

Sample filter implementation is available in WSO2 Carbon 4.4.x branch20. However, this filter is not in use, since Tomcat provides the necessary protection.

Alert - Approval Required: If any transport implementation or component that generates HTTP responses directly require usage of a custom written filter that does the "carriage return" and "line feed" (CRLF) filtering, the logic performing filtering should be reviewed and approved by Platform Security Team. Platform Security Team should be informed and approval should be obtained before releasing such component or a transport implementation.

2.1.5 Log Injection / Log Forging (CRLF Injection)

Including unvalidated data in log files allows an attacker to forge log entries or inject malicious content into logs. When a log entry contains unexpected CR (carriage return, also given by %0d or \r) and LF (line feed, also given by %0a or \n) characters, the server may record them in the log files/monitoring systems as different events. This can be used to forge log entries and might result in business level implications, if logs are used for further actions, such as reconciliation21.

For example, if below snippet was used to print a log entry, malicious input "example1\r\n$100 payment made to author: example2" can result in generating two log lines.

String author = request.getParameter(AUTHOR_PARAM);
...
log.info("$100 payment made to author: " + author);

$100 payment made to author: example1
$100 payment made to author: example2

2.1.5.1 Prevention Techniques

In WSO2 Carbon 4 (4.4.3 onwards), log appenders can be configured to append a UUID to each log entry. UUID will be randomly generated during server startup and the UUID regeneration time can be configured if such behavior is required. Therefore, even if a log line was forged, it would be possible to isolate the forged entry, since it will not contain the relevant valid UUID.

UUID in logs can be enabled by adding %K in log4j pattern and relevant configuration is further documented in Administration Guide22.

2.2 A2 - Broken Authentication

2.2.1 Session Hijacking

The Session Hijacking attack consists of the exploitation of the web session control mechanism, which is normally managed with a session token.

Because HTTP communication uses different TCP connections, the web server needs a method to recognize every user's connections. The most useful method depends on a token that the Web Server sends to the client browser after a successful client authentication. A session token is normally composed of a string of variable width and it could be used in different ways, like in the URL, in the header of the HTTP requisition as a cookie, in other parts of the header of the HTTP request, or yet in the body of the HTTP request. (In WSO2 products, session ID is maintained as a cookie and will be communicated between browser and the server through HTTP headers).

The Session Hijacking attack compromises the session token by stealing or predicting a valid session token to gain unauthorized access to the Web Server23.

The session token could be compromised in different ways; the most common methods controllable by application developer are:

  • Session Sniffing
  • Eavesdropping attack
  • Predictable session token
  • Client-side attacks (XSS, malicious JavaScript Codes, Trojans, etc)
2.2.1.1 Prevention Techniques

Preventing session sniffing and eavesdropping attacks

HTTP Strict-Transport-Security Header (HSTS)

HTTP Strict Transport Security (HSTS) is an opt-in security enhancement that is specified by a web application through the use of a special response header. Once a supported browser receives this header, that browser will prevent any communications from being sent over HTTP, to the specified domain and will instead send all communications over HTTPS24.

HSTS header prevents sensitive information exposure over unencrypted channels by avoiding SSLStrip attacks25 and by preventing a victim from using HTTP links that correspond to HTTPS-protected site, which could lead to session cookie exposure, if not configured properly.

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Engineering Guidelines - Security Related HTTP Headers".

HTTP Public-Key-Pins Header (HPKP)

To ensure the authenticity of a server's public key used in TLS sessions, this public key is wrapped into an X.509 certificate which is usually signed by a certificate authority (CA). Web clients such as browsers trust a lot of these CAs, which can all create certificates for arbitrary domain names. If an attacker is able to compromise a single CA, they can perform MITM attacks on various TLS connections. HPKP can circumvent this threat for the HTTPS protocol by telling the client which public key belongs to a certain web server26.

HPKP is a Trust on First Use (TOFU) technique. The first time a web server tells a client via a special HTTP header which public keys belong to it, the client stores this information for a given period of time. When the client visits the server again, it expects at least one certificate in the certificate chain to contain a public key whose fingerprint is already known via HPKP. If the server delivers an unknown public key, the client should present a warning to the user26. In addition, HPKP header prevents attack patterns such as SSLSplit27 attack.

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Engineering Guidelines - Security Related HTTP Headers".

Avoiding predictable session token

Please refer to documentation section "Session Prediction".

Preventing client-side attacks

Please refer to documentation section "Cross-Site Scripting (XSS)".

Cookie security

Cookie attributes should be set properly, in order to prevent session related cookies from getting exposed over unencrypted channels. Please refer to documentation section "Securing Cookie".

2.2.2 Session Fixation

Session Fixation is an attack that permits an attacker to hijack a valid user session (a type of a Session Hijacking attack). The attack explores a limitation in the way the web application manages the session ID, more specifically the vulnerable web application. When authenticating a user, it doesn't assign a new session ID, making it possible to use an existing session ID. The attack consists of obtaining a valid session ID (e.g. by connecting to the application), inducing a user to authenticate himself with that session ID, and then hijacking the user-validated session by the knowledge of the used session ID. The attacker has to provide a legitimate Web application session ID and try to make the victim's browser use it28.

2.2.2.1 Prevention Techniques

User Login Flow

When a user is successfully authenticated, a new session should be initiated and the guest session that was maintained to access the login sequence should be invalidated. This approach makes sure that an attacker is unable to use a compromised guest session token to gain access to an active user session.

User Logout Flow

When a user logs out of the system, any existing session should be invalidated so that an attacker is unable to login back into the system by re-submitting the previous session token.

2.2.2.2 Java Specific Recommendations

User Login Flow

Invalidate the HttpSession and create a new session after authentication is complete, and before setting any values to the user session.

Example Incorrect Usage:
boolean validLogin = login(username, password);
if(validLogin) {
session.setAttribute(Constants.IS_AUTHENTICATED, Constants.AUTHENTICATED);
session.setAttribute(Constants.AUTHENTICATED_USER, username);
}

Example Correct Usage:
booleanspan validLogin = login(username, password);
if(validLogin) {
session.invalidate();
session = request.getSession();
session.setAttribute(Constants.IS_AUTHENTICATED, Constants.AUTHENTICATED);
session.setAttribute(Constants.AUTHENTICATED_USER, username);
}

User Logout Flow

Invalidate the HttpSession, rather than just removing user specific attributes.

Example Incorrect Usage:
//... logout sequence
session.removeAttribute(Constants.IS_AUTHENTICATED);
session.removeAttribute(Constants.AUTHENTICATED_USER);

Example Correct Usage:
//... logout sequence
session.invalidate();

Other Best Practices

Do not use HttpServletResponse#encodeRedirectURL() or HttpServletResponse#encodeURL, in any operation, since it will append the session ID to the resulting URL. Since WSO2 products are dependent on cookies, there is no functional impact of not running URLs through these methods.

Example Incorrect Usage:
String redirectUrl = response.encodeRedirectURL(request.getContextPath() +
Constant.STORE_FRONT_URL);
response.sendRedirect(redirectUrl);

Example Correct Usage:
String redirectUrl = request.getContextPath() + Constant.STORE_FRONT_URL;
response.sendRedirect(redirectUrl);

2.2.2.3 PHP Specific Recommendations

User Login Flow

Use session_regenerate_id function to renew the session after successful authentication.

Example Incorrect Usage:
<?php
$validLogin = login($username, $password);
if(validLogin) {
$_SESSION[Constants::IS_AUTHENTICATE] = Constants::AUTHENTICATED;
$_SESSION[Constants::AUTHENTICATED_USER] = $username;
}
?>

Example Correct Usage:
<?php
boolean validLogin = login($username, $password);
if(validLogin) {
if(session_regenerate_id(true)) {
$_SESSION[Constants::IS_AUTHENTICATE] = Constants::AUTHENTICATED;
$_SESSION[Constants::AUTHENTICATED_USER] = $username;
} else {
//...
}
}
?>

User Logout Flow

Destroy current session using session_destroy function, rather than just removing user specific attributes.

Example Incorrect Usage:
<?php
//... logout sequence
unset($_SESSION[Constants::IS_AUTHENTICATED]);
unset($_SESSION[Constants::AUTHENTICATED_USER]);
?>

Example Correct Usage:
<?php
//... logout sequence
session_destroy();
?>

2.2.3 Session Prediction

Session prediction attack focuses on predicting session ID values that permit an attacker to bypass the authentication schema of an application. By analyzing and understanding the session ID generation process, an attacker can predict a valid session ID value and get access to the application.

In the first step, the attacker needs to collect some valid session ID values that are used to identify authenticated users. Then, they must understand the structure of session ID, the information that is used to create it, and the encryption or hash algorithm used by application to protect it. Some bad implementations use sessions IDs composed by username or other predictable information, like timestamp or client IP address. In the worst case, this information is used in the clear text or coded using some weak algorithm like base64 encoding.

In addition, the attacker can implement a brute force technique to generate and test different values of session ID until they successfully gets access to the application35.

2.2.3.1 Prevention Techniques

Using a longer random number or string as the session key will reduce the risk that an attacker could simply guess a valid session key through trial and error or brute force attacks. Session identifiers should be at least 128 bits long to prevent brute-force session guessing attacks, according to OWASP recommendations30.

2.2.3.2 Java Specific Recommendations

WSO2 Carbon 4 based products can use the Apache Tomcat context.xml file to configure the session ID generation. Default session ID length is 16 bytes, which is exactly 128 bit. Therefore, WSO2 Carbon 4 based products match with current recommendation. However, if the recommendations change and if any product needs to increase the session ID length, it is possible to use "SessionIdGenerator" element of context.xml file to make required changes as documented in Tomcat 7 "SessionIdGenerator Component" documentation31.

2.2.3.3 PHP Specific Recommendations

Below minimum session configuration should be used with PHP applications32 :

session.hash_function = 1
session.hash_bits_per_character = 6

Full set of recommended session configuration is:

session.auto_start = Off
#session.save_path = /path/PHP-session/
#session.name = CUSTOMSESSID
session.hash_function = 1
session.hash_bits_per_character = 6
session.use_trans_sid = 0
session.cookie_domain = full.qualified.domain.name
#session.cookie_path = /application/path/
session.cookie_lifetime = 0
session.cookie_secure = On
session.cookie_httponly = 1
session.use_only_cookies = 1
session.cache_expire = 30

2.3 A3 - Sensitive Data Exposure

2.3.1 Heap Inspection Attacks

When sensitive data such as a password or an encryption key is not removed from memory, it could be exposed to an attacker using a "heap inspection" attack that reads the sensitive data using memory dumps or other methods45.

2.3.1.1 Prevention Techniques

It is recommended to store sensitive information such as user passwords in mutable data types or data structures. Once usage is complete, it is essential to clear the memory space and make sure none of the store data is present in the memory.

2.3.1.2 Java Specific Recommendations

It would seem logical to collect and store the password in an object of type java.lang.String. However, here's the caveat: Objects of type String are immutable, i.e., there are no methods defined that allow you to change (overwrite) or zero out the contents of a String after usage.

Even if String object is no longer referenced and available for garbage collection, the object can stay in the memory for multiple garbage collection cycles, allowing a heap inspection attack to capture relevant values.

This feature makes String objects unsuitable for storing security-sensitive information such as user passwords. It is essential to always collect and store security-sensitive information in a char array or a mutable data type instead46.

Once operations that require password are executed, it is required to clear the values from the array elements, before moving the variable out of scope.

Example Incorrect Usage:
String userPassword = getUserPassword(request);

Example Incorrect Usage:
//...
char[] userPassword = getUserPassword(request);
boolean valid = validateUser(username, userPassword);
if(valid) {
//Do valid actions
}
return valid;
//...

Example Correct Usage:
private static final List SENSITIVE_PARAMETER_NAME_LIST = new ArrayList();

//...
Map<String, Object> parameterMap = SecurityUtil.getSensitiveDataMap(request, SENSITIVE_PARAMETER_NAME_LIST);

char[] userPassword = (char[]) parameterMap.get("password");
String otherNonSensitiveData = (String) parameterMap.get("otherNonSensitiveData");

boolean valid = validateUser(username, userPassword);
if(valid) {
//Do valid actions
}
SecurityUtil.clearSensitiveDataMap(userPassword);
return valid;
//...

public static void clear(char[] arr) {
for(int i = 0; i < arr.length; i++) {
arr[0] = '';
}
}

2.3.2 Privacy Violation - Password Auto Complete

Browsers will sometimes ask a user if they wish to remember the password that they just entered. The browser will then store the password, and automatically enter it whenever the same authentication form is visited. This is a convenience for the user47.

Having the browser store passwords is not only a convenience for end-users, but also for an attacker. If an attacker can gain access to the victim's browser (e.g. through a Cross Site Scripting attack, or through a shared computer), then they can retrieve the stored passwords. It is not uncommon for browsers to store these passwords in an easily retrievable manner, but even if the browsers were to store the passwords encrypted and only retrievable through the use of a master password, an attacker could retrieve the password by visiting the target web application's authentication form, entering the victim's username, and letting the browser to enter the password47.

Due to associated security risks relevant to password auto complete, it is recommended to turn autocomplete off, for sensitive text fields. This includes password inputs.

Example Incorrect Usage:
<input type="password" name="password" />

Example Correct Usage: 42
<input type="password" name="password" autocomplete="off"/>

In order to support password managers and increase usability features of browsers, some modern browsers do not honor autocomplete attribute. However, regardless of browser's behavior, it is advised to turn autocomplete off, to address security compliance related issues.

2.4 A4 - XML External Entity (XXE)

An XML External Entity attack is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, server-side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts12.

2.4.1.1 Java Specific Recommendations

In order to resolve this issue, it is required to configure the XML parser correctly performing following actions.

  1. Enable the DocumentBuilderFactory namespace awareness
  2. Disable the DocumentBuilderFactory entity reference expansion
  3. Enable the DocumentBuilderFactory secure processing feature
  4. Disable the DocumentBuilderFactory "https://xml.org/sax/features/external-general-entities" feature
  5. Use a SecurityManager for the DocumentBuilderFactory
  6. Use a custom EntityResolver for the DocumentBuilder created using above DocumentBuilderFactory

Alert - Approval Required: If any component requires, any of the recommended security flags not to be set in DocumentBuilderFactory, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

DocumentBuilderFactory (DOM Parser)

Example Incorrect Usage:
DocumentBuilder builder;
ByteArrayInputStream inputStream;
Element root = null;

// xmlConfig is the XML content
inputStream = new ByteArrayInputStream(xmlConfig.getBytes());

DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();

try {
Document doc = builder.newDocumentBuilder().parse(inputStream);
root = doc.getDocumentElement();
//doc is used for further processing from here
}

Example Correct Usage:
import org.apache.xerces.impl.Constants;

private static final int ENTITY_EXPANSION_LIMIT = 0;
private static final DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();

static {
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setXIncludeAware(false);
documentBuilderFactory.setExpandEntityReferences(false);

try {
documentBuilderFactory.setFeature(Constants.SAX_FEATURE_PREFIX +
Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE, false);
} catch (ParserConfigurationException e) {
logger.error("Failed to load XML Processor Feature " +
Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE);
}
try {
documentBuilderFactory.setFeature(Constants.SAX_FEATURE_PREFIX +
Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE, false);
} catch (ParserConfigurationException e) {
logger.error("Failed to load XML Processor Feature " +
Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE);
}
try {
documentBuilderFactory.setFeature(Constants.XERCES_FEATURE_PREFIX +
Constants.LOAD_EXTERNAL_DTD_FEATURE, false);
} catch (ParserConfigurationException e) {
logger.error("Failed to load XML Processor Feature " +
Constants.LOAD_EXTERNAL_DTD_FEATURE);
}

SecurityManager securityManager = new SecurityManager();
securityManager.setEntityExpansionLimit(ENTITY_EXPANSION_LIMIT);
documentBuilderFactory.setAttribute(Constants.XERCES_PROPERTY_PREFIX +
Constants.SECURITY_MANAGER_PROPERTY, securityManager);
}
private DocumentBuilderFactory getSecuredDocumentBuilderFactory() {
return documentBuilderFactory;
}

XMLInputFactory (Stax Parser)

Example Incorrect Usage:
DocumentBuilder builder;
ByteArrayInputStream inputStream;
Element root = null;

// xmlConfig is the XML content
inputStream = new ByteArrayInputStream(xmlConfig.getBytes());

XMLInputFactory factory = XMLInputFactory.newInstance();

try {
XMLEventReader eventReader = factory.createXMLEventReader(inputStream);
while(eventReader.hasNext()) {
//doc is used for further processing from here
}
}

Example Correct Usage:
import org.apache.xerces.impl.Constants;

private static final int ENTITY_EXPANSION_LIMIT = 0;

private static final XMLInputFactory xmlInputFactory;

static {
xmlInputFactory = XMLInputFactory.newInstance();
try {
xmlInputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
} catch (IllegalArgumentException e) {
log.error("Failed to load XML Processor Feature XMLInputFactory.IS_NAMESPACE_AWARE",
e);
}

try {
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
} catch (IllegalArgumentException e) {
log.error("Failed to load XML Processor Feature XMLInputFactory.SUPPORT_DTD", e);
}

try {
xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
} catch (IllegalArgumentException e) {
log.error("Failed to load XML Processor Feature
XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES", e);
}

//If Woodstox StAX parser 5+ is used, set following property
//to disable entity expansion
//try {
// factory.setProperty("com.ctc.wstx.maxEntityDepth", 1);
//} catch (IllegalArgumentException e) {
// log.error("Failed to load XML Processor Feature com.ctc.wstx.maxEntityDept", e);
//}
}

private XMLInputFactory getSecuredXMLInputFactory() {
return factory;
}

2.4.1.2 PHP Specific Recommendations

If libxml is used in XML processing, libxml_disable_entity_loader function13 must be used to protection against XXE attacks14,15.

Alert - Approval Required: If any component requires, any of the recommended security flags not to be set in libxml, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

Example Incorrect Usage:
<?php
//User provided XML content here (Hard-coded only as an example).
$xml = <<<EOD
<?xml version="1.0"?>
<!DOCTYPE root
[
<!ENTITY foo SYSTEM "file://$dir/content.txt">
]>
<test><testing>&foo;</testing></test>
EOD;


$doc = simplexml_load_string($xml);
?>

Example Correct Usage:
<?php
//User provided XML content here (Hard-coded only as an example).
$xml = <<<EOD
<?xml version="1.0"?>
<!DOCTYPE root
[
<!ENTITY foo SYSTEM "file://$dir/content.txt">
]>
<test><testing>&foo;</testing></test>
EOD;


$oldValue = libxml_disable_entity_loader(true);
$doc = simplexml_load_string($xml);
libxml_disable_entity_loader($oldValue);
?>

Example Correct Usage:
<?php
//User provided XML content here (Hard-coded only as an example).
$xml = <<<EOD
<?xml version="1.0"?>
<!DOCTYPE root
[
<!ENTITY foo SYSTEM "file://$dir/content.txt">
]>
<test<testing>&foo;</testing></test>
EOD;


$oldValue = libxml_disable_entity_loader(true);
$dom = new DOMDocument;
$dom->loadXML($xml);
libxml_disable_entity_loader($oldValue);
?>

2.5 A5 - 2017 – Broken Access Control

2.5.1 Insecure Direct Object References

2.5.1.1 Path Traversal

A path traversal attack (also known as directory traversal) aims to access files and directories that are stored outside the web root folder. By manipulating variables that reference files with "dot-dot-slash (../)" sequences and its variations or by using absolute file paths, it may be possible to access arbitrary files and directories stored on file system including application source code or configuration and critical system files40.

Prevention Techniques

Absolute paths should not be accepted from the end-user during any operation, apart from administrative configurations.

Alert - Approval Required: If any component requires that an absolute path must be accepted from the end-user (not in administrative configuration), the use-case, as well as recommended security manager rules that are in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

The general recommendation is to avoid accepting paths or path fragments (used to build absolute or relative paths) from the end-user.

However, if any such requirement arises, it is necessary to follow language specific recommendations for validating the accepted path fragment.

Java Specific Recommendations

Normalize41 the final path constructed and check if the normalized path is within the expected boundary. The purpose of this validation is to check if any malicious user has used ".." or other traversal techniques to move out of the expected base directory the action should be performed on.

Example Incorrect Usage:
String userDirectory = request.getParameter("userDirectory");
File file = new File(Constants.USER_HOME_BASE + File.separator + userDirectory +
File.separator + Constants.LOG_FILE_NAME);

Example Correct Usage: 42
//...
String userDirectory = request.getParameter("userDirectory");
Path resolvedPath = null;
try {
resolvedPath = SecurityUtil.resolvePath(Constants.USER_HOME_BASE, userDirectory + File.separator + Constants.LOG_FILE_NAME);
} catch (IllegalArgumentException e) {
//Exception handling and informing end-user in the errors
return;
}
File file = new File(resolvedPath.toString());
//...

public class SecurityUtil {
//...

/**
* Resolves an untrusted user-specified path against the API's base directory.
* Paths that try to escape the base directory are rejected.
*
* @param baseDirPath the absolute path of the base directory that all
user-specified paths should be within
* @param userPath the untrusted path provided by the API user, expected to be
relative to {@code baseDirPath}
*/

public static Path resolvePath(final Path baseDirPath, final Path userPath) {
if (!baseDirPath.isAbsolute()) {
throw new IllegalArgumentException("Base path must be absolute")
}

if (userPath.isAbsolute())
throw new IllegalArgumentException("User path must be relative");
}

// Join the two paths together, then normalize so that any ".." elements
// in the userPath can remove parts of baseDirPath.
// (e.g. "/foo/bar/baz" + "../attack" -> "/foo/bar/attack")
final Path resolvedPath = baseDirPath.resolve(userPath).normalize();

// Make sure the resulting path is still within the required directory.
// (In the example above, "/foo/bar/attack" is not.)
if (!resolvedPath.startsWith(baseDirPath)) {
throw new IllegalArgumentException("User path escapes the base path");
}

return resolvedPath;
}
}

PHP Specific Recommendations

Normalize the final path constructed and check if the normalized path is within the expected boundary. Purpose of this validation is to check if any malicious user has used ".." or other traversal techniques to move out of the expected base directory the action should be performed on.

Example Correct Usage: 43
<?php
$basepath = USER_HOME_BASE;
$realBase = realpath($basepath);

$userDirectory = $basepath . DIRECTORY_SEPARATOR . $_GET['userDirectory'];
$userDirectoryRealPath = realpath($userDirectory);

if ($userDirectoryRealPath === false || strpos($userDirectoryRealPath, $realBase) !== 0) {
//Directory Traversal. Informing end-user in the errors.

} else {
//No Directory Traversal. Proceed with usual operations based on userDirectoryRealPath.
}
?>

2.5.2 Missing Function Level Access Control

If the authentication check in sensitive request handlers is insufficient or non-existent, the vulnerability can be categorized as Missing Function Level Access Control48.

2.5.2.1 Prevention Techniques
  • Make sure authentication checks are present for any restricted URLs.
  • Make sure user authorization (role-permission) is checked before allowing a user to execute any function. It is essential to make sure, authorization checks are done, before processing any state-changing operation.
  • "login" permission should not be granted for any user that does not require access to Carbon Management Console (Carbon 4). (Example: API Manager - Store - Self-registered user).
  • The enforcement mechanism(s) should deny all access by default, requiring explicit grants to specific roles for access to every function.
  • If the function is involved in a workflow, check to make sure the conditions are in the proper state to allow access.
  • Make sure audit logs are maintained properly and authentication and authorization related changes are logged in audit logs.

2.6 A6 - 2017 - Security Misconfiguration

This section is not within the scope of "Secure Coding Guidelines". However, necessary prevention techniques are summarized for information.

If a component is susceptible to attack due to an insecure configuration it would classify as security misconfiguration44.

2.6.1.1 Prevention Techniques

Product Documentation

Product documentation should explain or reference to steps to be executed in order to perform required security hardening and production deployment guidelines should include security-related instructions.

All the default credentials, default certificates and security sensitive information such as ports being opened should be properly documented.

Deployments

All WSO2 deployments should follow security hardening guidelines and production deployment guidelines in security sensitive environments.

Production and staging environments should be configured identically. Configuration, as well as artifact deployment between these environments, should be automated and should follow a proper change management process to make sure no configuration changes are done in production environments without proper security evaluation.

External components of the deployment such as the operation system and runtime environment should be updated regularly and must be updated when relevant "security updates" are released.

Default credentials, default certificates, and any security sensitive default values should not be used in production environments (as recommended in security hardening guidelines and production deployment guidelines).

2.7 A7 - 2017 - Cross-Site Scripting (XSS)

Cross-Site Scripting allows an attacker to execute malicious code (scripts) against the web browser of the user. By leveraging this attack, an attacker could attempt to carry-out other forms of attacks such as stealing session cookies to perform Session Hijacking or stealing token values to conduct CSRF Attacks, launch a phishing attack etc33.

2.7.1.1 Prevention Techniques

There are three recommended best practices that need to be followed in order to prevent XSS threats:

Input validation

User inputs should be validated whenever possible and only characters that are relevant to the particular field should be accepted. Input validation should be done on the server-side to prevent any bypass attempts, even though additional front-end validation can be done to increase user experience.

However, in WSO2 Carbon 4 based products, input validation is given a lower priority and is only done in essential screens. Therefore, it is a must to use proper output encoding and output sanitization techniques.

Output Encoding

Proper output encoding should be applied, where output consists of user input that is not expected to include HTML content.

Example: User input is the API description. The user might have to add some special characters in the description. However, the application is not expecting any HTML syntax in the description.

In the example scenario, output encoding will convert special characters to respective HTML character entity references34.

Output Sanitization

Proper output sanitization should be applied, where output consists of user input that is expected to include HTML content.

Example: User input is the contents of API documentation, which is expected to have some basic HTML syntax used to in formatting.

In the example scenario, output sanitization will disallow the user from adding HTML tags that could introduce a potential threat such as <script> and from using HTML event related attributes.

Browser Level Protection

Modern browsers have built-in XSS prevention mechanisms. However, certain browsers require explicitly enabling these mechanisms using special response headers. "X-XSS-Protection: 1; mode=block" header should be set in HTTP responses to make sure browser level protection is enabled in all supported browsers.

For additional details on HTTP security related headers, refer to "Security Related HTTP Headers" section.

However, this is not a permanent or justifiable solution for XSS. Instead, browser level protection should only be considered as an additional protection mechanism.

2.7.1.2 Java Specific Recommendations

Output Encoding

OWASP Java Encoder35 should be used to perform output encoding. OWASP Java Encoder is capable of performing contextual encoding. Following are the contexts and relevant examples that should be used:

Encode within HTML content

Example Incorrect Usage:
<tr>
<td width="30%"><fmt:message key='workflow.impl.name'/></td>
<td><%=variableWithDynamicText%></td>
</tr>

Example Correct Usage:
<tr>
<td width="30%"><fmt:message key='workflow.impl.name'/></td>
<td> <%=Encode.forHtml(variableWithDynamicText)%></td>
</tr>

Encode Attributes used in JavaScript

Example Incorrect Usage:
<a title="Title" onclick="jsMethod(' <%=variableWithDynamicText%>')">Link Text</a>

Example Correct Usage:
<a title="Title" onclick="jsMethod('<%=Encode.forJavaScript(variableWithDynamicText)%>')">Link Text</a>

Encode Variables in Javascript Blocks

Example Incorrect Usage:
<script type="text/javascript">
//Some JS logic here
vat x = <%= variableWithDynamicText %> ;
//Some JS logic here
</script>

Example Correct Usage:
<script type="text/javascript">
//Some JS logic here
vat x = <%= Encode.forJavaScript(variableWithDynamicText)%> ;
//Some JS logic here
</script>

Encode with URLs

Example Incorrect Usage:
<a title="Title" href="<%=variableWithDynamicText%>">Link Text</a>

Example Correct Usage:
<a title="Title" href="<%=Encode.forUri(variableWithDynamicText)%>">Link Text</a>

Output Sanitization

OWASP Java HTML Sanitizer36 should be used to perform output sanitization. OWASP Java HTML Sanitizer can be used to allow only certain set of HTML elements in a user input. In addition, it is possible to define allowed attributes and properties of attributes, relevant to an enabled element.

It is recommended to limit to pre-packaged FORMATTING sanitizer policy37. However, if user should be allowed to use images, tables or links, other pre-packaged sanitizer policies can be used.

Alert - Approval Required: If a custom policy or a custom rule is defined other than the pre-packaged sanitizer policies, custom policy should be reviewed and approved by Platform Security Team. Therefore, before the release of component with custom sanitizer policies or rules, Platform Security Team should be notified, and use case, as well as rules, should be reviewed.

Example Incorrect Usage:
<tr>
<td width="30%"><fmt:message key='workflow.impl.name'/></td>

<td><%=variableWithDynamicHtmlContent%></td>
</tr>

Example Correct Usage:
<tr>
<td width="30%"><fmt:message key='workflow.impl.name'/></td>
<% PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS); %>
<td><%=policy.sanitize(variableWithDynamicHtmlContent)%></td>

</tr>

Browser Level Protection

"org.apache.catalina.filters.HttpHeaderSecurityFilter" Servlet Filter should be used to add X-XSS-Protection header to the HTTP response.

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Engineering Guidelines - Security Related HTTP Headers".

2.7.1.3 JavaScript Specific Recommendations

Output Encoding

When adding content into HTML document using client-side script (such as JavaScript), avoid inserting HTML content directly into the document. Avoid .html(), .innerHTML, and other related functions.

Example Incorrect Usage:
document.getElementById('example-div').innerHtml = dynamicText;

Example Incorrect Usage:
jQuery( '#example-div' ).html( dynamicText );
jQuery( '#example-div' ).before( dynamicText );
jQuery( '#example-div' ).after( dynamicText );
jQuery( '#example-div' ).append( dynamicText );
jQuery( '#example-div' ).prepend( dynamicText );
jQuery( dynamicText ).appendTo( '#example-div' );
jQuery( dynamicText ).prependTo( '#example-div' );

Use methods such as .text(), .textContent, for adding dynamic text content into DOM. When adding HTML content is required, programmatically create DOM nodes and append content to the newly created DOM and append the new DOM node into HTML document.

Example Correct Usage:
document.getElementById('example-div').textContent = dynamicText;

Example Correct Usage:
jQuery( '.some-div' ).text( dynamicText );

Example Correct Usage:
var text = jQuery('<div />').text( dynamicText );
jQuery( '#example-div' ).html( text.html() );

If dynamic input is used to construct a HTML attribute double quote and single quote should be additionally escaped.

Example Incorrect Usage:
var text = jQuery('<div />').text( dynamicText );
jQuery( '#example-div' ).attr("href", text.html());

Example Correct Usage:
var text = jQuery('<div />').text( dynamicText );
jQuery( '#example-div' ).attr("href", text.html().replace(/"/g, "&quot;").replace(/'/g, '&#39;') );

2.7.1.4 PHP Specific Recommendations

Output Encoding

"htmlspecialchars" function38 should be used whenever user input is printed back into a response. Mentioned function converts special characters in the input to HTML entities.

Use ENT_QUOTES flag to enable encoding both single and double quotes.

Example Incorrect Usage:
<a title="Title" href="<?php echo variableWithDynamicText ?>">Link Text</a>

Example Incorrect Usage:
<a title="Title" href="<?php echo htmlspecialchars(variableWithDynamicText)?>">Link Text</a>

Example Correct Usage:
<a title="Title" href="<?php echo htmlspecialchars(variableWithDynamicText, ENT_QUOTES)?>">Link Text</a>

Output Sanitization

HTML Purifier39 should be used to sanitize HTML content. Default HTML Purifier rules set is recommended.

Alert - Approval Required: If a custom policy or a custom rule is defined, other than the default sanitizer policy, custom policy should be reviewed and approved by Platform Security Team. Therefore, before the release of component with custom sanitizer policies or rules, Platform Security Team should be notified, and use case, as well as rules, should be reviewed.

Example Incorrect Usage:
<a title="Title" href="<?php echo htmlspecialchars(variableWithDynamicText)?>">Link Text</a>

Example Correct Usage:
<?php
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
?>
<a title="Title" href="<?php echo $purifier->purify(variableWithDynamicText, ENT_QUOTES)?>">Link Text</a>

Browser Level Protection

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Engineering Guidelines - Security Related HTTP Headers".

2.8 A8 - 2017 - Insecure Deserialization

Deserialization is the process of creating an object from binary data or text data. It is an opposite process of serialization. When serialized data is in control of an attacker, insecure deserialization flaws can enable an attacker to cause remote code execution upon deserialization or create a malicious deserialized objects that can cause remote code execution and date tampering upon usage119.

2.8.1.1 Prevention Techniques

Use language specific guidelines

Use language-specific guidelines to enumerate safe methodologies for deserializing data that can't be trusted.

Additional prevention techniques120

  • Implementing integrity checks such as digital signatures on any serialized objects to prevent hostile object creation or data tampering.
  • Log deserialization exceptions and failures, such as where the incoming type is not the expected type, or the deserialization throws exceptions.
2.8.1.2 PHP Specific Recommendations

Check the use of 'unserialize()' and review how the external parameters are accepted.Use a safe, standard data interchange format such as JSON (via json_decode() and json_encode()) if you need to pass serialized data to the user. If you need to deserialize externally-stored data, consider using hash hmac() for data validation. Make sure data is not modified by anyone but you121.

2.8.1.3 JAVA Specific Recommendations

Secure java.io.ObjectInputStream

The technique is overriding the ObjectInputStream#resolveClass() method to prevent arbitrary classes from being deserialized. This safe behavior can be wrapped by using SerialKiller. SerialKiller inspects Java classes during naming resolution and allows a combination of denylisting or allowlisting to secure the application120.

Example Usual Usage:
ObjectInputStream ois = new ObjectInputStream(untrustedInputStream);
String message = (String)ois.readObject();

In order to detect malicious payloads or allow trusted classes only, SerialKiller should be used instead of the standard java.io.ObjectInputStream122.

Example Recommended Usage:
ObjectInputStream ois = new SerialKiller(is, “/etc/serialkiller.conf”);
String message = (String) ois.readObject();

The second argument is the location of SerialKiller's configuration file. InvalidClassException exceptions should be used to gracefully handle insecure object deserialization.

Prevent Data Leakage

If there are data members of an object that should never be controlled by end users during deserialization or exposed to users during serialization, they should be declared as "transient".

For a class that is defined as Serializable, the sensitive variables should be declared as 'private transient'. For example, the variable 'name' and 'age' of the class Foo were declared as transient to avoid being serialized120.

Example Recommended Usage:
public class Foo implements Serializable
{
private transient String name;
private transient String age;
……….
……...

Prevent Deserialization of Domain Objects

If a Class is must implement Serializable only due to their hierarchy, in order to guarantee that the objects can’t be deserialized, readObject method should be declare with the final modifier120.

Example Recommended Usage:
private final void readObject(ObjectInputStream in) throws java.io.IOException{
throw new java.io.IOException(“Cannot be deserialized”);
}

Harden own java.io.ObjectInputStream

Override ObjectInputStream.html#resolveClass() to restrict which classes are allowed to be deserialized120.

A example code ensures the SampleObjectInputStream class is guaranteed not to deserialize any type other than the Foo class.

Example Recommended Usage:
public class SampleObjectInputStream extends ObjectInputStream{
Public SampleObjectInputStream(InputStream inpuStream) throws IOException{
super(inputStream);
}

@Overide
protected Class<?> resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException{
if(!osc.getName().equals(Foo.class.getName())){
throw new InvalidClassException(“Unauthorized deserialization attempt”,
osc.getName());
}
return super.resolveClass(osc);
}
}

2.9 A9 - 2017 – Using Known Vulnerable Components

Outdated components may have known vulnerabilities that are exploitable. Public databases such as NVD53 and ExploitDB54 offer information on known vulnerabilities and exploits available.

2.9.1 Introducing New External Dependencies

When introducing new external dependency components, use the most up-to-date version of the component.

Selected most up-to-date version should be scanned by using OWASP Dependency Check for known vulnerabilities by following "Engineering Guidelines - External Dependency Analysis using OWASP Dependency Check".

External dependency, as well as all transitive dependencies getting added should be scanned using instructions from "OWASP Dependency Check CLI" section of the document.

WSO2 Document Reference: Further information on required changes and code-level examples are available at "Engineering Guidelines - External Dependency Analysis using OWASP Dependency Check".

Generated report should be attached with the usual "Approval Request" and the approval request should be copied to Security Leads Group email.

If most up-to-date version contains a known vulnerability, and if there is no active development happening, other alternatives should be considered, rather than using the vulnerable library.

Alert - Approval Required: Any external dependency component approval request should include OWASP Dependency Check report (or else Platform Security Team team will down vote the approval request).

Any external component with known vulnerability should not be introduced as a dependency. If there is any exceptional situation, Platform Security Team should be informed and review should be conducted on the use-case, source code, known vulnerabilities and controls in place for mitigating the impact of the vulnerability in usage path. Platform Security Team's approval is required before introducing such dependency.

2.9.2 Vulnerabilities in Current Dependencies

OWASP Dependency Check maven plugin should be integrated into the build process of latest product builds, by following "Engineering Guidelines - External Dependency Analysis using OWASP Dependency Check".

WSO2 Document Reference: Further information on required changes and code-level examples are available at "Engineering Guidelines - External Dependency Analysis using OWASP Dependency Check".

Engineers can execute Dependency Check by calling the " dependency-check:check" maven goal, in development environment. However, Jenkins will execute this task by default during the scheduled builds, to identify if any latest product build contains external dependencies with known security vulnerabilities.

When it is identified that a security vulnerability has been identified for a particular external dependency, it is recommended to do following:

  • Initiate relevant discussion at Security Leads Group mailing list with subject "Dependency Vulnerability - [DependencyName] - [DependencyVersion] - [CVE]".
  • Analyze the impact on the usage of WSO2, relevant to the particular dependency and identify if usage of WSO2 makes any product vulnerable.
    1. If yes, take necessary corrective actions to migrate to a higher version of the dependency with no known security vulnerabilities.
    2. If yes, and no new version of the dependency exists, take necessary actions to nullify the impact of the vulnerability on usage of WSO2, by introducing additional validations or security checks.

Alert - Approval Required: Platform Security Team should review any validations, additional security checks or additional security constraints added in order to nullify the impact of a known vulnerability in an external dependency when no newer version is available and no active development is happening.

  1. If no, update the mail thread with the reasoning and request approval of Platform Security Team to add relevant mitigation information into OWASP Dependency Check, suppression file relevant to the component.

Alert - Approval Required: Platform Security Team should review and merge pull-requests, adding any entries to a particular component's OWASP Dependency Check suppression file. During the review, mitigated reason, dependency source, and usage path will be reviewed. This is further explained in "Engineering Guidelines - OWASP Dependency Check".

2.10 A10 - 2017 - Insufficient logging and Monitoring

Insufficient logging and ineffective integration with security incident response systems allow attackers to pivot to other systems and maintain persistent threats for weeks or months before being detected. This leads attacker to tamper, extract or system data123.

2.10.1.1 Prevention Techniques

As per the risk of the data stored or processed by the WSO2 products124.

  • Ensure all login, access control failures, and server-side input validation failures can be logged with sufficient user context to identify suspicious or malicious accounts, and held for sufficient time to allow delayed forensic analysis.
  • Ensure that logs are generated in a format that can be easily consumed by a centralized log management solutions.
  • Ensure high-value transactions have an audit trail with integrity controls to prevent tampering or deletion, such as append-only database tables or similar.

3. OWASP Top 10 - 2013 Prevention

This section discusses OWASP Top 10 2013 list of the most critical application security risks.

Note : OWASP has updated its top 10 list of the most critical application security risks in 2017. Please refer to OWASP top 10 2017 for updated list.

3.1 A1 – Injection

Please refer to OWASP Top 10 2017 A1 - Injection

Please refer to OWASP Top 10 2017 A4 - XML External Entity (XXE)

3.2 A2 – Broken Authentication and Session Management

Please refer to OWASP Top 10 2017 A2 - Broken Authentication

3.3 A3 – Cross-Site Scripting (XSS)

Please refer to OWASP Top 10 2017 A7 - Cross-Site Scripting (XSS)

3.4 A4 – Insecure Direct Object References

Please refer to OWASP Top 10 2017 A5 - Broken Access Control

3.5 A5 – Security Misconfiguration

Please refer to OWASP Top 10 2017 A6 - Security Misconfiguration

3.6 A6 – Sensitive Data Exposure

Please refer to OWASP Top 10 2017 A3 - Sensitive Data Exposure

3.7 A7 – Missing Function Level Access Control

Please refer to OWASP Top 10 2017 A5 - Broken Access Control

3.8 A8 - Cross-Site Request Forgery (CSRF)

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. CSRF attacks specifically target state-changing requests, not theft of data, since the attacker has no way to see the response to the forged request. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state-changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application49.

3.8.1.1 Prevention Techniques

There are multiple techniques usable for preventing CSRF attacks which are further documented at Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet50.

Synchronizer Token Pattern

With Synchronizer Token Pattern, any state-changing operation requires a secure random token which is generally known as CSRF Token. CSRF Token is a unique large random string generated per user session, using a secure pseudorandom number generator.

Once user session is created, per-session CSRF Token should be added to the server session as well. Basically, the storage of CSRF Token happens in server session.

Generated CSRF Token should be added to all the forms, generating requests for state-changing operations, as a hidden input. The server should do additional validation and reject the request if the CSRF Token sent in the request does not match with the token available in the user session. In addition to forms, AJAX requests for state-changing operations should also include the CSRF Token.

Ultimately, the attacker will not be able to make a form submission to protected application, since attacker will need to know the per-session CSRF Token value in advance, to craft the attack vector.

This pattern is further discussed in "Core J2EE Patterns"51.

Example of an Incorrectly Designed HTML Form:
<form action="create_user" method="POST">
<div>Username : <input type="text" name="username"></div>
<div>Password : <input type="password" name="password"></div>
</form>

Example of a Correctly Designed HTML Form:
<form action="create_user" method="POST">
<div>Username : <input type="text" name="username"></div>
<div>Password : <input type="password" name="password"></div>
<input type="hidden" name="CSRFToken"
value="MJpTVsF0EKZGnqbYxvizCupE9AOxhKWmKdD3E6uMVean36CEENAF7Q3swB8TQT5zAERQvvt3lgq2">
</form>

Double Submit Cookie

The difference between "Double Submit Cookie" and "Synchronize Token Pattern" is that, "Synchronize Token Pattern" uses server session for storing CSRF Token, whereas "Double Submit Cookie" approach uses cookies to store the CSRF Token.

Upon user login, per-session CSRF token value should be generated and it should be sent to the browser as a cookie. The server may decide not to store the CSRF token value.

When rendering HTML pages with forms, client side JavaScript should read the CSRF Token cookie value and inject the value all forms. In addition, AJAX requests should be modified to send the same value with AJAX requests.

When an application sends an HTTP request for a state changing operation (over HTTP method other than GET), the server should compare the CSRF Token received over the request cookies, with the CSRF Token value received in request payload (query parameter/post data). If values are not matching, request can be identified as a possible CSRF attack.

If an attacker creates a forged HTTP request with the intention of performing a CSRF attack, correct CSRF Token value will still be sent in the cookie, but they will not have required cross domain access to read the token value and inject same into the HTML forms.

3.8.1.2 Java Specific Recommendations
  • WSO2 products based on WSO2 Carbon Kernel versions prior to 4.4.6 use "Referer Header" based CSRF prevention, which is no longer recommended.
  • WSO2 products based on WSO2 Carbon Kernel 4 (4.4.6+) should use "Synchronizer Token Pattern" based CSRF prevention, using OWASP CSRFGuard52.
  • WSO2 Carbon Kernel 5+ based products and any new applications should use "Double Submit Cookie" approach in CSRF prevention.

Synchronizer Token Pattern (WSO2 Carbon Kernel 4 (4.4.6+))

OWASP CSRFGuard is used to implement Synchronizer Token Pattern in WSO2 Carbon Kernel 4 (4.4.6+) products. OWASP CSRFGuard provides required classes to generate per-session token and to do necessary validation on state-changing operations. Furthermore, it provides a JavaScript which is capable of dynamically adding CSRF Token as a hidden input and override XMLHttpRequest to include CSRF Token in AJAX requests.

WSO2 Document Reference: Further information on required changes and code-level examples are available at "Engineering Guidelines - OWASP CSRF Guard" document.

In summary, when integrating OWASP CSRFGuard with a product, it is required to do following changes:

  • Make sure all the state-changing operations are performed using HTTP methods other than GET. GET requests must not be used for state-changing operations.
  • In web.xml or jaggery.conf file, add CsrfGuardServletContextListener.
    • This class is responsible for loading CSRFGuard configuration and doing the initialization of component.
  • In web.xml or jaggery.conf file, add CsrfGuardHttpSessionListener.
    • This class is responsible for generating and storing per-session CSRF Token.
  • In web.xml or jaggery.conf file, add CsrfGuardFilter.
    • This class is responsible for comparing the submitted CSRF Token with the token in user session, and generating error response if an attack was detected.
  • In web.xml or jaggery.conf file, add JavaScriptServlet.
    • This class is responsible for serving the JavaScript file that is dynamically adding the CSRF Token to forms and AJAX requests.
  • Include "JavaScriptServlet" in the HTML template of the application, so that <head> element of all pages that need to be protected, should have JavaScriptServlet as the first JavaScript inclusion.
  • Prepare and store per-application CSRF configuration file according to "repository/conf/security/Owasp.CsrfGuard.Carbon.properties" or reuse the Carbon CSRF configuration.
  • Do thorough testing on CSRF protected application to verify that there is no functional impact.

Note : CSRF is dropped in OWASP top 10 list of the most critical application security risks in 2017.

3.9 A9 – Using Known Vulnerable Components

Please refer to OWASP Top 10 2017 A9 - Using Known Vulnerable Components

3.10 A10 - Unvalidated Redirects and Forwards

Unvalidated redirects and forwards are possible when a web application accepts untrusted input that could cause the web application to redirect the request to a URL contained within untrusted input. By modifying untrusted URL input to a malicious site, an attacker may successfully launch a phishing scam and steal user credentials. Because the server name in the modified link is identical to the original site, phishing attempts may have a more trustworthy appearance. Unvalidated redirect and forward attacks can also be used to maliciously craft a URL that would pass the application's access control check and then forward the attacker to privileged functions that they would normally not be able to access55.

3.10.1.1 Prevention Techniques

Absolute forward URLs or fragments of forward URLs should not be accepted from the end-user during any operation. This is advised since an attacker can use a less restricted resource with a malicious forward, to circumvent URL based security control in place and send requests to a restricted resource.

Alert - Approval Required: If any component requires that, an absolute forward URL must be accepted from the end-user by any means (as demonstrated in OWASP Cheat Sheet56)>, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

Absolute redirect URLs should not be accepted from the end-user during any operation, apart from administrative configurations.

Alert - Approval Required: If any component requires that, an absolute redirect URL must be accepted from the end-user (not in administrative configuration), the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

The general recommendation is to avoid accepting redirect or forward URL fragments (used to build absolute or relative redirect/forward URLs) from the end-user.

However, if there is such requirement, it is necessary to follow language specific recommendations for validating the accepted URL fragment.

3.10.1.2 Java Specific Recommendations

If an absolute URL is accepted from the end-user, it should be validated against a list of allowed redirect/forward URLs. However, since this the condition explained in Approval Required blocks above, Platform Security Team should be informed on the use case and approval is required.

Example Incorrect Usage:
response.sendRedirect(request.getParameter("url"));

Example Correct Usage:
String url = request.getParameter("url");
boolean allowed = SecurityUtil.validateRedirectUrl(listOfAllowedRedirectUrls, url);
if(!allowed) {
//Required logic to show the relevant error to the end-user
return;
}
response.sendRedirect(request.getParameter("url"));

When a portion of the redirect or forward URL is expected from the user, it is a must to validate if the appended fragment contains only the expected type of a value.

Example Incorrect Usage:
response.sendRedirect(Constant.BASE_URL + "/info/" + request.getParameter("index"));

Example Correct Usage:
String index = request.getParameter("index");
if(isInteger(index)) {
response.sendRedirect(Constant.BASE_URL + "/info/" + index);
} else {
//Inform end-user about the error
}

Note: Unvalidated Redirects and Forwards is dropped in OWASP top 10 list of the most critical application security risks in 2017.

4. OWASP Mobile Top 10 Prevention

4.1 Introduction

This section discusses OWASP Mobile Top 10 prevention techniques that should be followed by WSO2 engineers while engineering mobile applications.

4.2 M1 - Improper Platform Usage

This category covers misuse of a platform feature or failure to use platform security controls. It might include Android intents, platform permissions, misuse of TouchID, the Keychain, or some other security control that is part of the mobile operating system57.

4.2.1 Prevention Techniques

The best method of preventing improper platform usage is to follow the guidelines and best practices published by the respective platforms, on secure development of the mobile applications. These guidelines include the proper way to implement the relevant features and how to maintain them. Also, make sure to check whether the application behaves as it was intended without misusing platform features.

4.2.1.1 Android Specific Recommendations

Using Intents

Intents are used to request an action such as starting an activity, starting a service or delivering a broadcast from another app component. Explicit intents specify the component by the fully qualified class name. Usually, these are used to start a component within the app. Implicit intents declare a general action to be handled by another application.

Do not use an implicit intent to start a service as implicit intents allow any other app component to respond to the intent and start the Service transparently to the user. Use an explicit intent where the component can be specified using the fully qualified class name.

Note: From Android 5.0 (API level 21) onwards, the system will throw an exception if an implicit intent is used to start a service.

Set the android:exported attribute to false for the specific activity, service or receiver to limit the exposure to other components.

Example: A Service can be declared in the App Manifest with the android:exported attribute set to false as follows
<service
android:exported="false"
>
. . .
</service>

Alert - Approval Required: If any component requires that, android:exported attribute to be set to true, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

Data received by public components should be treated as untrusted data and needs to be properly validated and sanitized before usage.

Example: An email address received from a public component must be verified against the email address specifications defined by RFC282258.

4.3 M2 - Insecure Data Storage

This category covers insecure data storage and unintended data leakage57.

4.3.1 Prevention Techniques

4.3.1.1 Client-side data storage

Data stored in the mobile device have a risk of being exposed to an outside side attacker through a malware or a lost/stolen device. To reduce the impact of an attack, limit the amount of data stored in a mobile device and use a strong encryption algorithm to encrypt the stored data.

Android Specific Recommendations

Using internal storage

Do not create files with permissions MODE_WORLD_WRITEABLE59 or MODE_WORLD_READABLE60 as all applications will have permission to read or write to the file.Use a content provider61 to allow other applications to securely access and modify data.

Note: Constants MODE_WORLD_WRITEABLE and MODE_WORLD_READABLE were deprecated in API level 17

Using external storage

Files stored in the external storage has global read and write permissions. Therefore external storage should not be used to store any sensitive data. Also, input validations should be applied when using data from the external storage.

It is not recommended to store executable files in the external storage. If the application requires loading executable files from external storage, make sure to sign and cryptographically verify the content before dynamic loading.

Database Related Recommendations

Using a third party encryption can withstand a threat to the native protection provided by the OS. The master key for the encryption should be randomly generated and encrypted using a passphrase from the user by the time the data is processed. Unencrypted master key or the passphrase should not be stored on the device.

Example: SQLCipher is an open source extension to SQLite that provides transparent 256-bit AES encryption of database files62.

4.3.1.2 HTTP response caching

HTTP responses can have sensitive information. Caching them can increase the risk of data leakage. Therefore response caching should be disabled for sensitive data.

Example: API responses can contain sensitive information such as bank account details that should not be cached.

Android Specific Recommendations

Do not use HttpResponseCache63 to cache sensitive data.

4.3.1.3 Keyboard press caching

Mobile devices cache the keyboard input to be used in auto-suggesting words to the user. This feature can be a vulnerability when sensitive information of one user is cached and later suggests to a different user. Therefore auto suggest feature must be disabled to avoid keyboard press caching for sensitive information.

Android Specific Recommendations

The user dictionary in android saves the words entered by the user to be used for auto-correction. Since this dictionary is available to other applications without permission, sensitive information can get leaked to other apps. To prevent this, use android:inputType= “textNoSuggestions” for sensitive data fields or create custom keyboards with auto-suggest disabled.

4.3.1.4 Copy/Paste buffer caching

When using copy and paste, the data is initially copied into a clipboard. Malicious applications have the ability to access this clipboard cache to extract sensitive data. Disable the copy/paste functionality for sensitive data fields to prevent these type of copy/paste buffer caching.

Example: Application should not allow users to copy/paste credit card details.

4.3.1.5 Logging

Debug logs are used to identify flaws in the application. However, information provided by debug logs can be useful for an attacker to gather knowledge about the application. Therefore debug logs should be disabled in the production environment.

Android Specific Recommendations

Logs are a shared resource for Android. Any application with READ_LOGS permission can view them. Production applications should limit the logging by using debug flags and configure logging levels by defining custom log classes.

4.3.1.6 HTML5 local storage

HTML5 local storage can be used to store data within the browser between HTTP requests. Since this storage is accessible by JavaScript, cross-site scripting attacks can be used to steal the data. Therefore sensitive data should not be stored in HTML5 local storage.

4.3.1.7 Browser Cookie objects

Cookies are used by servers to store data in the browser. Often session related data are stored inside cookies. Use Secure flag to indicate that only HTTPS requests are allowed to transfer cookies and HTTP Only flag to make cookies inaccessible to JavaScript's Document.cookie API. Make sure that both Secure and HTTP Only flags are set to cookies containing sensitive data.

4.3.1.8 Analytics data sent to 3rd parties

Mobile applications may need to have access to user’s personal information for functionality purposes. However, the application should make sure that these sensitive pieces of information are not being sent to third parties violating the privacy of the user.

Example: Mobile applications send data to Google Analytics and Facebook Graph API for analytical purposes.

4.4 M3 - Insecure Communication

This section covers poor handshaking, incorrect SSL versions, weak negotiation, cleartext communication of sensitive assets, etc57.

4.4.1 Prevention Techniques

4.4.1.1 SSL/TLS

Use TLS to serve all sensitive and nonsensitive traffic. This will prevent from having mixed SSL sessions where the user’s session ID might get exposed.

Android Specific Recommendations

The application can choose to avoid unencrypted HTTP traffic by using cleartextTrafficPermitted="false" in the network security config file64.

Example: To enforce HTTPS on all connections to wso2.com use the following code in the network_security_config.xml

<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">wso2.com</domain>
</domain-config>
</network-security-config>

4.4.1.2 Self Signed Certificates

Usually, self-signed certificates are used in the development stage for the easiness of the developer. However, do not accept self-signed certificates in the production application as they allow an attacker to easily intercept the communication using their own self-signed certificate.

4.4.1.3 Certificate Pinning

The application accepts all the certificates signed by trusted Certificate Authorities(CAs). If one of these trusted CA gets compromised and started issuing fraudulent certificates, they will be accepted by the application. Certificate pinning can be used store the certificate locally along with the domain name. This allows detecting fraudulent certificates as the application can compare previously stored certificate with the new one.

Android Specific Recommendations

Example: To use certificate pinning on wso2.com use the following code in the network_security_config.xml. Here, base64 encoded Subject Public Key Information of the wso2 certificate should be used as the pin.

<network-security-config>
<domain-config>
<domain includeSubdomains="true">wso2.com</domain>
<pin-set expiration="2020-01-01">
<pin digest="SHA-256">2pCcYrG90hDFxwOCsVya7wpbQjqhBy3OPsFyyT+7108=</pin>
</pin-set>
</domain-config>
</network-security-config>

Note: Always include a backup pin to use in an event of a certificate change.

Note: To protect from compromised CAs android has the ability to denylist certain certificates or even whole CAs. While this list was historically built into the operating system, starting in Android 4.2 this list can be remotely updated to deal with future compromises65.

4.4.1.4 Hostname Verification

Hostname verification is verifying whether the hostname of the server that the application is trying to connect is specified in the certificate presented by the server. It is important to have this verification as this will make sure that the server has presented the right certificate.

Android Specific Recommendations

SSLSocket66 does not perform hostname verification. The application has to verify the hostname of the certificate by calling the method getDefaultHostnameVerifier() with the expected hostname.

Using org.apache.http.conn.ssl.AllowAllHostnameVerifier or SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER allows the application to accept all certificates. Make sure that these are not being used in the production code.

Note: org.apache.http.conn.ssl.AllowAllHostnameVerifier and SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER were deprecated in API level 22.

4.4.1.5 SMS

SMS is a protocol that has been designed for user to user communication. It is unencrypted and not properly authenticated. Therefore, do not use SMS for sensitive data transfer.

Android Specific Recommendations

In Android, SMS messages are transmitted as broadcast intents. Anyone with the READ_SMS permission can read the SMS messages on the device. Therefore, do not use SMS for data transfer.

4.5 M4 - Insecure Authentication

This category captures notions of authenticating the end user or bad session management.This can include:

  • Failing to identify the user at all when that should be required
  • Failure to maintain the user's identity when it is required
  • Weaknesses in session management57

4.5.1 Prevention Techniques

4.5.1.1 Local Authentication

Local Authentication can be bypassed if the attacker has the ability to tamper the application. Therefore all the authentication checks should be performed by a backend server.

Alert - Approval Required: If any component requires implementing local authentication, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

4.5.1.2 Password Policy

Ensure that a strong password policy is enforced by the authentication server. Use a similar strong password policy if the authentication is performed locally with the approval mentioned in the Local Authentication section.

4.5.1.3 Device Identifiers

Do not use device-specific identifiers for authentication. In an event of change of ownership of the phone, these IDs can expose previous owner’s data to the new owner.

4.5.1.4 Geo-Location

Geo-location should not be used as an authentication mechanism as attackers can easily spoof the geo-location. If an application requires the use of geo-location, ensure that the application has implemented proper geo-location spoof detection mechanism to detect location anomalies.

4.5.1.5 Token Revocation

In the event of a lost or stolen device, the application should have the ability to invalidate the authenticated session on the lost/stolen device by revoking a device-specific token.

4.6 M5 - Insufficient Cryptography

The code applies cryptography to a sensitive information asset. However, the cryptography is insufficient in some way. Note that anything and everything related to TLS or SSL goes in M3. Also, if the app fails to use cryptography at all when it should, that probably belongs in M2. This category is for issues where cryptography was attempted, but it wasn't done correctly57.

4.6.1 Prevention Techniques

4.6.1.1 Key Generation

Use a secure random number generator to generate strong keys that can withstand brute force attacks.

Android Specific Recommendations

Use the secure random number generator, SecureRandom67 to initialize any cryptographic keys generated by KeyGenerator68. Use of a key that is not generated with a secure random number generator significantly weakens the strength of the algorithm and may allow offline attacks.

4.6.1.2 Key Storage

Do not store keys in plaintext format. Use a cryptographic vault for secure storage of keys and make sure that compromised or outdated keys are properly revoked.

Android Specific Recommendations

Use the KeyStore69 for long-term storage and retrieval of cryptographic keys.

4.6.1.3 Custom Encryption Algorithms

Do not implement custom encryption algorithms. Use a proper algorithm that is widely used and accepted as secure.

Android Specific Recommendations

Do not write custom protocols for implementing secure tunnels. Instead use HttpsURLConnection70 or SSLSocket66. If a custom protocol is needed, do not implement new algorithms. Instead, use existing cryptographic algorithms such as the implementations of AES and RSA provided in the Cipher71 class.

4.6.1.4 Deprecated Algorithms

OWASP defines following algorithms as deprecated and not to be used for encryption purposes72.

  • RC2
  • MD4
  • MD5
  • SHA1

4.7 M6 - Insecure Authorization

This is a category to capture any failures in the authorization. It is distinct from authentication issues. If the app does not authenticate users at all in a situation where it should, then that is an authentication failure, not an authorization failure57.

4.7.1 Prevention Techniques

4.7.1.1 Permissions

Do not use roles and permission information coming from the mobile device for authorization. Backend code should independently verify that any incoming identifiers associated with a request (operands of a requested operation) that come along with the identify match up and belong to the incoming identity.

It is a must to request only the minimum number of permissions that your app requests, to reduce the risk of misusing permissions. In application documentation, it is required to mention the actual usage of each permission, so that users and security reviewers have access to this information.

Android Specific Recommendations

In Android, permissions are categorized into four protection levels73.

normal

The default value. A lower-risk permission that gives requesting applications access to isolated application-level features, with minimal risk to other applications, the system, or the user. The system automatically grants this type of permission to a requesting application at installation, without asking for the user's explicit approval (though the user always has the option to review these permissions before installing).

dangerous

A higher-risk permission that would give a requesting application access to private user data or control over the device that can negatively impact the user. Because this type of permission introduces potential risk, the system may not automatically grant it to the requesting application. For example, any dangerous permissions requested by an application may be displayed to the user and require confirmation before proceeding, or some other approach may be taken to avoid the user automatically allowing the use of such facilities.

signature

A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user's explicit approval.

signatureOrSystem

A permission that the system grants only to applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission.The "signatureOrSystem" permission is used for certain special situations where multiple vendors have applications built into a system image and need to share specific features explicitly because they are being built together.

When defining new permissions, use the dangerous protection level if the permission has the ability to access the stored data or affect the operation of other applications. Use the signature protection level if the permission has the ability to share data between applications signed with the same certificate.

When exposing data over Interprocess Communication(IPC), check the permissions of the data that are being exposed. Other applications might not have the same level of permission for the exposed data.

4.7.1.2 Proof Key for Code Exchange (PKCE)

Using OAuth 2.0 authorization code grant type is susceptible to interception attacks. An attacker has the ability to intercept the authorization code received from the authorization endpoint via an unprotected communication such as inter-application communication within the client’s operating system. Proof Key for Code Exchange (PKCE)74 is used to mitigate this vulnerability. In PKCE,

  1. A unique cryptographic random key (code verifier) is created by the application with every authorization request.
  2. The code verifier is transformed into a code challenge and sent to the authorization server along with the transform method.
  3. The authorization server stores the code challenge and the transform method.
  4. During the request for an access token, the application has to send it’s generated code verifier to the authorization server.
  5. The server transforms the received code verifier with the stored transform method and compares with the previously stored code challenge.

4.8 M7 - Poor Code Quality

This would be the catch-all for code-level implementation problems in the mobile client. That's distinct from server-side coding mistakes. This would capture things like buffer overflows, format string vulnerabilities, and various other code-level mistakes where the solution is to rewrite some code that's running on the mobile device57.

4.8.1 Prevention Techniques

4.8.1.1 Input Validation

All the input from the app and user should be treated as untrusted data. Therefore, input validation must be used when handling such data.

Android Specific Recommendations

When accessing a content provider, use parameterized query methods such as query(), update(), and delete() to prevent from potential SQL injection from untrusted sources.

If the content provider is serving files based on filename, make sure that path traversals are filtered out.

4.8.1.2 Third Party Libraries

Applications rely heavily on third-party libraries. Making the application secure won’t be enough if the third party libraries contain vulnerabilities. Therefore, security auditing must thoroughly test third-party libraries for vulnerabilities.

4.8.1.3 Buffer Overflows

Buffer overflows are not possible in Java. However, the application is susceptible to buffer overflows if it contains native code such as C or C++. To avoid buffer overflows, make sure that length of the incoming buffer data will not exceed the length of the target buffer.

Android Specific Recommendations

Run Android Lint75 on the application code using Android SDK and correct any identified issues.

4.9 M8 - Code Tampering

This category covers binary patching, local resource modification, method hooking, method swizzling, and dynamic memory modification.

Once the application is delivered to the mobile device, the code and data resources are resident there. An attacker can either directly modify the code, change the contents of memory dynamically, change or replace the system APIs that the application uses, or modify the application's data and resources. This can provide the attacker a direct method of subverting the intended use of the software for personal or monetary gain57.

4.9.1 Prevention Techniques

4.9.1.1 Tamper Detection

Use tamper detection techniques such as checksums or digital signatures to identify code tampering.

In an event of code tampering use an appropriate mechanism such as wipe the user data or send a notification to the server to protect the sensitive data.

4.9.1.2 Restricting Debuggers

Prevent the operating system from permitting to attach a debugger to the application. This will increase the complexity of an attack76.

Android Specific Recommendations

Set the android:debuggable=”false” in the application manifest to restrict the debuggers.

4.9.1.3 Stripping Binaries

Strip the native binaries to increase the difficulty for an attacker to debug or reverse engineer.

4.10 M9 - Reverse Engineering

This category includes analysis of the final core binary to determine its source code, libraries, algorithms, and other assets. Binary inspection tools give the attacker insight into the inner workings of the application. This may be used to exploit other nascent vulnerabilities in the application, as well as revealing information about back-end servers, cryptographic constants and ciphers, and intellectual property57.

4.10.1 Prevention Techniques

4.10.1.1 Obfuscation

Use an obfuscation tool to modify the code to become difficult to understand if the application gets decompiled.To measure the effectiveness of the obfuscator, use a deobfuscator.

Example: Hex Rays and Hopper are popular deobfuscators that are used in reverse engineering applications.

Android Specific Recommendations

ProGuard77 is a Java class file shrinker, optimizer, obfuscator, and preverifier. The obfuscation step in ProGuard renames the remaining classes, fields, and methods using short meaningless names making it difficult for attackers to reverse engineer.

4.10.1.2 Hide Application Logic

In an event of reverse engineering, the attacker might get hold of the source code containing all the application logic. To reduce the impact critical parts of the application logic can be moved to a web service.

4.10.1.3 Use C/C++

Java is easier to decompile when compared to C/C++. Use C/C++ to write security sensitive sections of the code to make reverse engineering difficult for an attacker.

4.11 M10 - Extraneous Functionality

Often, developers include hidden backdoor functionality or other internal development security controls that are not intended to be released into a production environment. For example, a developer may accidentally include a password as a comment in a hybrid app. Another example includes disabling of 2-factor authentication during testing57.

4.11.1 Prevention Techniques

  • Examine the app's configuration settings to discover any hidden switches.
  • Verify that all test code is not included in the final production build of the app.
  • Examine all API endpoints accessed by the mobile app to verify that these endpoints are well documented and publicly available.
  • Examine all log statements to ensure nothing overly descriptive about the backend is being written to the logs78.

5. General Recommendations for Secure Coding

5.1 Server Side Request Forgery (SSRF) Prevention

By providing URLs to unexpected hosts or ports, attackers can make it appear that the server is sending the request, possibly bypassing access controls such as firewalls that prevent the attackers from accessing the URLs directly. The server can be used as a proxy to conduct port scanning of hosts in internal networks, use other URLs such as that can access documents on the system (using file://), or use other protocols such as gopher:// or tftp://, which may provide greater control over the contents of requests79.

This is identified as a high severity attack because it allows an attacker to perform tasks which are usually prevented by the perimeter security devices such as firewalls. For example, an attacker would be able to appear to internal and external nodes as the vulnerable host and perform following:

  • Scan a network segment which is behind a firewall by analyzing responses received from the vulnerable host.
  • Perform a service enumerate attack by enumerating through services that are running on a particular host.
  • Bypass host based restrictions, policies or authentication mechanisms in place.
  • Query and attack internal hosts that are not normally accessible.

In detail explanations and analysis on SSRF can be found at SSRF Bible Cheatsheet80.

5.1.1.1 Prevention Techniques

Avoid Using User Inputs in Backend Requests

Avoid accepting information used in internal requests such as following from the user:

  • URLs used in back channel operations (backend calls made, where WSO2 product acts as the client).
  • IP addresses used in internal or back channel operations.
  • Unvalidated and unrestricted system paths used in internal file access.
  • Unvalidated XML payloads that are passed to XML parsers without proper security attributes set.

Perform Strict Error Handling

Display minimum information on the client side at event of an error or something unexpected occurs. For example, if content type validation failed, provide a generic error message such as "Invalid Data Retrieved". Also, ensure that the error message is same when the request fails in the backend and if invalid data is retrieved. This will make it hard to distinguish between open and closed ports or services.

Perform Strict Response Handling

Validate responses received from the remote resource. If a certain content type is expected by the application, validate the received response at the server-side before displaying it on client's side or processing it for the client.

5.1.1.2 Java Specific Recommendations

Proper Usage of Java Security Manager

Java Security Manager should be enabled in any production deployment and any other deployment that requires additional security (such as environments used for security related testing).

Steps relevant to enabling Java Security Manager is explained in "Enabling Java Security Manager" section of the "Administration Guide"81. Security policy file should be used to only allow network level connections to trusted and pre-identified hosts or subnets, using SocketPermission82.

Example Policy File:
grant signedBy "wso2carbon" {
// Other policies
permission java.net.SocketPermission "internal.example.com:1234", "connect, accept";
};

5.2 ClickJacking and Cross Frame Scripting Prevention

Clickjacking, also known as a "UI redress attack", is when an attacker uses multiple transparent or opaque layers to trick a user into clicking on a button or a link on another page when they were intending to click on the top level page. Thus, the attacker is "hijacking" clicks meant for their page and routing them to another page, most likely owned by another application, domain, or both83.

Cross-Frame Scripting (XFS) is an attack that combines malicious JavaScript with an iframe that loads a legitimate page in an effort to steal data from an unsuspecting user. This attack is usually only successful when combined with social engineering. An example would consist of an attacker convincing the user to navigate to a web page the attacker controls. The attacker's page then loads malicious JavaScript and an HTML iframe pointing to a legitimate site. Once the user enters credentials into the legitimate site within the iframe, the malicious JavaScript steals the keystrokes84.

5.2.1.1 Prevention Techniques

X-Frame-Options

X-Frame-Options HTTP response header should be used to indicate that the browser should not allow rendering relevant response in a <frame> or <iframe>. "X-Frame-Options: DENY" should be used in all the cases, except in situations where the product itself needs to frame a page exposed elsewhere in the same product. In a situation where product itself needs to frame a page exposed elsewhere in the same product, "X-Frame-Options: SAMEORIGIN" can be used.

Content-Security-Policy

In addition to non-standard X-Frame-Options header, the standard frame-ancestors directive can be used in a Content-Security-Policy HTTP response header to indicate whether or not a browser should be allowed to render a page in a <frame> or <iframe>. "Content-Security-Policy: frame-ancestors 'none'" should be used in all cases, except in situations where the product itself needs to frame a page exposed elsewhere in the same product. In a situation where product itself needs to frame a page exposed elsewhere in the same product, "Content-Security-Policy: frame-ancestors 'self'" can be used.

Alert - Approval Required: If any component requires that, framing of the page should be allowed globally, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

5.2.1.2 Java Specific Recommendations

X-Frame-Options

"org.apache.catalina.filters.HttpHeaderSecurityFilter" Servlet Filter should be used to add X-Frame-Options header to the HTTP response.

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Engineering Guidelines - Security Related HTTP Headers".

5.3 Random Number Generation

When an undesirably low amount of entropy is available, Pseudo Random Number Generators are susceptible to suffer from insufficient entropy when they are initialized, because entropy data may not be available to them yet85. This will leave patterns or clusters of values that are more likely to occur than others86.

5.3.1.1 Java Specific Recommendations

Avoid usage of java.util.Random class for security sensitive operations and use java.security.SecureRandom.

  • Periodically throw away the existing java.security.SecureRandom instance and create a new one. This will generate a new instance with a new seed.
  • Periodically add new random material to the PRNG seed by making a call to java.security.SecureRandom.setSeed(java.security.SecureRandom.generateSeed(int)).87
  • SecureRandom.getInstanceStrong() introduced with Java 8 should not be used in web applications, since application gets blocked until PRNG could collect required amount of entropy. This could affect Docker containers badly, since when instance spawning happens, entropy gathering will take significant amount of time88,89.

Example Incorrect Usage:
int randomPasswordPrefix = new Random().nextInt(9999);

Example Correct Usage:43
//...
int randomPasswordPrefix;
try {
SecureRandom secureRandom = SecurityUtil.getSecureRandom();
randomPasswordPrefix = secureRandom.nextInt(9999);
} catch (NoSuchAlgorithmException e) {
//Exception handling
}
//...

private class SecurityUtil {
//......

private static SecureRandom secureRandom = null;
private static int secureRandomUsageCount = 0;
private static final int SECURE_RANDOM_ROTATION_LIMIT = 1000;

private static SecureRandom getSecureRandom() {
if(secureRandomUsageCount > SECURE_RANDOM_ROTATION_LIMIT)
synchronized (SecurityUtil.class) {
if(secureRandomUsageCount > SECURE_RANDOM_ROTATION_LIMIT) {
secureRandom = null;
}
}
}
if(secureRandom == null) {
synchronized (SecurityUtil.class) {
if(secureRandom == null) {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
}
}
}
secureRandomUsageCount++;
return secureRandom;
}
}

5.4 Cross-Origin Resource Sharing

A wildcard same-origin policy is appropriate when a page or API response is considered completely public content and it is intended to be accessible to everyone, including any code on any site.

"Access-Control-Allow-Origin: *" should not be used in WSO2 products. If such option should be available, user/admin should have a way to configure between using wildcard and using domain restriction.

Alert - Approval Required: If any component requires that, framing of the page should be allowed globally, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

5.5 Security Related HTTP Headers

There are HTTP response headers that can be used to configure the security controls enforced by browsers.

WSO2 Document Reference: Further information on required changes and recommended configuration for WSO2 products as well as production deployments are available at "Engineering Guidelines - Security Related HTTP Headers".

5.6 Securing Cookies

Sensitive cookies such as JSESSIONID should be secured to avoid stealing the cookies from an insecure network or with the use of an XSS vulnerability of the application.

5.6.1 Avoiding sending of cookies over insecure (unencrypted) networks

By setting "secure" attribute of the cookie, it is possible to instruct the browser not to send the cookie over insecure networks (not to send the cookie unless HTTPS is used).

Alert - Approval Required: If any component requires that, "secure" attribute of the cookie should not be set for a sensitive cookie, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

Example Correct Usage:
cookie.setSecure(true);

5.6.2 Avoiding cookies being read by JavaScript and other client side scripts

If an XSS vulnerability is present in the web application a malicious JavaScript would be able to read sensitive information stored in cookies and communicate those to an external party.

An attacker could leverage this pattern to use an XSS vulnerability to read the session cookie from the victim's browser and conduct session hijacking attack.

To prevent JavaScripts and other client-side scripts from access cookie values, "HttpOnly" attribute should be set on the cookie.

Alert - Approval Required: If any component requires that, "HttpOnly" attribute of the cookie should not be set for a sensitive cookie, the use-case, as well as controls in place to provide required protection, must be reviewed and approved by Platform Security Team, before proceeding with the release of such component.

Example of Setting HttpOnly Flag with Java
cookie.setHttpOnly(true);

5.6.3 Summary of Recommendations

All cookies containing sensitive information should:

  • Include "secure" attribute
  • Include "HttpOnly" attribute
  • Include "path" attribute and the "path" attribute should contain accurate context information
  • Not include "expires" attribute (cookie should be a session cookie)

5.7 ZIP Slip Vulnerability Prevention

Zip Slip is a critical directory traversal security vulnerability that can be exploited when extracting files from an archive125. To exploit this vulnerability an attacker can create a malicious archive that holds directory traversal file names (e.g. ../../../../evil.sh). Exploitation of the said vulnerability could lead to overwriting executable files outside the target folder where the archived files are being extracted, thus causing the possibility of remote command execution.

This vulnerability can also be used to overwrite configuration files and other sensitive resources. The Snyk Security team is maintaining a GitHub repository126 with all projects that have been found vulnerable to Zip Slip and have been responsibly disclosed to, including fix dates and versions.

5.7.1 Java Specific Recommendations

When using the java.util.zip library, the name of the file that is being extracted needs to be validated before storing.

Example Incorrect Usage:125
Enumeration<ZipEntry> entries = zip.getEntries();
while(entries.hasMoreElements()){
ZipEntry e = entries.nextElement();
File f = new File(destinationDir, e.getName());
InputStream input = zip.getInputStream(e);
IOUtils.copy(input, write(f));
}

Example Correct Usage:
String canonicalDestinationDirPath = destinationDir.getCanonicalPath();
File destinationfile = new File(destinationDir, e.getName());
String canonicalDestinationFile = destinationfile.getCanonicalPath();
if (!canonicalDestinationFile.startsWith(canonicalDestinationDirPath + File.separator)) {
throw new ArchiverException("Entry is outside of the target dir: " + e.getName());
}

When using a library other than java.util.zip, refer the Snyk Security team’s GitHub repository126 for a fixed higher version.

Alert - Approval Required: Libraries not mentioned in the Snyk Security team’s GitHub repository126, or unable to find a fixed version, must be reviewed and approved by Platform Security Team.

6. Tooling Recommendations for Secure Coding

6.1 Security Related Dynamic Analysis

OWASP Zed Attack Proxy90 (ZAP) is the recommended tool for performing dynamic security analysis.

WSO2 Document Reference: Further information on using OWASP Zed Attack Proxy (ZAP) with WSO2 recommended security policies are available at "Engineering Guidelines - Tooling - Dynamic Analysis with OWASP ZAP" document.

6.2 Security Related Static Code Analysis

Find Security Bugs 91, FindBugs plugin is the recommended tool for performing static security analysis.

WSO2 Document Reference: Further information on using OWASP Zed Attack Proxy (ZAP) with WSO2 recommended security policies are available at "Engineering Guidelines - Tooling - Static Code Analysis using FindSecurityBugs" document.

6.3 Dependency Vulnerability Analysis

OWASP Dependency Check92 is the recommended tool for performing dependency vulnerability analysis.

WSO2 Document Reference: Further information on using OWASP Dependency Check is documented at "Engineering Guidelines - External Dependency Analysis using OWASP Dependency Check" document.

B. WSO2 Engineering Guidelines - Security Related HTTP Headers

Version: 1.1 | Date: April 7, 2017

Revision History

Version Release Date Contributors / Authors Summary of Changes
1.0 May 26, 2016 Ayoma Wijethunga Initial version
1.1 April 7, 2017 Ayoma Wijethunga Formatting changes

1. Introduction

1.1 Mandatory Headers

Below list consists of standard and non-standard security related HTTP headers, that must be enabled in order to enhance security aspects of web applications:

X-XSS-Protection: 1; mode=block
Enables reflected XSS protection in supported web browsers93.

X-Content-Type-Options: nosniff
Disable mime sniffing, which can result reflected or stored XSS in certain browsers94.

1.2 Configurable Headers

In addition, following security headers should be configured according to requirement of the application and they can be customized based on URL pattern:

X-Frame-Options: DENY
Disable embedding web application in iframes or frames95.

X-Frame-Options: SAMEORIGIN
Allow embedding web application in iframes or frames, only within same origin95.

1.3 Production Recommandations

Production or staging deployments (with CA signed certificates) should enable following headers for additional security:

Strict-Transport-Security: max-age=15768000; includeSubDomains
Prevent any communication over HTTP, since the time last response was received with
the aforementioned header, up-to duration defined in max-age96.

Security headers that need to be set with external filter (based on customer and security needs) or that should be incorporated into Tomcat filter in future release includes following:

Public-Key-Pins: pin-sha256="<sha256>"; pin-sha256="<sha256>"; max-age=15768000; includeSubDomains
Instructs web client to associate a specific cryptographic public key with a certain
web server to prevent MITM attacks with forged certificates97.

Content-Security-Policy:
Allow declaring what dynamic resources are allowed to load to serve current
response98,99. Replaces X-Fame-Options and X-XSS-Protection, non-standard headers with
standardized headers. For additional detail refer to Content-Security-Policy.com99.

2. Securing Java Web Applications

2.1 Recommended Default Configuration

Recommended web.xml filter mapping for development environments is as follows (WSO2 products should be released with this default configuration):

<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>

2.2 Recommandation Production Configuration

Recommended web.xml filter mapping for production environments is as follows:

<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsMaxAgeSeconds</param-name>
<param-value>15768000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>

2.3 Customized Configuration

It is possible to use filter mappings to cater product level customizations required. For example in order to enable X-Frame-Options only for particular URLs, below configuration can be used:

<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<!-- Disable sending X-Frame-Options with all responses-->
<init-param>
<param-name>antiClickJackingEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>

<filter>
<filter-name>HttpHeaderSecurityFilter_AntiClickJacking</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<!-- Disable other headers except X-Frame-Options (not required, but enhances
performance)-->
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>blockContentTypeSniffingEnabled</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xssProtectionEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter_AntiClickJacking</filter-name>
<url-pattern>/carbon/*</url-pattern>
<url-pattern>/dashboard/*</url-pattern>
</filter-mapping>

If an application requires enabling SAMEORIGIN framing only for a particular URL, below configuration can be used :

<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>

<filter>
<filter-name>HttpHeaderSecurityFilter_AntiClickJacking_SpecialURL</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<!-- Disable other headers except X-Frame-Options (not required, but enhances
performance)-->
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>blockContentTypeSniffingEnabled</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xssProtectionEnabled</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>antiClickJackingOption</param-name>
<param-value>SAMEORIGIN</param-value>
</init-param>
</filter>

<!-- Global filter mapping -->
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>

<!-- Overriding filter mapping for the specific URL, should come after global filter
mapping-->
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter_AntiClickJacking_SpecialURL</filter-name>
<url-pattern>/special_url/*</url-pattern>
</filter-mapping>

Further details on configuration is available at Tomcat official documentation on HTTP_Header_Security_Filter100 and relevant source files101.

3. Securing Jaggery Applications

It is required to upgrade Jaggery version to 0.12.6 or later.

3.1 Recommended Default Configuration

Recommended jaggery.conf filter mapping for development environments is as follows (WSO2 products should be released with this default configuration):

"filters":[
{
"name":"HttpHeaderSecurityFilter",
"class":"org.apache.catalina.filters.HttpHeaderSecurityFilter",
"params" : [{"name" : "hstsEnabled", "value" : "false"}]
}
],
"filterMappings":[
{
"name":"HttpHeaderSecurityFilter",
"url":"*"
}
]

3.2 Recommandation Production Configuration

Recommended jaggery.conf filter mapping for production environments is as follows :

"filters":[
{
"name":"HttpHeaderSecurityFilter",
"class":"org.apache.catalina.filters.HttpHeaderSecurityFilter"
"params" : [{"name" : "hstsMaxAgeSeconds", "value" : "15768000"}]
}
],
"filterMappings":[
{
"name":"HttpHeaderSecurityFilter",
"url":"*"
}
]

3.3 Customized Configuration

It is possible to use filter mappings to cater product level customizations required. For example in order to enable X-Frame-Options only for particular URLs, below configuration can be used :

"filters":[
{
"name":"HttpHeaderSecurityFilter",
"class":"org.apache.catalina.filters.HttpHeaderSecurityFilter"
"params" : [{"name" : "antiClickJackingEnabled", "value" : "false"}]
},
{
"name":"HttpHeaderSecurityFilter_AntiClickJacking",
"class":"org.apache.catalina.filters.HttpHeaderSecurityFilter"
"params" : [
{"name" : "hstsEnabled", "value" : "false"},
{"name" : "blockContentTypeSniffingEnabled", "value" : "false"},
{"name" : "xssProtectionEnabled", "value" : "false"}
]
}
],
"filterMappings":[
{
"name":"HttpHeaderSecurityFilter",
"url":"*"
},
{
"name":"HttpHeaderSecurityFilter_AntiClickJacking",
"url":"/example1/*"
},
{
"name":"HttpHeaderSecurityFilter_AntiClickJacking",
"url":"/example2/*"
}
],

If an application requires enabling SAMEORIGIN framing only for a particular URL, below configuration can be used :

"filters":[
{
"name":"HttpHeaderSecurityFilter",
"class":"org.apache.catalina.filters.HttpHeaderSecurityFilter",
"params" : [{"name" : "hstsEnabled", "value" : "false"}]
},
{
"name":"HttpHeaderSecurityFilter_AntiClickJacking_SpecialURL",
"class":"org.apache.catalina.filters.HttpHeaderSecurityFilter"
"params" : [
{"name" : "hstsEnabled", "value" : "false"},
{"name" : "blockContentTypeSniffingEnabled", "value" : "false"},
{"name" : "xssProtectionEnabled", "value" : "false"},
{"name" : "antiClickJackingOption", "value" : "SAMEORIGIN"}
]
}
],
"filterMappings":[
{
"name":"HttpHeaderSecurityFilter",
"url":"*"
},
{
"name":"HttpHeaderSecurityFilter_AntiClickJacking_SpecialURL",
"url":"/special_url/*"
}
],

Further details on configuration is available at Tomcat official documentation on HTTP_Header_Security_Filter100 and relevant source files101.

C. WSO2 Engineering Guidelines - OWASP CSRFGuard

Version: 1.1 | Date: April 7, 2017

Revision History

Version Release Date Contributors / Authors Summary of Changes
1.0 May 30, 2016 Ayoma Wijethunga Initial version
1.1 April 7, 2017 Ayoma Wijethunga Formatting changes

1. Introduction

This document introduces OWASP CSRFGuard and further summarizes best practices and configuration recommendations for applications hosted on WSO2 platform. In addition, this document further explains configuration values that can be fine tuned to increase security, based on security requirements of the specific application.

OWASP CSRFGuard52 is an OWASP flagship project that provides synchronizer token pattern based CSRF protection in a comprehensive and customizable manner.

CSRFGuard offers complete protection over CSRF scenarios by covering HTTP POST, HTTP GET as well as AJAX based requests.

Forms based on HTTP POST and HTTP GET methods can be protected by injecting CSRF tokens into "action" of the form, or by embedding token in a hidden field. In addition, HTTP GET requests sent as a result of resource inclusions and links can also be protected by appending relevant token in the "href" or "src" attributes. Token inclusions can be done manually using provided JSP tag library or by using a JavaScript based automated injection mechanism. AJAX requests are protected by injecting an additional header which contains CSRF token.

2. Recommended Approach for WSO2 Products

Any state changing actions should be performed with HTTP POST method, with exception for usage of PUT and DELETE methods in REST APIs.

CSRFGuard should not validate HTTP GET requests for CSRF protection. Token injection should be performed using JavaScript mechanism102. Hidden input field injection should be the only injection operation performed by CSRFGuard, that will protect HTTP POST based forms. In addition, AJAX POST requests should be protected by sending CSRF token in a header.

CSRF token values should not be exposed in URL. In situations where script injection can not be performed and built in AJAX protection does not suffice, product teams may decide to use JST tag library based manual inclusion103, after verifying with Platform Security Team.

Product teams should append CSRF exclusion URLs exposed from the root context, relevant to the particular product, in "Owasp.CsrfGuard.Carbon.properties" by following the steps mentioned in section 6.

3. Securing Web Applications

Recommended web.xml changes:

<!-- OWASP CSRFGuard context listener used to read CSRF configuration -->
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
</listener>

<!-- OWASP CSRFGuard session listener used to generate per-session CSRF token -->
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
</listener>

<!-- OWASP CSRFGuard per-application configuration property file location-->
<context-param>
<param-name>Owasp.CsrfGuard.Config</param-name>
<param-value>repository/conf/security/Owasp.CsrfGuard.Carbon.properties</param-value>
</context-param>

<!-- OWASP CSRFGuard filter used to validate CSRF token-->
<filter>
<filter-name>CSRFGuard</filter-name>
<filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>

<!-- OWASP CSRFGuard filter mapping used to validate CSRF token-->
<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- OWASP CSRFGuard servlet that serves dynamic token injection JavaScript (application can customize the URL pattern as required)-->
<servlet>
<servlet-name>JavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JavaScriptServlet</servlet-name>
<url-pattern>/csrf.js</url-pattern>
</servlet-mapping>

Include "JavaScriptServlet" in the HTML template of the application, so that element of all pages that need to be protected, should have JavaScriptServlet as the first JavaScript inclusion.

<html>
<head>
...
<script
type="text/javascript" src="/csrf.js"></script>

<!-- other JavaScript inclusions should follow "csrf.js" inclusion -->
<script type="text/javascript" src="/main.js">lt;/script>
...
</head>
<body>
...
</body>
</html>

Prepare and store per-application CSRF configuration file according to section 5 and 6 of the document.

4. Securing Jaggery Applications

Update Jaggery version to 0.12.6
Recommended jaggery.conf changes:

"listeners" : [
{
"class" : "org.owasp.csrfguard.CsrfGuardServletContextListener"
},
{
"class" : "org.owasp.csrfguard.CsrfGuardHttpSessionListener"
}
],
"servlets" : [
{
"name" : "JavaScriptServlet",
"class" : "org.owasp.csrfguard.servlet.JavaScriptServlet"
}
],
"servletMappings" : [
{
"name" : "JavaScriptServlet",
"url" : "/csrf.js"
}
],
"contextParams" : [
{
"name" : "Owasp.CsrfGuard.Config",
"value" : "repository/conf/security/Owasp.CsrfGuard.dashboard.properties"
}
],
"filters" : [
{
"name" : "CSRFGuard",
"class" : "org.owasp.csrfguard.CsrfGuardFilter"
}
],
"filterMappings" : [
{
"name" : "CSRFGuard",
"url" : "/*"
}

],

Include "JavaScriptServlet" in HTML template of the application, so that <head> element of all pages that need to submit or make ajax requests to a protected URL should reference it as the first JavaScript inclusion.

<html>
<head>
...
<script
type="text/javascript" src="/csrf.js"></script>

<!-- other JavaScript inclusions should follow "csrf.js" inclusion -->
<script type="text/javascript" src="/main.js"></script>
...
</head>
<body>
...
</body>
</html>

Prepare and store per-application CSRF configuration file according to section 5 and 6 of the document.

5. Recommended Default Configuration Changes

Diff available at104 highlights recommended changes, which are further listed below.

# WSO2 : Since state-changing operations are not performed via HTTP GET,
# disabling CSRF validation for GET method.

org.owasp.csrfguard.UnprotectedMethods=GET

# WSO2 : Considering overhead, necessity, as well as current unintended behaviour
# of library after blocking a CSRF attack, disabling per-page tokens.

org.owasp.csrfguard.TokenPerPage=false

# WSO2 : Disabling token rotation after blocking a CSRF attack, since this behaviour
# will break back navigation after blocking an attack.
#org.owasp.csrfguard.action.Rotate=org.owasp.csrfguard.action.Rotate

# WSO2 : Disable redirecting user to an error page after blocking a CSRF attack
#org.owasp.csrfguard.action.Redirect=org.owasp.csrfguard.action.Redirect
#org.owasp.csrfguard.action.Redirect.Page=%servletContext%/error.html

# WSO2 : Enable sending a 403 error after blocking a CSRF attack. Product teams
# can add error page that handles 403 or "org.owasp.csrfguard.action.Error" to
# display custom error pages.

org.owasp.csrfguard.action.Error=org.owasp.csrfguard.action.Error
org.owasp.csrfguard.action.Error.Code
=403
org.owasp.csrfguard.action.Error.Message
=Security violation.

# WSO2 : Since, CSRFGuard will send relevant token name as HTTP header
# "X-" prefix was added to express that this is a non-standard header.

org.owasp.csrfguard.TokenName=X-CSRF-Token

# WSO2 : Disable printing configuration during start-up
org.owasp.csrfguard.Config.Print = false

# WSO2 : Disable JavaScript from injecting token value to HTTP GET based forms.
# This prevents token leakage that could occur when sending token in URL.
# State-changing actions should not be performed over HTTP GET

org.owasp.csrfguard.JavascriptServlet.injectGetForms = false

# WSO2 : Disable JavaScript from injecting token value to form action.
# This prevents token leakage that could occur when sending token in URL.

org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = false

# WSO2 : Disable JavaScript from injecting token value to "src" and "href".
# This prevents token leakage that could occur when sending token in URL.

org.owasp.csrfguard.JavascriptServlet.injectIntoAttributes = false

# WSO2 : Changing X-Request-With header text to avoid unnecessary information disclosure.
<org.owasp.csrfguard.JavascriptServlet.xRequestedWith = WSO2 CSRF Protection

# WSO2 - Pseudo-random number generator provider should be configured based on
# environment (SUN/IBMJCE)

org.owasp.csrfguard.PRNG.Provider=SUN

6. Excluding URLs from CSRF Validation

Web applications can include property keys with "org.owasp.csrfguard.unprotected." prefix to exclude relevant patterns from CSRF protection.

Examples :

org.owasp.csrfguard.unprotected.Default=%servletContext%/exampleAction
org.owasp.csrfguard.unprotected.Default_1
=%servletContext%/exampleAction
org.owasp.csrfguard.unprotected.Example
=%servletContext%/exampleAction/*
org.owasp.csrfguard.unprotected.ExampleRegEx
=^%servletContext%/.*Public\.do$

Note : Please do not use additional "." (period) symbols in unprotected URL alias which is followed by "org.owasp.csrfguard.unprotected."

Example relevant to above note:

Example Incorrect Usage:
org.owasp.csrfguard.unprotected. auth.example=%servletContext%/auth

Example Correct Usage:
org.owasp.csrfguard.unprotected.authExample=%servletContext%/auth

7. Further Enhancing Security

This section list down configurations values that can be used to further enhance security or introduce additional restrictions. Changes to following configuration values should only be done based on customer request or justifiable application level requirement, since they will affect performance or user experience.

Below property can be used to change the hashing algorithm used to generate CSRF token:

org.owasp.csrfguard.PRNG=SHA1PRNG

Following property can be used to define the length of CSRF token:

org.owasp.csrfguard.TokenLength=32

Following property can be enabled to invalidate the user session if an CSRF attack attempt was blocked by CSRFGuard:

#org.owasp.csrfguard.action.Invalidate=org.owasp.csrfguard.action.Invalidate

8. WSO2 Product Integration Checklist

Checklist Item 1:
Make sure state changing actions are performed only with HTTP POST method, with exception for usage of PUT and DELETE methods in REST APIs. No state changing operation should happen through GET requests.

Checklist Item 2:
CSRFGuard configuration should be changed to allow unauthenticated sessions to pass through the filter, by setting "org.owasp.csrfguard.ValidateWhenNoSessionExists" property to "false" in "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties". This can be done using product distribution POM file by adding below rule in "tasks" section of "maven-antrun-plugin" :

<!-- Update Owasp.CsrfGuard.properties file with ValidateWhenNoSessionExists to disable validation on requests made with no valid session -->
<
replace
file="target/wso2carbon-core-${carbon.kernel.version}/repository/conf/security/
Owasp.CsrfGuard.Carbon.properties"
token="org.owasp.csrfguard.ValidateWhenNoSessionExists = true"
value="org.owasp.csrfguard.ValidateWhenNoSessionExists = false"/>

Checklist Item 3 (For WSO2 Carbon 4.4.6 / 4.4.7 / 4.4.8 based products only):
CSRFGuard configuration location should be changed in web.xml to adapt into IBM JDK and DevStudio deployment environments. Default configuration location should be changed from
"/repository/conf/security/Owasp.CsrfGuard.Carbon.properties" to "repository/conf/security/Owasp.CsrfGuard.Carbon.properties". This can be done using product distribution POM file by adding below rule in "tasks" section of "maven-antrun-plugin" (if any product completely replaces the web.xml file derived from carbon, product should add this change in their version of web.xml file) :

Note : This path correction should also be done in any web.xml files other than carbon web.xml, and also in jaggery.conf files, if a product contains such.

<!-- Update Owasp.CsrfGuard.properties file location to fix IBM JDK and DevStudio issue-->
<replace
file="target/wso2carbon-core-${carbon.kernel.version}/repository/conf/tomcat/carbon/
WEB-INF/web.xml"
token="/repository/conf/security/Owasp.CsrfGuard.Carbon.properties"
value="repository/conf/security/Owasp.CsrfGuard.Carbon.properties"/>

Checklist Item 4
CSRFGuard configuration for Carbon console is available at
"/repository/conf/security/Owasp.CsrfGuard.Carbon.properties". Product team should append product specific CSRF exclusions for "Carbon console" to configuration file, during "distribution" maven build.

Product specific patterns used in previous implementation are available at105 for reference.

Please refer to "Excluding URLs from CSRF Validation" section for more details on adding exclusion patterns.

Checklist Item 5
If product contains Java web applications other than "Carbon console", make sure web.xml and template follows instructions in "Securing Web Applications" section.

While preparing CSRFGuard configuration file for the web application, you may duplicate "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties" and make application specific changes (if there is any). Thereafter, use "Owasp.CsrfGuard.Config" context parameter to point to the configuration file location.

Checklist Item 6
If product contains Jaggery web applications, make sure jaggery.conf and template follows instructions in "Securing Jaggery Applications" section.

While preparing CSRFGuard configuration file for the Jaggery application, you may duplicate "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties" and make application specific changes (if there is any). Thereafter, use "Owasp.CsrfGuard.Config" context parameter to point to the configuration file location.

Checklist Item 7
If any component made available within carbon context (root context) product contains a screen that is not rendered within the "Carbon console" template, but submits data to a "CSRF protected" resources exposed from "Carbon console" (root context) :

  • Component should include the CSRFGuard JavaScript as the first JavaScript inclusion in <head> section.
  • Example : TryIt (Example PR106)

Checklist Item 8
If any component contains JavaScript logic that generates forms dynamically using "document.createElement('form')" and submits same to a CSRF protected URL, it is required to add CSRF token manually as a form element using taglib:

  • Add taglib to the jsp,

<%@ taglib uri="https://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>

  • Manually inject the csrf token to form

var input = document.createElement("input");
input.setAttribute('type',"hidden");
input.setAttribute('name',"<csrf:tokenname/>");
input.setAttribute('name',"<csrf:tokenvalue/>");
form.appendChild(input);

Checklist Item 9
If any AJAX POST request sent to a CSRF protected, relative path (path not starting with "https://" or "https://") contains a colon (":") in the request URL, CSRFGuard will fail to add X-CSRF-Token header. This will result in a CSRF error. As a fix, it is required to include the CSRF token manually as a header similar to following:

jQuery.ajax({
type: "POST",
url: "../eventreceiver/get_adapter_properties.jsp?name=example:1.0.0",
data: {},
contentType: "application/json; charset=utf-8",
dataType: "text",
beforeSend: function(xhr) {
xhr.setRequestHeader("<csrf:tokenname/>","<csrf:tokenvalue/>");
},
success: function (propertiesString) {
...
}
});

Checklist Item 10
If an integration test submits data to a URL protected by CSRFGuard, test case should do following to prevent test failures:

  • Call configured JavaScriptServlet with HTTP header "FETCH-CSRF-TOKEN: 1" set to retrieve CSRF token for current session.

Example Request: curl 'https://localhost:9443/carbon/admin/js/csrfPrevention.js' -X POST -H 'FETCH-CSRF-TOKEN: 1' -H 'JSESSIONID=0C3C606B62FC7AC2D175AA1B9DCA971D;' --compressed --insecure

Example Response: X-CSRF-Token:TCPT-DI3J-DVGZ-2684-NQ67-L9OR-DTZU-FW85

  • Send CSRF token received in response as a parameter of submission.

Checklist Item 11
For file uploads (multipart requests), the recommendation is to manually inject the csrf token to action of the form (including requests made to /fileupload path). To do so, following steps need to be followed:

  • Add taglib to the jsp,

<%@ taglib
uri="https://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>

  • Manually inject the csrf token to form action

action="../../fileupload/webapp?<csrf:tokenname/>=<csrf:tokenvalue/>"

D. WSO2 Engineering Guidelines - Dynamic Analysis with OWASP ZAP

Version: 1.2 | Date: April 25, 2017

Revision History

Version Release Date Contributors / Authors Summary of Changes
1.0 June 4, 2016 Tharindu Edirisinghe Initial version
1.1 June 21, 2016 Prakhash Sivakumar ZAP API Information
1.2 April 25, 2017 Ayoma Wijethunga Formatting Changes

1. Introduction

This document provides details of all necessary steps for configuring the OWASP Zed Attack Proxy (OWASP ZAP)90 tool for scanning WSO2 products in order to discover security threats.

2. OWASP ZAP Setup

2.1 Increase JVM Heap Size for Running ZAP

The heap size is defined in the zap.sh (for linux) and zap.bat (for Windows) files. Default value is set to Xmx512m (if available free memory is above 1,500 MB) and increase the value appropriately based on the memory availability of your system. (At-least 4GB is recommended)

In addition to that, ZAP scan is a long running process. Therefore it is better to run ZAP in a cloud instance or in a dedicated server to avoid any interruptions.

2.2 Fine Tune ZAP Tool with Pre-Configured Policy

ZAP tool should be fine tuned before running a scan for obtaining better results. For this, you can download the WSO2 policy file for ZAP)107 which contains the settings to fine tune ZAP.

Go to Analyze --> Scan Policy Manager in ZAP.

figure1

Figure 1

In the Scan Policy Manager window, click on Import.

figure2

Figure 2

Browse and select the WSO2 Policy file you downloaded.

figure3

Figure 3

Since the policy file is imported correctly, you can use this later when you run the spider and the scan.

2.3 Configuring ZAP Proxy to Trace Browser Traffic

Rather than providing the URL of WSO2 server and attack the URL with ZAP, it is much more effective if we record the UI actions we do on the WSO2 server and let ZAP tool capture the traffic which can then be used for performing attacks.

Go to Tools --> Options --> Local Proxy and set the hostname/ip address and the port number for the proxy. (In this example, the port is set to 7777 which is selected randomly)

figure4

Figure 4

Now ZAP tool is ready to capture the traffic going through the above set port number. Next step is to configure the browser to send traffic through this port number so ZAP tool can trace them.

In Firefox, go to Edit --> Preferences and in the Advanced options, click on Settings under the Network tab.

Select the Manual proxy configuration and set the hostname/ip and the port number.

figure5

Figure 5

If any exception for localhost, 127.0.0.1 or the hostname of the WSO2 server you are trying to scan is given in No Proxy for: text box, remove them so ZAP can detect the traffic flow of that as well.

Now, go to firefox and access the WSO2 server. You will see the SSL warning below because the traffic goes through ZAP proxy. Add an exception to the site in the browser.

figure6

Figure 6

Now the WSO2 Server URL should be opened in the browser. Also it should be listed in ZAP under the sites.

figure7

Figure 7

Select the Mode of the scan as Protected Mode. With this, you can choose which sites to be used for attacking. (For example, if you are trying out the Federated Authentication scenario with WSO2 Identity Server and Facebook, under the Sites in ZAP tool, facebook website also will be listed to be attacked. In the scope of scanning, external websites should be removed. With the Protected Mode, you have the capability to select the Sites that should be attacked by ZAP tool)

3. Scanning Process

3.1 Excluding the Server Logout from Spider

When we run the ZAP scan with an active user session, if ZAP executes the action to logout from the server in the middle of the scan, the actions that should be performed with a logged in user session would not be performed after that (because active session is removed with logout action ). In order to avoid that, we need to exclude the logout action from the Spider.

For that, first login to the WSO2 Server and then logout so that the logout action is traced by ZAP. Then, find the GET:logout_action.jsp and right click on it and exclude from Spider.

The logout action is listed under <server_url> --> carbon --> admin in the Sites tree.

figure8

Figure 8

Then in the Session Properties window, it will show the URL regex that ZAP is going to exclude in the spider. Click OK.

figure9

Figure 9

3.2 Perform UI Actions Manually (or using Selenium)

With the above steps, ZAP is tracing the sites that you visit in the browser. Next step is to manually perform UI actions in the browser so that ZAP traces all the actions which we can then use for attacking.

This is helpful for testing a specific feature. For example, if we want to identify the possible issues in the user creation flow, we can create a new user in Management Console while ZAP traces all actions through the proxy.

figure10

Figure 10

On the URLs ZAP discovered, it can perform attacks to find possible issues. We can improve the coverage of the scan by manually performing all actions in the browser (i.e in Management Console) so that ZAP discovers each flow that it can try attacking.

You can also automate this by having selenium scripts for all UI actions. After setting the ZAP to act as the proxy, you can run selenium scripts so that in the browser, it automatically plays the actions you would do manually. For every action, ZAP will discover the URLs.

3.3 Removing Unnecessary Sites from Scan

When the ZAP is acting as the proxy, all the URLs that the browser calls will be traced under the Sites in ZAP. We need to remove external websites and select only the WSO2 Server's scope for scan.

Right click on the Site that should be included in the scan and select Include in Context -> New Context.

figure11

Figure 11

Then it will show the Session Properties window with the regex for including the URL patterns in the scan. Provide a name for the context so that we can identify the site uniquely when we have multiple sites added as different contexts. (For example when you are testing a product like WSO2 API Manager, the Management Console, API Store and API Publisher can be three major sites where you can add each as a different context)

figure12

Figure 12

Once the site is added to the Context for scan, the icon image for each entry under the tree of the site will be changed showing that it is added to the context.

figure13

Figure 13

Under the Sites list, you can click on the Show all URLs button to view only the sites that are added to the contexts. All other sites will be hidden from the Sites panel with this option.

figure14

Figure 14

Once you have added the site/s to the context, you can filter the scan results (after running a scan) easily. In the History tab, Show only URLs in Scope filters the results and shows only the URLs that belong to the context.

figure15

Figure 15

When searching also you can search URLs that belong only to the context with the Search all URLs option enabled.

figure16

Figure 16

You can also filter the alerts that belong only the contexts you have added with the Show all URLs option enabled.

figure17

Figure 17

3.4 Globally Excluding URL Patterns

When the ZAP tool starts crawling the site, it will increase the network traffic heavily. We can reduce the traffic by excluding the URL patterns globally so that ZAP will ignore such URLs when crawling. For example if we exclude URLs of .mp4 video files, ZAP tool will not download mp4 video files which saves network bandwidth.

Go to Tools -> Options and select Global Exclude URL option. By default there are some patterns already added to ZAP. You can select all of them for exclusion. Additionally, if there is any URL pattern you need to exclude, you can add the regex for the URL as a new entry.

figure18

Figure 18

3.5 Creating the Logged in User Session

When running the spider to crawl the site, we have to let ZAP discover the URLs that are accessible only by logged in users as well. For that, we need to create a logged in user session in ZAP so that same as a logged in user can browse the URLs in web browser, ZAP will be able to crawl through those URLs.

Click on Show All Tabs in the toolbox so that it will display all the tabs.

figure19

Figure 19

Go to the Http Sessions tab. If there are already created sessions listed, you can remove them.

figure20

Figure 20

Now while ZAP proxy is tracing the traffic, go to the browser and login to the site you need to scan. (When ZAP performs the scan, it will attack to the URLs with the associated privileges of the user you logged in). Once you login, the session ID should be listed in the HTTP Sessions tab. Right click on the session and Set as Active.

figure21

Figure 21

Above should be done only if the authentication to the site is tracked via the JSESSIONID. In a scenario like Single Sign On ( i. e when testing Identity Server Dashboard), the session is maintained using the commonAuthId cookie. In such case, go to the Params tab, right click on the JSESSIONID and select Unflag as session Token.

figure22

Figure 22

After that, right click on commonAuthId and Flag as Session Token. With this ZAP will take commonAuthId value for maintaining the session.

figure23

Figure 23

In both cases above, the browser should have an active user (logged in) session with the particular session value traced in ZAP which should then be flagged as the session token.

3.6 Configuring and Running AJAX Spider

When you have multiple sites added to the context and when you need all the sites to have the same configuration, you can set them globally. Go to Tools -> Options and select AJAX Spider.

Set the maximum crawl depth, maximum crawl states and maximum duration to 0 so that the AJAX Spider will go on crawling completely without any limitation.

figure24

Figure 24

You can choose the browser to be used for crawling by the AJAX spider. If your browser is not listed in the dropdown, go to Tools -> Options and in the Selenium option, browse and provide the selenium driver for the particular browser. (You can download the selenium driver for the particular web browser from internet). Once you have provided the driver, in AJAX Spider configuration's browser dropdown the browser will be listed.

figure25

Figure 25

If you have multiple sites added to the context, but need to have separate ajax spider configuration for a particular site, you cannot use global settings. In such case, right click on the particular site and go to Attack -> AJAX Spider.

Also you need to select Protected Mode (from the dropdown in toolbox) for running the AJAX spider so that it will crawl through the sites added to the context and will skip any URL that is out of scope.

figure26

Figure 26

Select Show advanced options in the Scope tab which will make the Options tab visible.

figure27

Figure 27

In the Options tab of AJAX Spider, you can set the configuration specific to this particular site.

figure28

Figure 28

Once the configuration is set, you can Start Scan.

Before starting the scan, you need to make sure that you have an active user session set in ZAP (Follow the steps in 1.8 Creating the Logged in User Session section) so that AJAX spider can crawl URLs that are accessible by the logged in user.

3.7 Running Spider

The global configuration for Spider is in Tools -> Options under Spider option which is applicable to all the sites added to the context.

You can set the maximum depth to crawl to 5. At this point we have already run the AJAX Spider and discovered most of the URLs with crawling. Therefore crawling more up to a depth of 5 levels would provide sufficient coverage.

figure29

Figure 29

When you have multiple sites added to the context and need to have separate Spider configuration for a particular site, you cannot use Global Settings. In such case, you can right click on the site and go to Attack -> Spider.

figure30

Figure 30

In the Spider window, select Show Advanced options and go to the Advanced tab.

figure31

Figure 31

Since we have run the AJAX Spider previously, it should have crawled most of the URLs of the server. Therefore having only 5 as the maximum depth to crawl would be sufficient to complete crawling and covering the URLs of the server.

figure32

Figure 32

With above configuration, start the scan to complete URL discovery.

3.8 Removing False Positives before Scanning

Before running the Active Scan, we can configure the Session Properties such that when reporting alerts, it would avoid known false positive URLs.

Go to File → Session Properties and under the particular context, select Alert Filters.

figure33

Figure 33

The click on Add button to define the URLs that we have already identified to be reporting false positive alerts.

figure34

Figure 34

In the Add Alert Filter window, select the type of Alert and set it as a False Positive in the New Risk Level dropdown. If the URL is a direct URL, it can be given in the URL textbox. If there are multiple URLs following the same pattern, select the URL is Regex? checkbox and define the regular expression for the URL. Finally Confirm the alert filter.

The alerts generated for these URLs would be ignored by ZAP during the scanning time and also would not appear in the identified security vulnerabilities.

3.9 Running Active Scan

When you have multiple sites in the context and need to have similar active scan configuration for all the sites, you can use the global settings. Go to Tools -> Options and select Active Scan.

As the default active scan policy and attack mode scan policy, select the WSO2Policy file which you imported in section 1.2 Fine Tune ZAP Tool with Pre-Configured Policy.

figure35

Figure 35

When you have multiple sites added to the context, but need to have specific active scan configuration for a particular site, you can right click on the particular site and go to Attack -> Active Scan.

figure36

Figure 36

It will show the Active Scan window. Select Show advanced options and go to Policy tab.

figure37

Figure 37

As the Policy, select the WSO2Policy file which you imported previously.

figure38

Figure 38

Finally start the scan. Note that you need to have a logged in user session when running the active scan. (follow the steps in 1.8 Creating the Logged in User Session)

Then the scan will begin and you can see the progress in Active Scan tab.

figure39

Figure 39

4. Report Generation

4.1 Removing False Positives Before Report Generation

Once the Active Scan is completed and the alerts are generated, if there are false positive alerts, they can be removed appearing in the reports generated. For that, go to the Alerts tab and double click on the particular alert that should be marked as a false positive.

figure40

Figure 40

Then the Edit Alert window will appear. In the Confidence dropdown, select False Positive.

figure41

Figure 41

4.2 Generating Reports

Once the Active Scan is complete, you can generate the reports for exporting the results of the scan. Go to Report -> Generate HTML Report from the menu.

figure42

Figure 42

Then it will prompt where to save the report. Once you provide a file path, it will export the ZAP scan report. By examining the report, you will be able to identify possible security threats and get them fixed.

figure43

Figure 43

5. Scanning RESTful APIs with ZAP

WSO2 products have APIs that are secured with OAuth. In order to consume such APIs, we need to provide an access token in the request. When ZAP is scanning the URLs, since the access token is not passed when making the requests, it will fail to scan the APIs completely. In such cases, we can manually test the APIs using a REST client which can be configured to send traffic through a proxy. Here we can configure the proxy host and port to the same host and port that ZAP is running so that ZAP can trace and record traffic for all the API requests.

OAuth access tokens have a fixed expiration time, which is set to 60 minutes by default in WSO2 products (i.e Identity Server). This expiration time is not sufficient when running the active scan. Therefore you have to increase the token expiration time in
<AccessTokenDefaultValidityPeriod> element in
<CARBON_HOME>/repository/conf/identity.xml file.

  1. Configure the proxies in the browser as you do in the usual scenario, since REST client runs on top of the browser ZAP is intelligent enough to identify the process.
  2. Configure the authentication headers in REST client.
figure44

Figure 44

Now run the requests in the REST client, ZAP can now scan as it does for the web UI. You will be able to do the active scan, spider and ajax spider after that as you do in the usual way.

If you see any certificate based errors like below in your REST client, allow the certificate when pops up when trying to login to the carbon console (In firefox you won't get any response).

figure45

Figure 45

E. WSO2 Engineering Guidelines - Static Code Analysis using FindSecurityBugs

Version: 1.2 | Date: April 25, 2017

Revision History

Version Release Date Contributors / Authors Summary of Changes
1.0 June 28, 2016 Tharindu Edirisinghe Initial version
1.1 December 16, 2016 Prakhash Sivakumar Minor wording correction
1.2 April 25, 2017 Ayoma Wijethunga Formatting Changes

1. Introduction

This document provides details of all necessary steps for configuring FindBugs108 and Find Security Bugs91 for scanning source code in order to discover security threats.

2. Installation - IntelliJ Idea - FindBugs Plugin

Once you open IntelliJ IDEA, you can go to Configure -> Plugins in the opening window.

figure1

Figure 1

If you have already opened a project in IntelliJ IDEA, you can go to File -> Settings and in the left panel of the Settings window, select Plugins.

figure2

Figure 2

You can install the FindBugs plugin in two ways. If you have an internet connection, you can click on Browser repositories button and get the plugin installed. If not you can download the FindBugs plugin for IntelliJ IDEA109 and go with Install plugin from disk option where you can browse and provide the already downloaded plugin.

When you go with Browse repositories option, you can search for the findbugs plugin and select FindBugs-IDEA and get it installed.

figure3

Figure 3

3. Installation - IntelliJ Idea - Find Security Bug Plugin

Once you have installed the FindBugs plugin in IntelliJ IDEA, in the bottom of the IDE you will see the FindBugs-IDEA button. Upon clicking on it you can see all the settings of it in a panel.

figure4

Figure 4

Now we have to enable the FindSecurityBugs plugin which comes with FindBugs. This is for finding the security bugs in your code. Click on Plugin Preferences button.

figure5

Figure 5

Under the Plugins section of the General tab, click on the + button and select Add Find Security Bugs.

figure6

Figure 6

Once the FindSecurityBugs plugin is added, click on Apply and then OK.

figure7

Figure 7

Now we have successfully installed FindBugs plugin in IntelliJ IDEA and also have enabled the FindSecurityBugs plugin in it. Let's perform a static code analysis and get to know all the bugs we have in the code.

4. Code Analysis

To analyze the project, right click on the project and go to FindBugs -> Analyze Scope Files. With this, the scanning will happen only under the selected folder. You can also go with Analyze Module Files which would scan the particular module you have selected and also Analyze Project Files which would scan the entire project.

figure8

Figure 8

Once the static scan is completed, you can see the identified bugs in FindBugs-IDEA panel. Since we have enabled the FindSecurityBugs plugin, it will list all the identified security issues under the Security category.

figure9

Figure 9

5. Report Generation

You can export the reported bugs for further analysis. For that, click on the Export Bug Collection to XML/HTML button.

figure10

Figure 10

A generated report would look like below.

figure11

Figure 11

In you go to the Security Warnings section, you can see a detailed explanation for each identified security issue.

figure12

Figure 12

F. Engineering Guidelines - External Dependency Analysis using OWASP Dependency Check

Version: 1.1 | Date: June 22, 2017

Revision History

Version Release Date Contributors / Authors Summary of Changes
1.0 June 12, 2017 Tharindu Edirisinghe Initial version
1.1 June 22, 2017 Nadeeshani Pathirennehelage Running Maven plugin without POM file modification

1. Introduction

This document provides details of all necessary steps for using OWASP Dependency Check92 Command Line Client (CLI)92 tool and the Maven plugin110 for analyzing 3rd party dependencies92 used in projects for identifying known security vulnerabilities.

2. OWASP Dependency Check CLI

This is useful when you have the external dependencies (libraries/jar files) downloaded and put in a folder, where you can run the CLI tool against the folder for analyzing the libraries in it and generate the vulnerability assessment report.

OWASP Dependency Check CLI

Figure 1

Download the CLI tool111 and extract the zip file. In the bin directory of the dependency-check tool, you can find the executable script dependency-check.bat file which is for running the tool on Windows operating system and the dependency-check.sh file which is for running on Linux. If you just execute the script without providing any parameters, you can see the list of parameters that you need to provide for performing the vulnerability analysis and generating reports.

OWASP Dependency Check CLI

Figure 2

Following are the basic parameters that are required when running a vulnerability analysis.

Parameter Description
--project You can specify a name for the project and this would appear in the report
--scan The folder which contains the 3rd party dependency libraries
--out The folder where the vulnerability analysis reports should be generated
--suppression An XML file that contains the known vulnerabilities that should be hidden from the report (false positives)

Now let’s do an analysis using OWASP Dependency Check. First I download commons-httpclient-3.1 and httpclient-4.5.2 libraries and put them in a folder.

Following is the sample command to run for performing the vulnerability analysis.

./dependency-check.sh --project "<myproject>" --scan <folder containing 3rd party libraries> --out <folder to generate reports> --suppression <xml file containing suppressions>

Here I skip the suppression and just do the analysis. I have put the above downloaded 2 libraries to /home/tharindu/dependencies/mydependencies folder in my filesystem and I would generate the reports to the /home/tharindu/dependencies/reports folder.

./dependency-check.sh --project "<myproject>" --scan /home/tharindu/dependencies/mydependencies --out /home/tharindu/dependencies/reports

When you run the OWASP Dependency Check for the very first time, it would download the known vulnerabilities from the National Vulnerability Database (NVD)53 and it would maintain these information in a local database. So, when running this for the very first time, it would take some time as it has to download all the vulnerability details.

OWASP Dependency Check CLI

Figure 3

By default the duration for syncing the local database and NVD is 4 hours. If you have run the Dependency Check within 4 hours, it will just use the data in local database without trying to update the local database with NVD.

OWASP Dependency Check CLI

Figure 4

Once you run the Dependency Check against the folder where your project dependencies are, it would generate the vulnerability analysis report.

3. OWASP Dependency Check Maven Plugin

In the previous chapter, the usage of OWASP Dependency Check CLI tool was explained which requires the user to download the external dependencies to a folder and run the tool against the folder for performing the vulnerability analysis. However in practice, this approach does not scale as we would introduce new dependencies as and when we code. In such cases, the maven plugin110 of OWASP Dependency Check does the job where every time we build the project, it would analyze all the external dependencies of the project and generate the vulnerability report. In this section it is explained how to use this maven plugin for analyzing the project dependencies and how to identify the reported vulnerabilities of them.

In the pom.xml file of your maven project, add the following plugin.

<build>

<plugins>

<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>1.4.5</version>
<configuration>
<cveValidForHours>12</cveValidForHours>
<failBuildOnCVSS>7</failBuildOnCVSS>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>

</build>

Now you can build the project (mvn clean install) and it will generate the dependency check report in the target directory.

In the maven plugin under the configuration section, from the cveValidForHours parameter you can control the duration to check for newly reported vulnerabilities in the National Vulnerability Database (NVD) when the maven project is being built. From the failBuildOnCVSS parameter, we can define a CVSS score where if any known vulnerability is found in a dependent library which has a CVE with CVSS score equal or greater than to the value we define, it will fail the build no matter even if the project has no syntax errors. This is a useful feature for an organization which has automated building the codebase using tools like Jenkins, so that the threats can be identified and rectified as and when they are introduced.

There are more configuration like above which you can refer the official documentation112 to find out. In addition to that, there are few references113,114, useful for finding more information on the plugin.

You can test the plugin by adding the following two dependencies to your project. There, the 3.1 version of commons-httpclient has known vulnerabilities which will be indicated in the vulnerability report. The 4.5.3 version of httpclient has no reported vulnerabilities and therefore it will not be indicated in the report.

<dependencies>

<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>

</dependencies>

The generated report would look as the same which is the same as using the CLI115 tool.

4. OWASP Dependency Check Maven Plugin - Without POM Modification

We can run OWASP Dependency Check without doing any changes to maven pom.xml file. We can just run using the mvn command as follows.

mvn org.owasp:dependency-check-maven:check

Then it will build the product with the dependency-check-maven. Thus, it will generate the dependency check report for 3rd party dependencies of your product.

In any case of false positive issues that you want to remove from the generated report, you can suppress those by creating a suppression.xml file. Then, you can give that suppression file as an argument in the mvn command.

-DsuppressionFile="\${path.to.suppression.file}/suppression.xml"

This is an example suppression.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
<suppress>
<notes><![CDATA[
CVE-2016-7051 is only relevant to jackson-dataformat-xml according to NVD [1] and original bug report [2].
[1] https://github.com/FasterXML/jackson-dataformat-xml/issues/211
]]></notes>
<cve>CVE-2016-7051</cve>
</suppress>
<suppress>
<notes><![CDATA[
CVE-2012-4232 is only valid for "a:jcore:jcore" JCore is not used within Ballerina.
]]></notes>
<cve>CVE-2012-4232</cve>
</suppress>
</suppressions>

5. Analyzing the Reports

Given below is an example on analyzing the vulnerability report.

Analyzing the vulnerability report

Figure 5

Based on the analysis, we can see that the commons-httpclient-3.1.jar is having 3 known security vulnerabilities, but httpclient-4.5.2.jar is not having any reported security vulnerability.

Following are the 3 known security vulnerabilities reported against commons-httpclient-3.1.jar.

Security vulnerabilities reported against commons-httpclient-3.1.jar

Figure 6

Security vulnerabilities reported against commons-httpclient-3.1.jar

Figure 7

Security vulnerabilities reported against commons-httpclient-3.1.jar

Figure 8

A known security vulnerability would have a unique identification number (CVE)116 and a score (CVSS117, a scale from 0 to 10) and the severity. The severity is decided based on the CVSS score. The identification number follows the format CVE-<reported year>-sequence number.

When we identify that there is a known security vulnerability in a 3rd party library, we can check if that library has a higher version where this issue is fixed. In above example httpclient 3.1’s vulnerabilities are fixed in its latest version.

If the latest version of a 3rd party library is also having known vulnerabilities, you can try to use an alternative which has no reported vulnerabilities so you can make sure your project is not dependent on any external library that is not safe to use.

However there comes situations where you have no option other than using a particular 3rd party library, but still that library has some known vulnerabilities. In such case, you can go through each vulnerability and check if it has any impact to your project. For example, the 3 known issues in httpclient 3.1 are related to SSL, hostname and certificate validation. Let’s say your project uses this library just to call some URL (API) via HTTP (not HTTPS), then your project has no impact from the reported vulnerabilities of httpclient. So these issues become false positives in your case.

In such situation, you might need to get a vulnerability analysis report for 3rd party dependencies that clearly reflects the actual vulnerabilities and hides false positives. Then you can use the suppress option in Dependency Check.

6. Vulnerability Suppressions - Marking False Positives

When you get the Dependency Check report, next to each vulnerability in the report, there is a button named suppress. If you want to hide that vulnerability from the report, click on this button and it would popup a message that contains some XML content.

Vulnerability Suppressions - Marking False Positives

Figure 9

You can create an XML file with below content and put the XML content you got by clicking on the suppress button as child elements under <suppressions> tag.

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">

<!-- add each vulnerability suppression here-->

</suppressions>

A sample is below.

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<notes><![CDATA[file name: commons-httpclient-3.1.jar]]></notes>
<sha1>964cd74171f427720480efdec40a7c7f6e58426a</sha1>
<cve>CVE-2015-5262</cve>
</suppress>
</suppressions>

When you are using the Dependency Check CLI, you can run it with the --suppression parameter where you provide the file path to the XML file that contains the suppressions.

./dependency-check.sh --project "myproject" --scan /home/tharindu/dependencies/mydependencies --out /home/tharindu/dependencies/reports --suppression /home/user/dc/suppress.xml

When you are using the Dependency Check Maven plugin, you can add the suppressionFile property to the configuration and point to the XML file which contains the suppressions.

<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>1.4.5</version>
<configuration>
<cveValidForHours>12</cveValidForHours>
<failBuildOnCVSS>8</failBuildOnCVSS>
<suppressionFile>/home/user/dc/suppress.xml</suppressionFile>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>

Then the report would show how many vulnerabilities are suppressed.

Vulnerability Suppressions - Marking False Positives

Figure 10

Also the report would contain a new section called Suppressed Vulnerabilities and you can make this section hidden or visible in the report.

Vulnerability Suppressions - Marking False Positives

Figure 11

7. Summary

In conclusion, before using an external library as a dependency for your project, it is important to know those are safe to use. You can simply use a tool like OWASP Dependency Check and do a vulnerability analysis for the 3rd party dependencies. You can follow this as a process in your organization to ensure that you do not use components with known vulnerabilities in your projects. This is one major software security risk listed under OWASP Top 10118 as well.

For more details about our solutions or to discuss a specific requirement contact us.

x

Interested in similar content?