in , ,

Code Auditing | Methods, Tools, Books, Testing and Checklists

A comprehensive guide from industry leaders on how to code audit.

Introduction

This article aims to be a resource for beginner and expert code auditors alike, providing guidance and recommendations on everything from code auditing tools, to books and even example code. The overall goal here is to help people write more secure code, faster.

This article was a collaborative effort between TurgenSec and several industryleading professionals. To find out more about who contributed click here or scroll to the bottom of the article.

What is code auditing?

A software code audit is a comprehensive analysis of source code in a programming project with the intent of discovering bugs, security breaches or violations of programming conventions. It is an integral part of the defensive programming paradigm, which attempts to reduce errors before the software is released.

C and C++ source code is the most common code to be audited as many higher-level languages, such as Python, have fewer potentially vulnerable functions (e.g., functions that do not check bounds).

Source: en.wikipedia.org/wiki/Code_audit

Why code auditing should be your number one priority

Ensuring code quality should be one of your primary concerns as a developer. It’s very easy and simple to solve a particular problem and have it execute on your localhost 100% of the time, but how can you guarantee that it will run on the production server, or even just on a different machine locally?

How can you ensure that if some of the key inputs change or aren’t available a later time when your function runs that you will still receive a response that’s useful (even if that is an error)?

Methods for code auditing

Before attempting to code audit you should create a checklist of core issues to look for such as security holes, authentication issues, authorization issues, memory leaks, and bad design practices.

The University of Washington has published a useful checklist to get you started. It can be found here.

Linting

If you’re not linting your code, it’s likely you’re making some very simple mistakes – you could be the best programmer in the world and still mis-type the name of a variable.

A ‘linter’ checks for common errors in code (semi-colons at the end of lines, that variables are available within the scope you’ve used them, that your indentation or white space conforms to that standards you’ve set or are required by the programming language etc.). A lot of integrated development environments (IDEs) or text editors will have plugins that can highlight code as you write or save it to ensure you’ve (at the very least) written code that is coherent to a machine.

Examples

To give a basic overview, let’s see how a basic linting instruction looks like. We’ll use the most commonly used linter which is eslint a linter for JavaScript. After setting up eslint in your project, you’ll see a .eslintrc file where all the changes are to be made.

Warning generation for unused variables

A lot of times while writing code, we declare some variables that are never used. With the help of a linter, we can generate a warning whenever there is some unused variable in a program. The code for this rule is:

{
    "rules": {
        "no-unused-vars": "warn"
    }
}
Instruction to use only single quotes in the code

Now, this linting instruction will take care of the fact that only single quotes are used in the code, except when we use double quotes to avoid escaping a single quote or apostrophe in the string.

{
    "rules": {
       "quotes": [2, "single", { "avoidEscape": true }]
  }
}

Additionally, you can add linting plugins to your code compiler to highlight errors in the terminal, and as a good final step you can ensure a linter runs on pull requests in GitHub (or other code versioning tool) and enforces your specified rules prior to allowing you to merge a branch.

Test Driven Development (TDD)

The principle of TDD is that you know exactly what a given function will be expected to do under all circumstances before you write a line of code that your users will run.

You will layout your inputs, outputs, and edge cases and capture them in unit tests. You can then run these tests from your compiler as you develop to ensure that your expectations at the planning stage match the final product. This produces very high-quality code (assuming your assumptions about what your function is doing are correct) but adds a time overhead to producing working code.

Example

JUnit is one of the unit testing frameworks for Java containing an “Assert Class” that has a lot of methods to test for your unit code outputs.

Consider, you have a code snippet where you want to compare the value of two different strings. The unit test for this problem statement in JUnit will look like:

String obj1="Junit";
String obj2="Junit";
assertEquals(obj1,obj2);

This test case will return True, if the condition matches else False.

Integration testing

By this point, you know that the individual lines of code are sound, and that at the functional level everything works as expected, but how does your application work as a whole when everything is running together? Integration tests allow you to step through the process of actually using the application and ensure that a user can complete a given task.

For a web application, this may involve a testing framework spinning up your site in multiple browsers while you watch it creepily operate the form controls by itself, or it could run in the background, analysing your markup, performing actions and feeding back if the outcome matches your definitions.

This is a great way to verify the acceptance tests set by product managers, and you can ensure these tests continue to run against your pull requests going forward to protect against regression or conflict with newer features. The downside of this style of testing is that you will almost certainly have to maintain and refactor these tests as your product evolves.

Pull requests, code reviews and pair programming

Insisting that at least one other person reviews your code protects you against blinkered thinking and development. If your colleague can spot a logical hole in your code, knows of a more efficient way to write a piece of code, or has been working on code that does something similar, you can take advantage of their knowledge and experience in addition to your own and catch errors before they make their way to production.

If you have the resources, and your team is working on a vital or complex feature, pair programming is literally where two developers sit next to each other. One of the developers types, and the other observes, offers advice or direction and ensures code quality – it’s a great way to bring junior developers up to speed, but is also a great learning tool for both developers and can reduce code review time as the output is delivered by consensus (so you’re less likely to have to completely refactor a function based on later feedback from the team).

The obvious drawback of this approach is that it can be literally twice as expensive in terms of hours.

Penetration testing

