In the modern world, software is everywhere. Software houses and programming enthusiasts produce millions of lines of code that other specialists use transparently. Maintaining a high level of security for such software snippets is essential, but unfortunately, this level of security is not largely met.

Nowadays, whether an application consists of just a few lines of code or is a big and complex program, it most likely relies on additional libraries. Those dependencies facilitate the developer’s work, speed up the creation of a product, and significantly enlarge the code base… as well as the number of bugs. Also, considering that code is written by people – and no one is infallible – it’s impossible to have an entirely bug-free piece of software. The code review process helps to eliminate software bugs, but the outcome is also prone to human error.

Why does auditing code for vulnerabilities matter?

The penetration test is a time-limited operation, so finding all the security issues during the process is almost impossible. Due to limited budgets, companies often take the black box approach, auditing software without prior knowledge about how the system works. Black box testing further limits the likelihood of finding security bugs. 

Even a team of cybersecurity specialists will be unable to find every issue. There is only limited time to carry out white box tests, so some bugs can remain undiscovered.

Unfortunately, cybersecurity criminals aren’t restricted by time or money. They have unlimited resources to analyse the software and find security flaws they can exploit.

To prevent a successful cyberattack, one should carry out a security code review. It’s the process of inspecting source code to detect and eliminate vulnerabilities and security flaws.

The assessment can be conducted as follows:

  • manually by a person,
  • in an automated way, using security code review tools,
  • or by combining those two approaches.

Security code review vs code review

While regular code reviews focus on the quality of the code, security code reviews focus on its secure aspects, like string concatenation of database operations or authentication configuration.

A security bug is a specific type of software flaw that allows an action, that the application’s author didn’t intend, to take place. For instance, the wrong application parameter handling can lead to an attacker injecting additional SQL queries and retrieving sensitive data, like passwords, from the database.

How to perform a security code review 

There isn’t a structured way to perform a security code review, although it can be done with the help of well-known standards like: 

  • OWASP TOP 10, 
  • Mitre Top 25 Most Dangerous Software Weaknesses, 
  • PCI-DSS, 
  • or HIPPA.

Every programmer should be aware of the standards and go through at least OWASP TOP 10 cheat sheet. Of course, they should also follow an organisation’s internal security standards. 

If applied, such knowledge can increase the code’s security level in the development stage.

Automated security code review

Apart from manually scanning the code, the audit can be performed using automated security code review tools. They can be divided into two groups: 

  • SAST – Static Application Security Testing, 
  • DAST – Dynamic Application Security Testing. 

Static Application Security Testing (SAST)

SASTtools are simple scanners with rules that aim to find the code’s patterns. The effectiveness of this approach depends on the quality of the set rules. SASTtools are language-dependent, so if the software is written in a rare programming language, in some cases the automated analysis cannot be performed. Regarding the Secure Software Development Life Cycle (S-SDLC) framework, the SAST analysis should be triggered during the application build process to spot security issues as soon as possible.

Dynamic Application Security Testing (DAST)

DAST tools are independent of the technology stack. They test and exploit the application during its runtime. The DASTtools don’t need to access the source code, which is a significant advantage in some situations. Their main drawback is that they can’t find all the security flaws; what’s more, to interpret the results, technical security knowledge is required.

Tools for automated security code review

Tools can also help to find “low-hanging fruit” when dealing with large amounts of code. Most of them are grep-like tools which look for a predefined sets of rules, keywords, or technology-specific functions. For instance, (Java Spring framework case): find the following piece of code: “csrf().disable()”; if this code is found, report this situation as a security issue as the anty Cross-Site Request Forgery mechanism is disabled.

SonarQube or semgrep are examples; both are open-source platforms for analysing static code to find bugs and detect vulnerabilities in dependencies.

There are also tools that offer a more advanced approach enabling the use of internal language, writing advanced rules and querying the code. They can even handle queries such as “find all the methods” (while in object-oriented programming, “a method” is another term for a function), where code responsible for authorisation is not present. 

A greater range of possibilities also requires greater domain skills. To write such queries, one should have a certain degree of security knowledge, that may be regulated by the code writing style. For external auditors this approach is prone to false positives and false negatives. However, it can be an excellent solution for engineers that are part of an internal development team.

Monitoring of dependencies

As mentioned, dependencies are an integral part of the software. Usually, libraries are more extensive than the software itself, and using them expands the threat surface as well. Reviewing the code to ensure the security of third-party dependencies is barely possible, as the time for delivering the product is always strictly limited. Fortunately, tools like OWASP Dependency Check or npm audit can address the time constraintThanks to many researchers reporting vulnerabilities, those tools always have an up-to-date list of the most popular and recent security issues.

Manual security code review 

The main advantage of a manual security code review is that it’s carried out by an auditor who understands the business logic and validation, and can find vulnerabilities in it. This kind of code review is performed with the use of an IDE tool (integrated development environment). Depending on which language the audited application is written in, usually VS Code or IntelliJ are sufficient.

Where should you start the manual security code review?

To perform a manual security code review, the best and simplest approach would be to read the code from the beginning. But in most cases, there is no such thing as one point where the program begins. 

For instance, applications designed in the MVC principle can consist of tens of controllers with hundreds of actions, each of which can be treated as “the beginning”. In that case, the code can be read from the action (controller level) through the service layer into the model layer, where database operations are stored. That approach makes sure that every API method is checked. 

Another strategy is to read the code from the bottom (database layer) to the top (controller layer). In the case of SQL injection vulnerability, it will be easier to identify affected endpoints or methods. 

Also, you can look for technology-specific functions that can lead to vulnerabilities – like system() or shell_exec() in PHP, or eval(), setInterval() in JavaScript – and analyse the path or flow within the code to determine whether it is possible to inject malicious code into the functions. 

The strategy depends on several factors, like the number of code lines (LoC), time granted for the review, or technology stack.

Configuration files and sensitive data 

Another critical step of a code security review is checking the configuration files. In many cases – especially in non-public code repositories – configuration files contain sensitive data like passwords, API keys, or other types of secrets. Sensitive data stored in the code repository is treated as compromised; thus, secrets, passwords, or API keys should be re-generated and stored in secure places, like vaults. Configuration files must contain only placeholders for values, not values themselves.

In case of vulnerability identification, confirming the finding and exploiting the issue in the application runtime is a good practice. There are cases where, through reading the code, an auditor identifies a security issue, but the framework’s security mechanisms apply a protection layer so, as a result, the flaw can’t be exploited.

Keep your application secure

Reviewing software code is a challenging task. Still, by doing it methodically with the support of automated tools, it is possible to cover more threat landscapes, ultimately having more impact than in any other type of security audit.

If you want to ensure a high level of security in your application, contact us. Together, we’ll discuss the needs and scope of the security audit. Here you’ll find more information on how we can help you.

About the author

Piotr Izak Senior Cybersecurity Pentester

Piotr Izak

Senior Cybersecurity Pentester