SAST and DAST are two different approaches used to search for errors and vulnerabilities in the code. It's better not to choose one or the other but apply both methods. Let's discuss the pros and cons of SAST and DAST.
In this article, you are not going to learn which methodology is better or worse. We should not oppose them, because they complement each other. It's like saying that an excavator is better than a crane when it comes to building a house — you just can't compare these two different things. The same is with SAST and DAST.
Static Application Security Testing (SAST) is a testing technique that uses static analysis to check application source code for errors and vulnerabilities.
Dynamic application security testing (DAST) is a testing technique that simulates malicious external attacks trying to exploit common vulnerabilities.
The purpose of SAST and DAST is to protect an application from zero-day vulnerabilities. Zero-day vulnerabilities are vulnerabilities that can be found and exploited by attackers. The term "zero-day" means that developers had 0 days to fix errors. In other words, the purpose of SAST and DAST is to detect security defects at the application development stage and prevent exploits by attackers.
You can find more details about security techniques in the following article: Application Security Testing. How not to get confused between SAST, DAST, and IAST.
The main difference is that SAST handles the application source code only, while DAST should be used with running compiled source code on various sets of input data.
SAST and DAST detect two different sets of errors that only partially overlap each other. Let's figure out why.
void foo(struct Object *p1, struct Object *p2)
{
if (p1 == NULL || p1 == NULL)
return;
if (memcmp(p1, p2, sizeof(p1)) == 0)
start();
}
This C code contains two errors at once. The first typo: the p1 pointer is checked twice, and the p2 pointer is not checked. The second typo: the sizeof operator calculates the size of the pointer, not the object.
SAST easily detects such errors. For example, the PVS-Studio analyzer issues the corresponding warnings:
These errors are hidden from DAST. Actually, their detection depends on a combination of circumstances. DAST handles compiled code. This binary code will be equivalent to the following source code:
void foo(struct Object *p1, struct Object *p2)
{
if (p1 == NULL)
return;
if (memcmp(p1, p2, 8) == 0)
start();
}
The compiler will remove the repeated pointer check. Therefore, there is no reason to suspect that the condition is incorrect. The error will be noticed only if the p2 pointer turns out to be null and is passed to the memcmp function. However, we don't need a special tool for this — we'll notice access violation anyway.
Instead of the sizeof(p1) expression, the binary code will use the value 8 (it is assumed that we are compiling a 64-bit program where the pointer size is 8 bytes). The possibility of detecting an error depends on the size of the Object:
Does this mean that SAST is more useful than DAST? Of course not. Let's take a look at another case.
size_t foo(size_t n)
{
if (n < 3)
return 0;
size_t *arr = (size_t *)malloc(sizeof(size_t) * n);
if (arr == NULL)
return 0;
for (size_t i = 0; i < n; i++)
arr[i] = i;
size_t indexOutOfBounds = arr[n - 1] + arr[n - 2];
size_t x = arr[indexOutOfBounds]; // Bug
free(arr);
return x;
}
Dynamic analysis can easily detect an error in this code. Suppose the function receives the value 10. Then the value of the indexOutOfBounds variable will be 8+9=17. An array index out of bounds, containing only 10 elements, occurs. Dynamic analyzers can easily detect such cases, while static analyzers are unlikely to find them.
To find the error, a static analyzer has to virtually execute this program, create arrays, store values in them, and so on. Theoretically, this is possible. However, in actual practice, such a tool would run extremely slowly — the analysis would take a lot of time. To learn more about what static analyzers can't find, read the following article: What static analysis cannot find.
Note. Perhaps, some static analyzers will manage to find this error. However, that's only because the code is simple, and only one function contains all the logic. If the case is a bit more complicated, the static analyzer is unlikely to help you.
As you can see, SAST and DAST search for different types of errors in different ways. It is better to use them both to identify the maximum number of security errors and defects (security weaknesses).
SAST helps identify components with known vulnerabilities and potential vulnerabilities in the application code. If the vulnerability is known and described in one of the vulnerability databases, then static analysis can import information from the database and use it to check the project's components. This is called SCA (software composition analysis).
SAST also identifies potential vulnerabilities. The analyzer cannot understand whether a particular error in the code is a real (exploited) vulnerability. However, if the error is classified according to the Common Weakness Enumeration (CWE), then it might indeed indicate the vulnerability. That is, we have a potential vulnerability that should be fixed.
An important part of vulnerability detection is taint analysis (taint checking). It allows you to track the distribution of unverified external data across the program. If such data gets into code key points, this can lead to various vulnerabilities, including SQL injection, cross-site scripting (XSS), path traversal, and others.
DAST also helps identify vulnerabilities with the help of fuzzing testing.
Fuzzing is a testing technique that injects invalid, malformed, or unexpected input into an application to track the system's behavior. If the system crashes/hangs/behaves incorrectly, there's an error.
Unlike static analysis, fuzzing reveals defects in code that certainly occur while the application is running. In other words, there's no false positives in this approach — and this is its great advantage over SAST.
Let's sum it up. It should be noted that this table does not represent the best or the worst approach. It demonstrates differences in two methods. The fact that these are two different approaches means that it's better to use both SAST and DAST to create high-quality and secure applications.
SAST |
DAST |
---|---|
White box testing (analyzers handle the source code of applications). |
Black box testing (actually, some analyzers introduce additional checks into the code and, in fact, they also deal with the source code of applications). |
False positives occur (it takes some time to decide whether to edit the code or to suppress the warning). |
False positives do not occur. |
Requires the source code of applications. Uses static code analysis to search for defects. |
Does not require the source code. Requires running compiled applications. |
Errors and vulnerabilities can be detected at the earliest stage of SDLC (during code writing). |
Errors can be detected during the application development process and after. |
Low cost of fixing bugs and vulnerabilities (defects are detected almost immediately after they appear in the code, so they are easy to fix). |
The cost of fixing bugs and vulnerabilities is slightly higher (developers find out about the defects after some time when they are busy with other functionality). |
Full code analysis (you can check even those parts of the code to which control flow is rarely transferred). |
It's difficult to achieve high code coverage (requires excessive resource usage to prepare input data sets needed to execute as many code branches as possible). |
Examples of tools: PVS-Studio, Coverity, Klocwork, SonarQube. |
Examples of tools: AddressSanitizer, BoundsChecker, Valgrind. |