Rick Ramgattie's InfoSec Adventures

| Posts | About |

Securing Play Web Applications

Published Date: 2020-04-25

Play is a web framework written in the Scala programming language that follows the Model-View-Controller (MVC) archtectural pattern. It is a fairly popular framework and is most well known for it's use in the financial industry and amongst tech giants like Twitter.

Play provides functionality that helps prevent common web application vulnerabilities: HTML Templates are processed by the Twirl templating engine which helps prevent most Cross-Site Scripting (XSS) attacks database queries are delegated to the Slick Functional Relational Mapping (FRM) library which helps prevent SQL Injection (SQLi) attacks, and Play itself has built-in Cross-Site Request Forgery (CSRF) defenses.

Although these features enhance security, their presence is not enough to secure Play apps.

This blog focuses on security issues developers and security folk should keep in mind when developing or auditing a Play app. In the first half I provide examples of Play's default security features being disabled, and the second half I discuss features that have a good Signal to Noise (SNR) ratio when searching for vulnerabilities.

If you are looking for general Webb App security testing I recommend checking out the OWASP Testing Guide.

Disabled Security Features

Disabled HTML Escaping in Twirl

Twirl's auto HTML escaping functionality can be disabled by wrapping it with the template content type. If you see user input wrapped by the `@Html` helper function the application is vulnerable to HTML Injection (HTMLi) and Cross-Site Scriptin (XSS) attacks.

Disabled SQLi Protections

Slick is a Functional Relational Mapping (FRM) library for Scala. By default Slick prevents SQL Injection attacks by representing SQL queries as a Scala collection. If you see user input being included in a Slick Plain SQL query as a spliced parameter `#$` the application is vulnerable to SQL Injection. Additionally, if the SQL query is built as a composition of unsanitized user provided values they application is likely vulnerable to SQLi as well.

Disabled CSRF Protections in Play

Play has a global Cross-Site Request Forgery (CSRF) filter that be applied to all requests. Play's documentation provides a number of ways to disabled these CSRF checks but the most commonn is adding the `nocsrf` modifider tag to a route.

Catching CSRF bypasses can be tricky, I recommend going through Play's documentation and vetting your config when searching for this issue. I also recommend setting the `SameSite` flag on your cookies as a defense in depth measure.

Features with a good SNR for vulnerabilities


A Play app can access the client's IP address by calling the `remoteAddress` method on the request object. If Play is not fronted by a Web Server that appropiately sets the `X-Forwarded-For` and `Forwarded` headers the value of `remoteAddress` can be set in those headers in the client HTTP request.

absoluteURL and webSocketURL

You can transform the URL from a `Call` object to an absolute URL by calling to `absoluteURL` method. If Play is not fronted by a Web Server that appropiately verifies the `Host` header the value returned by `absoluteURL` can be set in the client HTTP request. Likewise, if the `webSocketURL` method is called it is also affected by requet's `Host` header. This is often refered to as Host Header Poisoning.


Although Web Application Frameworks help reduce vulnerabilities it is important to understand the magic that happens in the background. If you are working on our reviewing a Play app I recommend reviewing the documentation to ensure you are appropiately using it's features. I also recommend revieiwing the source to ensure your understanding of the magic and checking out the articles that I haved linked below.

Additional Reading: