Manual Source code review is one of the most essential skills for any penetration tester to have. This is one of the areas where even the experienced penetration testers are not comfortable. This is because there are multiple challenges associated with the manual code review.
One of the challenges is the familiarity with the language. As a penetration tester, we come across several languages and technology stacks. It is not feasible for a person to be proficient in all the programming languages. The other challenge is the size of the codebase. Often we come across the application which has a huge codebase and we have no idea where to start from.
In this blog, we are going to look at a few of the techniques which can help to get started with manual secure code review. The methodologies discussed in this blog are language agnostic so they can be used to review the code irrespective of the language.
A man is only as good as his toolsEmmert Wolf
Before starting the code review, it is important to have a certain set of tools at your disposal to perform the manual code review efficiently. Use an IDE which is supported by the language you are reviewing. An IDE is required for:
- Searching through the complete codebase
- Jumping to the method implementation using shortcuts
- Debugging (not mandatory)
VSCode is one of the IDE which supports multiple languages via plugins. This makes it a great IDE for code review of any language.
We can get away with this pre-requisite by using find/grep and a simple text editor, but it will certainly make life tougher and becomes time-consuming.
The other prerequisite is the ability to read and write code. As a penetration tester, if we want to review the source code, it is really crucial that we know at least one programming language. We should be familiar with basic programming constructs like loops, if-else conditions, switch-case etc.
Code Review Methodologies
Before starting the code review, we might have multiple queries in our mind like
- How to start?
- What to look for?
- Which areas to focus on?
In this section, we are going to look into various methodologies for reviewing the source code and identifying the security issues. I have tried to provide the analogy for all the techniques in order to relate it with real-world scenarios.
Reconnaissance is the first step of penetration testing where we try to understand the target system and gather as much information as possible. Apply the same concept while doing the code review. During the reconnaissance phase, get the feel of the codebase. Skim through the code repository and try to understand the structure of the codebase. This helps us to the coding pattern used and locate the important directories like:
- Route mappings
- Handler / Controller functions
- Authenticated and un-authenticated areas of the app
- Libraries used (open source, custom)
This gives us the overall idea of the code repository and a good starting point.
While reviewing the web applications / APIs, start with the unauthenticated area or publicity accessible pages because issues found on these pages can serve as an entry point to the whole application and these issues are considered more severe.
Keyword / Pattern Searching
The easiest way to start the code review process is grepping or searching for interesting keywords or patterns in the source code. This approach can also be termed as a bottom-up approach.
There are certain dangerous functions in every language which can lead to critical vulnerabilities like Remote Code Execution. We can use resources like SonarSource to identify such functions or vulnerable code patterns. SonarSource supports multiple languages and it can help to find the language-specific security issues by selecting the “Security Hotspot” tab. In SonarSource, select the language you are auditing and search the keywords in the complete codebase. If any such instances are found, start reviewing the code to validate if it is vulnerable. Look for the parameters accepted by that function and traceback till we reach the origin.
Unsanitized user input consumed by the dangerous functions is the prime reason for most of the vulnerabilities. This approach requires a general understanding of the programming concepts. The ability to read and understand the code in any language is sufficient to perform code review using this method.
This approach of reviewing the source code has few advantages like:
- Identifying low hanging fruits.
- Doesn’t require prior knowledge of the language.
But is this method really worth when most of the companies now have the automated static code analysis tool integrated with their development pipeline? There are multiple static analysis tools (free and commercial) which can easily identify such issues.
The answer is YES. Most of the security tools are integrated as non-blocking jobs in the CI/CD pipeline. This means that even if the security issues are reported by these tools, the build and deployment process continues without any failure. The problem is that these source code analysis tools are notorious for reporting a large number of false positives again and again (if not configured correctly). It’s not uncommon that the development team soon starts ignoring the reports from these tools. It is possible that a genuine issue slips in the list of hundreds of false-positive findings. This is where this approach of manual code review can help.
Source to Sink Approach
This is the more sturdy approach. This method can also be termed as top-down approach. Start with one functionality at a time. For eg, if you are reviewing the source code of an API, start with the handler/controller function which handles that URL route. From the handler function, move downwards and check all the intermediate function calls.
The downside of this approach is that for a very big codebase, it will be very difficult to cover all the functionalities and review their source code. It might not provide complete coverage, so it is very important to prioritize the important areas of the application. Some of the critical areas of any application which needs to be prioritized during the code review are:
|Authorization (Login, Register, Change / Forget password)||Timing Attacks|
|Authorization||Business Logic Flaws|
|Database Access||SQL Injection|
|Logging and Error Handling||Information disclosure|
|Cryptography||Usage of weak algorithms used like MD5|
(Note: The above list of critical areas and bug associated with them are not exhaustive and they are just used as examples)
Improper function usage
Some times even using the secure functions can result in security errors. Using the functions incorrectly can lead to unexpected behaviour. If you are reviewing any critical functionality say authentication or authorization, make sure to thoroughly look into the complete code and review ALL the intermediate functions calls – both internal (language-specific) and custom. Review the documentation of the internal functions and check for any warnings related to the usage of that function. Research for any security issues specific to those functions if used incorrectly. For example, the usage of addslashes() in PHP can result in SQL Injection. The same issue is highlighted in the comment section of the documentation. This shows the importance of reading the documentation carefully while doing the code review.
This is one of the most critical areas to look into while doing the code review. Most of the security vulnerabilities can be avoided by having robust input validation. Review the logic used for input validation. If regular expressions are used, review the regex to confirm it does not result in accepting unexpected or undesired inputs. Use sites like regex101.com to validate the regular expression. regex101.com supports multiple languages, and it is very helpful in validating the malformed inputs without running the application.
Review Logs / Debugging
This method might not be considered as a part of code review but is really efficient while reviewing big applications with a huge codebase. Having access to the real-time logs generated by the application or debugging at runtime eases the process of code review and helps to uncover hidden security and business logic flaws in the application. Access to the application and its backend infrastructure is required for reviewing the live logs (application and database). If access to the backend is not possible, try running and debugging the application locally if possible. This makes the code review process much robust and increases confidence in securing the application.
I hope this blog was informative and it will help you to get started with the manual code review. If you found this article helpful, please follow me on Twitter and subscribe to the mailing list (on the right sidebar) to get updates on my latest blogs. Feel free to provide your comments and feedback below.
Happy Learning 🙂