In modern applications, security should be paramount. There are so many users out there who would and could exploit any weaknesses in your code for their own purposes, and so many ways in which they could do it, that it’s almost impossible to create a 100% secure product.

It’s a known and given risk in the industry, so never promise your client that anything will be secure, but if you’re holding potentially sensitive data about users, and you can’t afford to be an expert in every aspect of web and application vulnerabilities, then I’d recommend getting an external security specialist to perform a penetration test.

They’ll poke and prod your application manually and via automated means to determine if a moderately skilled hacker or bad actor could access areas they shouldn’t or misuse your system in some way.

Code auditing books

The Internet is the greatest resource and expert on the subject of the Internet itself, and a well-phrased search will get you to the answer you need to solve a particular problem most of the time (otherwise you may have to do 2 or 3 searches to get to the page you need!).

Books can serve as a valuable beginner tool to get a broader understanding of code auditing as well as a powerful reference sheet for experienced coders to brush up on industry knowledge and current best practices.

Clean Code: A Handbook of Agile Software Craftsmanship

Even bad code can function. But if code isn’t clean, it can bring a development organization to its knees. Every year, countless hours and significant resources are lost because of poorly written code. But it doesn’t have to be that way.

Noted software expert Robert C. Martin presents a revolutionary paradigm with Clean Code: A Handbook of Agile Software Craftsmanship . Martin has teamed up with his colleagues from Object Mentor to distill their best agile practice of cleaning code “on the fly” into a book that will instill within you the values of a software craftsman and make you a better programmer–but only if you work at it.

Head First Design Patterns

What’s so special about design patterns?

At any given moment, someone struggles with the same software design problems you have. And, chances are, someone else has already solved your problem. This edition of Head First Design Patterns—now updated for Java 8—shows you the tried-and-true, road-tested patterns used by developers to create functional, elegant, reusable, and flexible software. By the time you finish this book, you’ll be able to take advantage of the best design practices and experiences of those who have fought the beast of software design and triumphed.

Code auditing tools

The tools should limit scope to the sections of the code changes and point out any issues that are detectable with automatic code analysis tools. Tools can help find common issues although there are usually false positives, they can be configured to meet your code repository needs.

GitHub

If you’re using git repositories, github comes with a great set of visual tools that show just the changes for the feature branch merge.

GitStash/BitBucket

This is similar to GitHub, but Atlassian’s version.

Phabricator

This is an open source tool that can be installed on your servers. However, this tool requires maintenance every now and then.

FindBugs

Finds common issues in code.

Sonar Code Analysis

Analyzes code against basic software code policies.

Code auditing tool (by use)

Linting

jslint/jshint for Javascript will run in the compilers Grunt/Gulp/Webpack. Phplint works for PHP (as you might expect!)

Unit and integration tests

Frameworks for unit testing ship with a lot of both frontend and backend code frameworks these days, so just see what works out of the box for what you’re using, or see which are the most popular on Github. I’ve used Jasmine and Karma before for setting up and running unit tests in Angular, and Selenium for browser testing. Jenkins can be used to automate running tests on your server, but Github now also has a number of automation plugins you can add to your project without having to go through too many complex setup steps.

Code versioning/reviews

Obviously Github, but Bitbucket is also a popular option depending on your needs.

The industry experts who contributed to this article.

This article was written and edited by Nathaniel Fried with industry knowledge from Riley Ramone (Founder of Ticketlab) and David Lee (Co-Founder of Kastling).

Riley Ramone

Position: Founder of Ticketlab

Riley has been a web developer for over 15 years. He has many years experience of writing, reviewing and auditing code and spent a good portion of his career working in FinTech, where security concerns are paramount.

David Lee - Co-Founder of Kastling

David Lee

Position: Co-Founder of Kastling

David co-founded Kastling Group and serves as the Chief Operating Officer and Chief Architect. He specializes in digital transformation strategy and implementation for large organizations and optimizes customer value and experiences for target customers through purpose-driven organizational structures. He has architected widely-used, multi-million dollar solutions in federal and commercial markets that have been implemented efficiently by large development teams.

Abhinav Sharma

Position: Executive Partner at TurgenSec and Original Team Member

Socials: Twitter, GitHub, Linkedin

Ranked at 1st in India and 9th in the world at the HackerRank Access Denied 1.2 CTF – Abhinav is a Security Researcher at Bugcrowd specialising in Web Application Pentesting, Reverse Engineering and RFID Hacking. His recent achievements include – Successfully finding security flaws in Dell, Tesla, Telefonica, Lenovo and MasterCard. Ranking 3rd in India and 5th globally for Glug CTF 2018 (NITDGP).

Leading and managing information security events for thousands of people alongside a DEF CON group – with more events scheduled for the future. Singlehandedly developing an SSH honeypot system leveraging machine learning for the Gurugram Police Force in India.

Nathaniel Fried

Position: Co-founder of TurgenSec

Socials: Twitter, Facebook, Linkedin

Nathaniel is an SEO and Marketing expert with 6 years of industry experience.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Loading…

0

Comments

0 comments

AI for cancer research

Machine Learning for Curing Lung Cancer – Harvard and Topcoder Collab

Cyber Security Guide for USA Businesses | Breaches, Cyber Scams, Laws, Obligations