06/11/2012

The Da Vinci Cod(e) Review

Introduction

This article is going to talk about performing Web Application security code reviews the proper way (also known as my way). The best approach to perform a Web Application security code review would be to have at your disposal the Web Application (uploaded and running in a Web Server) and of course the Web Application code itself,  because you would be able to verify your findings in real time (e.g. exploit an Cross Site Scripting Issue immediately after you identify the issue in the code).


But first lets define what is a security source code review. A security code review is a systematic examination of a Web Application source code that is intended to find and fix security mistakes overlooked in the initial development phase, improving both the overall security of the software. Reviews are done in various forms such as pair programming, informal walkthroughs, and formal inspections. It is often done by independent contractors or an internal security team, hiring a third independent party to perform the code review adds value because it gives to the company the chance to examine its code by a person that has been engaged in the last stage of the development  process and has no "emotional attachements to the code" therefor has a unique perspective on the subject.

Types of code review

Code review practices fall into three main categories: 1) pair programming, 2) formal code review and 3) lightweight code review. Formal code review, such as a Fagan inspection, involves a careful and detailed process with multiple participants and multiple phases. Formal code reviews are the traditional method of review, in which software developers attend a series of meetings and review code line by line, usually using printed copies of the material. Formal inspections are extremely thorough and have been proven effective at finding defects in the code under review. Lightweight code review typically requires less overhead than formal code inspections, though it can be equally effective when done properly.

Lightweight reviews are often conducted as part of the normal development process:
  1. Over-the-shoulder – One developer looks over the author's shoulder as the latter walks through the code.
  2. Email pass-around – Source code management system emails code to reviewers automatically after checkin is made.
  3. Pair Programming – Two authors develop code together at the same workstation, such is common in Extreme Programming.
  4. Tool-assisted code review – Authors and reviewers use specialized tools designed for peer code review.
Important note: Tools can be used to perform this task but they always need human verification. Tools do not understand context, which is the keystone of security code review. Tools are good at assessing large amounts of code and pointing out possible issues but a person needs to verify every single result to determine if it is a real issue, if it is actually exploitable, and calculate the risk to the enterprise.

What is the most important thing in a code review

The most important is applying the proper Thread modeling. Threat modeling is an approach for analyzing the security of an application. It is a structured approach that enables you to identify, quantify, and address the security risks associated with an application. Threat modeling is not an approach to reviewing code but it does complement the security code review process. The inclusion of threat modeling in the SDLC can help to ensure that applications are being developed with security built-in from the very beginning. This, combined with the documentation produced as part of the threat modeling process, can give the reviewer a greater understanding of the system. This allows the reviewer to see where the entry points to the application are and the associated threats with each entry point. The concept of threat modeling is not new but there has been a clear mindset change in recent years.

Modern threat modeling looks at a system from a potential attacker's perspective, as opposed to a defender's view point. Microsoft have been strong advocates of the process over the past number of years. They have made threat modeling a core component of their SDLC which they claim to be one of the reasons for the increased security of their products in recent years.

There are at least three general approaches to threat modeling:

Attacker-centric

Attacker-centric threat modeling starts with an attacker, and evaluates their goals, and how they might achieve them. Attacker's motivations are often considered, for example, "The NSA wants to read this email," or "Jon wants to copy this DVD and share it with his friends." This approach usually starts from either entry points or assets.

Software-centric

Software-centric threat modeling (also called 'system-centric,' 'design-centric,' or 'architecture-centric') starts from the design of the system, and attempts to step through a model of the system, looking for types of attacks against each element of the model. This approach is used in threat modeling in Microsoft's Security Development Lifecycle.

Asset-centric

Asset-centric threat modeling involves starting from assets entrusted to a system, such as a collection of sensitive personal information.

The threat modeling

The threat modeling process can be decomposed into 3 high level steps:

Step 1: Decompose the Application:
  • Create use-cases to understand how the application is used.
  • Identifying entry points.
  • Identifying assets.
  • Identifying trust levels to external entities.
Note: This stage has to do with understanding the context of the Web Application and its surrounding entities.

