SAST for the People

Lacework EditorialJuly 26, 202410 min read

Authors: Vaggelis Altidakis, Jeremy Dubreil, Ibrahim Elsayed, Pascal Kesseli, Peter O’Hearn, Francesco Parolini, Christien Rioux, Linpeng Zhang

Lacework has developed an approach to securing first-party code that supports different users and constituents within DevOps and security teams. Our approach delivers capabilities that teams need for efficient product development, instead of requiring them to change their behavior to accommodate how traditional code security tools work. 

Companies in need of Static Application Security Testing (SAST) tools often have two distinct and divergent requirements. On the one hand, security teams value and expect deep exploitability analysis and are usually more willing to do more up-front work to achieve lower false positive and negative rates. On the other hand, DevOps want to scan everything to get a baseline and have that data quickly integrated into developer workflows; they are often interested in understanding overall risk and need to be able to scale to thousands of repositories without manual intervention. Companies mistakenly assume that a single SAST offering can provide what they need.

As a result, the people that need broad analysis, like developers and DevOps, are often overwhelmed by tools that take too long to run, require hand-holding, and generate too many false positives. At the same time, security teams often fail to get enough value due to high false negative rates or become frustrated with the extensive manual validation required by high false positive rates.

Lacework has proposed a novel approach to this problem. Rather than a single tool that disappoints both audiences, Lacework SAST was developed to meet the needs of developers and security teams, and their respective requirements. Together, Lacework FastSAST and DeepSAST help customers secure first-party code.

FastSAST: SAST for developers

Main User Persona: Developers

Goal: First-party risk management. Anti-patterns in first-party code 

Workflow: CLI, PR integration, UI

Expectations: Breadth in language coverage, buildless, fast, no hand-holding, low FP rate

FastSAST is a new approach to SAST which meets developers where and how they work.

The prime job of a developer is to create features as part of products or infrastructure. Lacework FastSAST helps developers produce secure code without slowing them down. Rather than diverting developers to a separate UI or disrupting existing workflows, FastSAST delivers security findings directly to developers within their IDEs and PR requests. Our approach helps developers quickly write more secure code.

Four principles guide the design of FastSAST for developers as part of this family of tools. First, the ability to run on pull requests or in an IDE has implications for how the tool operates. 

1. FastSAST is “buildless” and runs in seconds  

A “buildless” approach means that the security analysis does not rely on being able to build the code or on built artifacts. Instead, it is possible to analyze code without the need to find build commands, download dependencies, or perform other activities. This saves significant time in getting started and reduces the time-to-first-bug. FastSAST can even, in principle, run on code that can’t yet be built, such as code snippets that might come across in an IDE, as the code is being written. 

Although ignoring dependency information coming from the build system may increase false negatives, allowing the analysis to produce results quickly by skipping the build steps is critical for the integration with the development workflow. However, a buildless approach does not necessarily impact the false positive rate.

2. FastSAST prioritizes low false positives over low false negatives; ideally it has very low or no false positives

A low false positive rate is important, but alone doesn’t achieve the goal of saving developer time. Even a low false positive analysis can be difficult for developers to use if understanding an alert requires deep security expertise and global context which each person may not have. FastSAST aims to deliver security findings that are easy for developers to understand and action.

3. FastSAST warnings are easy to address

In order to achieve the above outcomes, FastSAST focuses on locally checkable code practices rather than flaws requiring additional security knowledge. Below we give an example where FastSAST detects a potentially dangerous use of concatenation in an SQL command (this use might or might not be exploitable, depending on the surrounding code).

4. FastSAST finds violations of secure coding practices

These points work together in the delivery of FastSAST. Focusing on coding practices (4) helps keep warnings simple and easy to understand (3) without the need for deep security expertise. Focusing on violations rather than confirmations of practices (4) helps minimize false positives (2). Searching for bad practices (4) in a straightforward but incomplete manner (2) can be achieved through simple local checks. These checks can be implemented in a buildless analysis (1), allowing for a fast time to the first bug detection and can be run on pull requests or within an IDE.

Example: Avoid feeding concatenated strings to a raw SQL query

The use of prepared statements when constructing SQL queries is a well known good practice that helps avoid SQL injection attacks. Depending on the engineering context, constructing every SQL query this way might be too noisy. However, concatenating strings directly fed into an SQL query is a poor coding practice that should be avoided, as it is a common way an SQL injection can occur.

For example, if we have an SQL query string

1 "SELECT * FROM users WHERE username = '" + name + "' AND password = '" + pwd + "'"

Then if the user can pass “admin” for name and "' OR '1'='1" for pwd,the string resolves

1 "SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'

And the result is that the password check is skipped.

FastSAST identifies these bad practices with local reasoning which stays within a single function. The following Java code includes an instance of this bad practice. 

While not by itself a vulnerability, this code is dangerous in the sense that it can be used in such a way as to lead to an SQL injection. This can be the case if, for example, injectibleQueryConfidentiality(name,auth_tan) is called with user-controlled parameters.

Running FastSAST in the VS Code IDE gives the following alert on this code.

When the code is fixed using a prepared statement, it prevents the risk of malicious data being injected into the query and FastSAST no longer alerts.

Insecurity Invariants: Designing FastSAST for low false positives

