You are here

You are here

Want secure code by default? Minimize your framework risk

Morgan Roman Software Security Engineer, DocuSign

It's tiring when you have to constantly remind developers to follow secure practices, and this often burns out security teams. Developers just want to get the job done, so they often write insecure code that just works. 

Their job is to build features or complex systems, and they have to build with the framework they are using. But usually the framework has vulnerabilities in its standard libraries—and developers then use the unsafe, default version.

So it comes to pass that the developer who just wanted to use regular expression (regex) or parse XML ends up exposing your application to serious security vulnerabilities, such as ReDoS or XXE.

Here's how to standardize how developers use your framework's risky parts.

Security for developers, made simpler

A lot of security training for developers goes against both common sense and what they have learned, which is to rely on the framework for simple tasks and then build cool things using a framework they can trust. But the frameworks are not trustworthy, and that leads to developers shooting themselves in the foot.

Even the worthy goal of training developers to understand security can lead to problems. They rarely have time to do that on top of their regular job, and that training often requires them to retain knowledge that's specific to security and the libraries they are using.

So, instead of having the safe way be the more complicated way, make things safe by default. Developers will then use the default behavior of the library most of the time.

This simple solution involves writing a safe wrapper class around libraries or functionality that has unsafe behavior by default. Then you just recommend and enforce the use of the safe wrapper instead of using the library directly.

[ Special Coverage: DevSecCon Seattle 2019 ]

How to block regex denial of service forever

Regex denial of service occurs when a regex pattern takes exponential time to evaluate. This holds up a process or thread of an application, consuming resources and making the server unreachable for legitimate customers.

Here's how to identify and solve this in a .NET codebase. Although the example that follows is written in C#, this pattern works in Java and other languages or frameworks.

The bad pattern

By default, using the base regex class has no built-in timeout. So the following code would be vulnerable to a ReDoS attack:

// Unsafe!
Regex bad = new Regex("(a+)+");

For developers to use regex safely, they would have to remember to include a timeout such as the following every time:

//Safe var timeout = TimeSpan.FromSeconds(1);
Regex good = new Regex("(a+)+", RegexOptions.None, timeout);

If they forget even once, you could have a vulnerability on your hands. Note that there are a lot of other ways to use regex without a timeout, so you'll have to cover each of those as well. This makes the problem difficult and complex for just one type of security bug.

Make the good pattern your default

For simplicity's sake, you could just make a safe version of the regex class — let's call it "MySafeRegex." It's going to inherit from the base regex class, have a built-in timeout, and look something like this:

//Safe by default. Inherits from the base Regex class.
public class MySafeRegex : Regex {
  // create your default timeout of one second
  private static TimeSpan defaultTimeout => TimeSpan.FromSeconds(1);
  // make your constructor use the default timeout by default
  public MySafeRegex(string pattern) : base(pattern, RegexOptions.None, defaultTimeout)

The above code is a simple example of a safe-by-default class. Just train the developers to use the safe version of your class, rather than the default one for the framework they're using.

How to write the training and documentation

The training for the above is simple. If you use the default regex class, a poorly crafted regex can result in executing with exponential time. Instead, use the MySafeRegex class since this bounds the execution to a reasonable amount of time.

Regex bad = new Regex("(a+)+");

MySafeRegex good = new MySafeRegex("(a+)+");

The above gets developers to write more secure code since it has three key parts:

  1. What could happen if developers don't follow your advice.
  2. What they should NOT do with a code example. (Also known as "what the developer was trying to do in the first place.")
  3. What they should do, by way of a simple example.

Here's a template for training and documentation when you are using this method:






Try the above template, and you'll be surprised how effective your training is when it is simply "use this, not that." 

For more on how to protect your developers from shooting themselves in the foot, come to Morgan's presentation at DevSecCon Seattle 2019, where he'll dive deeper into how to integrate these methods into your CI/CD pipeline and prevent other security bugs. The conference runs September 16-17, 2019. 

Keep learning

Read more articles about: DevOpsSecure DevOps