In a time where application security vulnerability indices struggle to keep up with the drastic growth of different attack vectors, it is not a surprise that application engineers will overlook new security threats being discovered.

Security Guidelines?

In order to make sure application engineers are up to date on security threats, organizations will usually provide security guidelines. One such example is the WSO2 Secure Engineering Guidelines, which is about to get published with OWASP Top 10–2017 updates, as I am writing this blog post. Adhering to the security guidelines is a must, but these are lengthy lists to follow. New engineers will take more time to familiarize themselves with these guidelines. Moreover, who is going to validate if these guidelines are followed?

Code Reviews and Static Code Analysis?

Even if it is not fully reliable, having a strict manual code review process is one way to go. If you are responsible for the security aspect of the applications, you will not feel comfortable enough depending completely on the manual code reviews.

The other option is to use automated static code analyzers. Usually, static analyzers will look for known security weaknesses using language-specific rules and signatures. Some static analyzers will perform taint-analysis to make sure untrusted (tainted) data is not passed to a sensitive sink.

As soon as you speak of an automated static code analyzer, engineers will start to think of all the “false positives” these tools could generate. The effort of adding mitigation or suppression comments and then again reviewing these comments is huge. Maintaining such suppression details per application version is another daunting task, which will require separate Vulnerability Management Systems. Apart from all these troubles, there can be “false negatives” leading to costly security incidences.

But why false positives & negatives?

This is mainly because the static code analyzers are acting on top of a programming language that does not fully understand or support security concepts. These are the side effects of using an external tool to fill up a gap the programming language itself has left wide open!

The static code analyzer will have to take the full responsibility of segregating trusted data sources and untrusted data sources, which is hard enough! Nevertheless, we also make the analyzer responsible for knowing all the security sensitive operations! Yet again, the analyzer should have the ability to know the security impact of all the complicated language features and all the language features a new version of the programming language will bring in.

Security-aware programming language to the rescue!

What would happen if the programming language itself is aware of all the security sensitive operations it exposes and has the ability to segregate trusted data sources from untrusted data sources?

In addition, what if this language uses “secure-defaults” and will not allow engineers to use language features insecurely without proper validations?

Yes, we no longer need a static code analyzer to find costly security mistakes, and yes, we no longer need to fully rely on manual code reviews for security checks!

However, it is not practical to change a years old programming language and make it security aware. This will break most of the user applications since the changes will be drastically backward incompatible. Instead, what we need is a programming language designed with security in focus.

Ballerina, a security-aware programming language to engineer secure by design integrations and microservices.

If you need to integrate multiple services or write cloud-native microservices, Ballerina will make your life way easier by providing everything from concurrency, resilience, testability, gRPC, distributed transaction, messaging to security, built and well-baked into the language.

You can of cause head over to Ballerina.io and Ballerina by Examples page to read all about microservice and integration focused features Ballerina has to offer.

However, this post is focused only on security, and security only!

Ballerina standard library has been designed with a strong security focus.

All the functions in Ballerina standard library that generate untrusted data has been explicitly marked. Therefore, the language compiler will have the ability to identify what operations could result in generating untrusted data. Network reads, database reads, and file reads are just a few high-level examples of untrusted data sources.

All the security-sensitive parameters of Ballerina standard library functions are explicitly marked, giving the language compiler the ability to know where tainted data should not be passed.

The following example extract is from the native functions relevant to HTTP request and response handling (MIME handling, to be precise). sensitive annotation is used to denote that the headerName parameter is security-sensitive, whereas tainted annotation is used to denote that the getHeader(-) function returns an untrusted value.

In combination, aforementioned information will create the security signature of a function. Security signatures of other function will be derived automatically based on the usage of standard library functions, without programmers having to explicitly add the annotations.

Therefore, since the standard library functions are properly covered, Ballerina programmers can take advantage of standard library security signatures to automatically derive security signatures for their code.

Taint Analysis — Examples

The usefulness of taint-analyzer can be further clarified with few examples. Following code creates a simple “Hello World” Ballerina service:

Once you run the program, it will expose a HTTP service with one resource that can can be invoked by sending a HTTP GET request to http://localhost:9090/hello/sayHello.

What if we change this program to accept a “name” as a query parameter and appending that to “Hello” in the response:

Even though the change makes the program even more attractive, anyone with security in focus will know that the application relying on this service is now vulnerable to Cross Site Scripting (XSS).

However, Ballerina compiler knows that the HTTP response sent with the respond action should not be an untrusted value. In addition, Ballerina knows that the name extracted from HTTP GET query parameter is an untrusted value. Therefore, if you try to run this application, Ballerina compiler will generate the following error:

error: ./helloworld_xss.bal:9:24: tainted value passed to sensitive parameter ‘payload’

compilation contains errors

The programmer should do proper validation of the parameter before passing the untrusted data to the HTTP response payload. untaint unary expression can be used to denote that the proceeding data should be considered trusted:

Another example can be demonstrated by using the Ballerina database connector. In the following code, HTTP GET query parameter is appended to the SQL query which will result in SQL Injection vulnerability.

Ballerina compiler is aware that the SQL Query parameter of the select action is security sensitive. Hence, the compiler will not allow tainted data in its place.

error: ./helloworld_sqli.bal:21:40: tainted value passed to sensitive parameter ‘sqlQuery’

compilation contains errors

Correct approach is to use sql:Parameter to create properly parameterized SQL queries. JDBC Client Ballerina example shows such correct usage.

Similarly, by using the taint-analysis, Ballerina prevents multiple critical security vulnerabilities including:

Path Manipulation

File Manipulation

Unauthorized File Access

Unvalidated Redirect (Open Redirect)

Technical details on how Ballerina taint-analyzer works is a story for another post!

Secure Defaults

Ballerina compiler, run-time and the standard library enforce multiple other security checks and secure-defaults to prevent critical security vulnerabilities.

Bringing up one such example, OWASP Top 10 — 2017 update made a significant change to the 2013 version. One of these changes include the addition of XML External Entities (XXE) attack, a critical attack made possible by misconfigured XML parsers.

Ballerina having first-class support for XML and JSON data, makes sure the default internal XML parsing mechanism prevents XML External Entities (XXE) attack as well as XML Entity Expansion attack without developers having to do complex configuration changes to implement security. Relevant unit tests and integration tests can be reviewed for further technical details.

Security Monitoring & Response

Since security is a domain that changes very frequently, it is important to watch for new attack vectors and vulnerabilities to provide better security. Security team responsible for keeping Ballerina platform secure (including myself) constantly monitoring for these types of developments.

One such example is the Zip Slip attack, which is an arbitrary file write vulnerability through archive extraction that got discovered in Java based applications very recently.

Even though public libraries used by external Ballerina programmers were not affected, within a week from the original public disclosure, all the locations withing Ballerina platform that performs archive extraction got patched with additional security validations. The immediate Ballerina version contained relevant fixes. Related unit test can be reviewed for further technical details.

Authentication & Authorization

Ballerina services can be configured to enforce authentication and authorization checks. Integrations points can be configured to use the built-in security framework to generate or exchange required tokens. That in itself is an interesting discussion on different microservice security patterns. Therefore, I will move the relevant content to a separate post.

Further Reference

If you are looking for more details about using Ballerina to make the world a secure place, be sure to visit “How to Write Secure Ballerina Programs” page. I assure you that it is not a 500+pages long list of security guidelines!