Accurately predicting whether concatenated strings can be safely fed into an SQL query is generally difficult and considered a classic undecidable problem. A powerful approach to tackling undecidable problems is to rely on approximations. These approximations may not always provide complete answers, but when they do, they are often accurate. FastSAST is targeted at developers to help them prioritize the reduction of false positives over false negatives by under-approximating the possible bugs. This under-approximation approach is implemented through the concept of an Insecurity Invariant.

The basic approach is summarized in the following diagram.

The “best practice” is captured as a program property, the Security Invariant. The Insecurity Invariant is a program property that indicates a best practice has been violated. Critically, when the invariant does not hold, we can’t conclude that the best practice is being followed; it is more important that it be easy to check in an automated fashion. Our implementation of the FastSAST rule for concatenated strings into an SQL query is based on an easily verifiable invariant that (with certain assumptions) implies bad practice.

Security Invariant: a concatenated string is never fed to an non parameterized SQL query

Insecurity Invariant: a concatenated string is fed IMMEDIATELY, within one function, to an non parameterized SQL query

Assuming the quality of our reasoning within a single function, this invariant identifies a bad practice. However, the invariant can’t detect bad practices that span multiple functions. For example:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Test extends HttpServlet { @GET @Path("/path") public static void fastSAST_false_negative( @QueryParam("") String a, @QueryParam("") String b) { try { Connection c = DriverManager.getConnection("what", "ev", "er"); // DeepSAST reports the SQL injection on the line below ResultSet r = c.createStatement().executeQuery(wrap(a, b)); } catch (Exception e) { System.out.println(e); } } public static String wrap(String a, String b) { String s = "SELECT * FROM users WHERE username='" + a + "' AND password='" + b + "'"; return (s); } }

It is possible to extend FastSAST to catch this specific example while maintaining a low false positive rate by implementing an under-approximate form of inter-procedural analysis. However, for computability reasons, no ultimate extension exists that can completely eliminate false positives and false negatives. Our approach for FastSAST is to continue to prioritize reducing false positives – even if it results in an increase in false negatives.

Our FastSAST design involves identifying an easy-to-check insecurity invariant for each CWE that implies (but is not necessarily equivalent to) a bad practice. In a sense, our approach is the inverse of that of type systems which identify invariants that imply good practice. In scientific terms, our approach is to under-approximate whereas type systems are to over-approximate.

DeepSAST: SAST for security engineers

Main User Persona: Security Engineers Goal: Identify 0-day vulnerabilities in first-party code Workflow: Scheduled runs, UI

Goal: Identify 0-day vulnerabilities in first-party code

Workflow: Scheduled runs, UI

Expectations: Depth in selected languages, may require build, some hand-holding, low false negatives

The main goal of DeepSAST is to analyze all of the code paths in an application and detect those that are potentially exploitable first-party codebases. Its findings are similar to those reported by security team, detailing ho user-controlled data can be manipulated to gain unauthorized access to other parts of the applications, such as:

  • Access to restricted parts of the filesystem (Path traversal) 
  • Protected databases (SQLi)

DeepSAST produces an exhaustive and complete list of findings and based on exploitability enables security analysts to easily determine which attack scenarios are the most likely. For example, DeepSAST would identify that the method injectableQueryConfidentiality described above is invoked by another method like this one:

DeepSAST identifies that the variables name and auth_tan are user controlled (this allows malicious users to control the SQL query being executed to access arbitrary data in the database).

Returning to the fastSAST_false_negative() example above, DeepSAST detects that executeQuery(wrap(a, b)) will eventually run the SQL query where the user controlled variable a and b can be maliciously crafted to alter the query and bypass the protection. However, FastSAST will not consider this case since the concatenations of strings to create the SQL query and execution of the query happen in different methods. Then, iffastSAST_false_negative() is called with user-controlled input similar to the completed() example just given, DeepSAST will report a potential SQL injection; fastSAST_false_negative() is a true positive.

In this context, most of the rules in FastSAST come from the realization that a large part of real attack scenarios, like the ones reported by DeepSAST, can be reduced to a missing best practice. The above scenario related to the use of string concatenations instead of parameterized queries illustrates this situation. Errors identified by FastSAST can be configuration issues, use of deprecated APIs, or the misuse of standard libraries. Each of these can be easily explained to product teams without requiring the global security context of an application. They’re also easy to address locally (ideally before the code is ever merged).

Internal testing suggests that more than half of DeepSAST findings could be avoided by fixing identified FastSAST issues along the trace, making FastSAST the first line of defense for secure code development.

Technical background

The division between FastSAST and DeepSAST mirrors and is influenced by the experience of static analysis at Facebook. In that case, the tool Infer focused on developers and evolved to become under-approximate (exploring a strict subset of the paths, to favor false positive reduction). Another, Zoncolan, focused on security engineers. Its foundation was based on over-approximation (covering all the paths). The Lacework DeepSAST offering is built on top of a close relative of Zoncolan, the Mariana Trench analyzer. One difference between Infer and FastSAST is that the latter focuses on bad practices rather than definite errors, (again influenced by the Zoncolan experience). Finally, our approach using insecurity invariants is related to and influenced by fundamental work on symbolic execution and incorrectness logic.

FastSAST and DeepSAST are currently available for existing Lacework customers, with wider availability expected later this year. See this codesec demo and contact us for further availability and pricing information.

Categories

Suggested for you