Securing modern web apps: A case for framework-aware SAST

If you were to write a web application entirely by yourself, it would be a rather daunting task. You would need to write the UI elements from lower-level APIs, set up and manage the database connections, manage the HTTP requests and replies, and so on. Then there is the application code itself and its business logic. Maintaining this application release after release would be another onerous task.

Thankfully, this isn’t how web applications are written. A plethora of frameworks have evolved to provide pre-written code for common components like UIs, database management, and more. These frameworks provide ready code to manage common tasks, enabling the developer to concentrate on the application itself.

A background on frameworks

Frameworks are software that has been architected to ease, automate, and structure one or more aspects of application development. Just as there are varied subsystems and functions in a web application, there are frameworks that provide cookie-cutter implementations of those subsystems, which the application developer need not write.

Many dozens of frameworks cover popular languages used in web programming and applications. Owing to their popularity, Java and JavaScript have the largest ecosystem of frameworks out there, with 50 or more between them. JavaScript frameworks fall into three main classes: client-side, server-side, and template engines. Popular JavaScript frameworks include Node.js for server-side scripting, the Angular.js front-end web framework, and Vue.js.

One of the most popular frameworks for Java is Spring, which provides a wide range of functions such as object management, database connectivity, messaging, persistence, network communications, and user interface elements. Spring also enforces a certain software architecture by implementing programming paradigms such as inversion of control and aspect-oriented programming. In an application, the Spring framework provides almost all the common (and reusable) code, while the application code fills in the blanks with the application’s own objects and implements its business logic.

Many frameworks provide narrower, specialized facilities to simplify specific tasks. As a craftsman would likely use many tools from a toolbox for a given project, it’s common for a developer to use more than one framework in an application. For database connectivity and data binding, MyBatis is used to connect objects to SQL procedures or statements. An object-relational mapping (ORM) framework is another popular way of connecting database information to objects; Hibernate is a well-known example. In the domain of UIs and UI mapping to the underlying application, Struts, Apache Tiles, and Vaadin are some of the most widely used frameworks.

Analyzing applications for security

With such a broad range of frameworks available, it shouldn’t be a surprise that framework code makes up most of the code in an application. Therefore, security tooling used to scan the application must understand the framework code. Static analysis is a leading security mechanism to identify bugs and vulnerabilities in source code before deployment. A key benefit of static analysis is that it allows security to shift to the earliest phases of development, which reduces both the remediation cost and developer time spent resolving issues.

In your search for the strongest static analysis tooling option to implement within your team or organization, consider the depth and breadth of scanning. Top tools available on the market bring nearly 400 checkers to bear on a codebase, detecting both bugs and security issues (sometimes the line between the two is blurry).

Static analysis tools use a variety of techniques to analyze both framework and application code for vulnerabilities. For example, cross-module data flow tracking follows data as it originates from web requests and flows into the application’s functions, which helps identify sources and sinks for cross-site scripting (XSS) and injection scenarios. Look for a tool that detects issues with authorization, hardcoded passwords, certificate usage, insecure (non-SSL) communication, and issues relating to leakage of sensitive data.

One big challenge in analyzing framework-based applications for vulnerabilities is the flow of control between the framework code and application code. In the traditional model, the application calls into libraries as needed. But modern frameworks use the inversion of control model, where the framework and its components become the main body of the application, transferring control into your application at specific points in specific contexts.

Any control flow across subsystems can pass data, possibly tainted, from the web, into the framework, and on to the application—and tainted data coming in from untrusted sources are a potential source of injection attacks. Other issues related to framework code include buffer handling, certificate management, credential management, insecure connection settings, path manipulation scenarios, and so on.

An application using a framework isn’t secure if its framework code has exploitable vulnerabilities or insecure settings. Therefore, scanning the application code alone isn’t enough. Static analysis must cover the combined stack of application code and the frameworks it uses.

There are static analysis tools available that include a wide array of security-related checkers, many framework-specific. Checkers for Spring, Struts, Sequelize, and Socket.io are tuned to understand the frameworks’ behavior and interactions with applications. The result is high-accuracy findings and fewer false positives.

Broad coverage in a static analysis tooling solution frees up developers to focus on the application features and functionalities that require their attention and expertise. Be sure to implement a solution that not only understands the programming languages you use but can also identify and understand the frameworks you build your applications on.