The following images show the Business Architecture (Business Owner's Perspective) and Business Architecture Behavior of a Web Application:


Note: Lists the entities important to the business. Business entities can be a person, a thing or a concept that is part of or interacts with the business process (Proforma 2003). In the example of "XYZ-Match", the business entities include the following: Investors, Entrepreneurs, "XYZ-Match" web system.


Note: Lists the processes in which the business operates. In the example of "XYZ-Match", "Investor listing information to Venture Capital Directory" is one of such business processes.

Step 2: Determining and rank threats or else the threat categorization methodology:
  • Auditing & Logging
  • Authentication
  • Authorization
  • Configuration Management
  • Data Protection in Storage and Transit
Note: This stage has to do with mapping the vulnerabilities to a category.

Threat listing is an important part of a Web Application code auditing. Threat lists based on the STRIDE model for example are useful in the identification of threats with regards to the attacker goals. For example, if the threat scenario is attacking the login, would the attacker brute force the password to break the authentication? If the threat scenario is to try to elevate privileges to gain another user’s privileges, would the attacker try to perform forceful browsing? Categorizing and grouping the Web Application threats will help to see which Web Application security controls have the majority of the problems, it is like a blinking led that says "Hey I have multiple problems, save me please I am a poor cod dying out, save me".


Step 3: Determine countermeasures and mitigation.

Note: Such countermeasures can be identified using threat-countermeasure mapping lists.The risk mitigation strategy might involve evaluating these threats from the business impact that they pose and reducing the risk.

The objective of risk management should be to reduce the impact that the exploitation of a threat can have to the application (not to necessarily mitigate the risk!). This can be done by responding to a theat with a risk mitigation strategy. In general there are five options to mitigate threats
  1. Do nothing: for example, hoping for the best. 
  2. Informing about the risk: for example, warning user population about the risk. 
  3. Mitigate the risk: for example, by putting countermeasures in place. 
  4. Accept the risk: for example, after evaluating the impact of the exploitation (business impact). 
  5. Transfer the risk: for example, through contractual agreements and insurance. 
The decision of which strategy is most appropriate depends on the impact an exploitation of a threat can have, the likelihood of its occurrence, and the costs for transferring (i.e. costs for insurance) or avoiding (i.e. costs or losses due redesign) it.
  • Define the application requirements:
  1. Identify business objectives
  2. Identify user roles that will interact with the application
  3. Identify the data the application will manipulate
  4. Identify the use cases for operating on that data that the application will facilitate
  • Model the application architecture:
    • Model the components of the application
    • Model the service roles that the components will act under
    • Model any external dependencies
    • Model the calls from roles, to components and eventually to the data store for each use case as identified above
  • Identify any threats to the confidentiality, availability and integrity of the data and the application based on the data access control matrix that your application should be enforcing
  • Assign risk values and determine the risk responses
  • Determine the countermeasures to implement based on your chosen risk responses
  • Continually update the threat model based on the emerging security landscape.
Simple tools to use for code auditing

Graudit is a simple script and signature sets that allows you to find potential security flaws in source code using the GNU utility grep. It's comparable to other static analysis applications like RATS, SWAAT and flaw-finder while keeping the technical requirements to a minimum and being very flexible. Graudit supports scanning code written in several languages; asp, jsp, perl, php and python.

Graudit usage: graudit /path/to/scan

Graudit prerequisites: bash, grep, sed 

The following picture shows a screenshot of the tool:


Note: You can download Graudit from this link. The basic concept behind this tool is to that you provide the tool with a list chunk of code lines searches for them. As an alternative of Graudit you can use common command windows tools such as findstr and find.

The findstr command line windows tools allows to search for text (as specified with pattern in the file file-name. If file-name contains wildcards (* or ?), it searches in all files that match. The option /S searches in the current directory as well as in its subdirectories. If pattern contains spaces, it must be specified like so /C:"some text to be searched". In order to turn pattern into a regular expressions, the /R option must be used. The /I option searches case insensitive. It is possible to pipe the result of another command through findstr. 

For example, the following command finds all files whose name contain either an m or a p: 

C:\> dir /B | findstr /R /C:"[mp]"

Note: You can find more examples for findstr in the Microsoft command line page.

Cod(e) reviewing for SQL Injection

Use Database stored procedures, but even stored procedures can be vulnerable. Use parameterized queries instead of dynamic SQL statements. Data validate all external input: Ensure that all SQL statements recognize user inputs as variables, and that statements are precompiled before the actual inputs are substituted for the variables in Java.  A simplified way of thinking about SQL injection when talking about security code reviews would be to emphasize in multiple type casting checks through out the whole Web Application system. For example type casting should occur in at least two different places the Web Application input validation filter and the Web Application connected database. Additional layers of defense can be added through a Web Application Firewall (WAF) and a Database Application Firewall.  

The following picture shows a sequence of yes and no flow chart explaining an SQL injection flow:



Note: This is a very simplified SQL Injection threat model.

The actual code in java that introduces the SQL Injection vulnerability originally to the code:

// Define variable to use

String DRIVER = "com.ora.jdbc.Driver";
String DataURL = "jdbc:db://localhost:5112/users";
String LOGIN = "admin";
String PASSWORD = "admin123";

Class.forName(DRIVER);

//Make connection to DB 

Connection connection = DriverManager.getConnection(DataURL, LOGIN, PASSWORD);

String Username = request.getParameter("USER"); // From HTTP request
String Password = request.getParameter("PASSWORD"); // From HTTP request
int iUserID = -1;
String sLoggedUser = "";
String sel = "SELECT User_id, Username FROM USERS WHERE Username = '" +Username + "' AND Password = '" + Password + "'"; 

Statement selectStatement = connection.createStatement ();

ResultSet resultSet = selectStatement.executeQuery(sel);

if (resultSet.next()) { 
   
     iUserID = resultSet.getInt(1);

     sLoggedUser = resultSet.getString(2);
}

PrintWriter writer = response.getWriter ();

if (iUserID >= 0) {

      writer.println ("User logged in: " + sLoggedUser); 

}  else {
   
    writer.println ("Access Denied!"
}

When SQL statements are dynamically created as software executes, there is an opportunity for a security breach as the input data can truncate or malform or even expand the original SQL query. Firstly, the request.getParameter retrieves the data for the SQL query directly from the HTTP request without any data validation (Min/Max length, Permitted characters, Malicious characters). This error gives rise to the ability to input SQL as the payload and alter the functionality in the statement.

Epilogue

Educating developers to write secure code is the paramount goal of a secure code review. Taking code review from this standpoint is the only way to promote and improve code quality. Part of the education process is to empower developers with the knowledge in order to write better code. This can be done by providing developers with a controlled set of rules which the developer can compare their code to. Automated tools provide this functionality, and also help reduce the overhead from a time perspective. A developer can check his/her code using a tool without much initial knowledge of the security concerns pertaining to their task at hand. Also, running a tool to assess the code is a fairly painless task once the developer becomes familiar with the tool(s).

References: