Introduction to Code Review



This course is an introduction to performing source code review to find security vulnerabilities in web applications. The application we are going to work on is a simple PHP application that allows users to upload and download files. Think of it as a over-simplified Dropbox. This exercise will also cover the different methods that can be used to perform code review.


Reasons for doing code review

There are multiple reasons for doing code review:

  • It can be faster than penetration testing. Some issues are really easy to spot during a code review (for example weak encryption), where others can take a lot more time (XSS for example).
  • Compliance can require you to perform security code review (for example as part of PCI DSS 6.3.2).
  • After doing penetration testing for a while; you want to do something different.
  • You want to find better bugs. Some of the bugs you will find during a code review can be surprisingly hard to discover with black-box testing.
  • You want to check if some code is backdoored (it’s actually really hard to do).
  • You want to write an exploit for a bug.


There are plenty of ways to perform code review. You can find some of the methods below:

  • String matching/Grep for bugs.
  • Following user input.
  • Reading source code randomly.
  • Read all the code.
  • Check one functionality at a time (login, password reset…).

String matching/Grep for bugs

This is probably the fastest way to find low-hanging fruits; you just try to find patterns of known vulnerabilities. For example, you can use grep to find calls to the PHP system function:

<code>$ grep -R 'system($_' *

You can find a list of regular expressions to try on your code base in the GRaudit project (

This approach suffers from a lot of limitations:

  • You don’t get a lot of coverage/assurance on the quality (and therefore security) of the source code. You just know that based on your list of patterns, you couldn’t find any issues.
  • You need to know of all the dangerous functions/patterns.
  • You end up using very complex regular expressions.

This approach works pretty well for timeboxed reviews where you don’t have enough time. It can also help you get familiar with a code base as part of a longer review. However, it’s probably not the best way to perform proper reviews.

Following user inputs

Another way to go about doing a review is to follow all the user-controlled inputs and find all ways to access the application (the routes/URI available)

To get started you need to find all the ways to provide data to the application (example in PHP):

  • $_POST / $_GET / $_REQUEST
  • Data coming from the database (for stored XSS and second-order injections for example)
  • Data read from a file or a cache

This method provides good coverage. However, you will need a good understanding of the framework/language used. Finally, you may end up reviewing the same function again and again if it’s called multiple times.

By functionality

Another common way to do a review is to pick one functionality, for example:

  • “Password reset”.
  • “Database access”.
  • “Authentication”.

And review all the code associated with this functionality. This work especially well if you do this across multiple applications/framework as they will all have different behaviors.

This approach gives you an excellent coverage for the functionalities your reviewed and will teach you what mistake people usually make for a given functionality. However, you only have coverage of what you reviewed.

Read everything

Finally, the more time-consuming way: just start reading the code one file at the time. A better ways to do this is to try to find weaknesses, not vulnerabilities. Then trying to see if the weaknesses can become vulnerabilities on their own or by combining them.

This method is obviously the most laborious way of working but it brings excellent coverage. It’s crucial to keep good notes when using this approach.

What to look for?

When doing a review, you need to look for everything:

  • Weird behavior
  • Missing checks
  • Complexity
  • Security checks already in place
  • Differences between 2 functions/methods/classes
  • Comparison and conditions (if/else)
  • Regular expressions/string matching
  • What is missing?

You will probably end up seeing function/class/method you don’t know. To solve this issue, you need to

  • Google it
  • Test its’ behavior

It’s going to take time (especially early on) but the more code you review, the easier it gets. Make sure you create a snippet with the function/class/method to test its’ behavior. It will be convenient for your future reviews. To test it, you need to run it locally and try to find some edge cases that the developers may have missed.


Getting started

For this exercise, you have a really simple web application. We are going to go with the “Read everything” approach as there isn’t that much source code to read.

To get started, don’t focus on finding vulnerabilities, try to find weaknesses:

  • “That doesn’t seem right”
  • “What happens if I put [X] here”

Then, try to see if these weaknesses can become vulnerabilities. Either on their own or by combining them.

The application

The application is a straightforward application with a dozen security issues. As a user, you can only:

  • Register/Login/Logout
  • Upload and retrieve file

To get started you can get the code:

You can use the tool cloc ( to get a better idea of the size of the application:

<code>% cloc .
     14 text files.
     13 unique files.                              
      2 files ignored. v 1.72  T=0.11 s (120.6 files/s, 46503.2 lines/s)
Language                     files          blank        comment           code
CSS                              2            676             11           3973
PHP                             10             48              4            289
SQL                              1              5              0              5
SUM:                            13            729             15           4267

List of weakness

You can find below the list of issues:

  • Hardcoded credentials or secrets
  • Information leak
  • Missing security flags
  • Weak password hashing mechanism
  • Cross-Site Scripting
  • No CSRF protection
  • Directory listing
  • Crypto issue
  • Signature bypass
  • Authentication bypass
  • Authorisation bypass
  • Remote Code Execution

Leave a Reply