Improve Security with "A Layer of Hurt"

Improve Security with "A Layer of Hurt"

  • Comments 4
Hello, Michael here.

I got a lot of interesting comments from my TechEd 2008 presentation entitled, "How To Review Your Code And Test For Security Bugs," but the most comments and questions were reserved for fuzz testing; I was blown away by the number of people who thought fuzz testing was hard, or that you only left fuzz testing to ‘leet hackers.

During the presentation I mentioned in some depth how to perform fuzz testing, and what parts of an application should be fuzz testing targets. I also introduced an idea (that's not new) to help people who have never performed fuzz testing begin fuzz testing with very little cost and friction. The idea is to add a small layer of code to an application to automatically mutate untrusted data as it comes into an application; I called that code layer "a layer of hurt."

Before I continue, I want to point out that fuzzing is an SDL requirement, but the idea in this blog post is not an SDL requirement, it's just another way to help meet SDL fuzzing requirements.

Adding a layer of hurt, as shown in the picture below, is pretty simple as it involves adding code to an application to tweak data as it comes into an application. You can work out where to place the fuzzing code by looking at your threat models to see where data crosses trust boundaries. You could also simply grep the code looking for APIs that read data, for example:

  • Read from files: fread, ReadFile
  • Reading from sockets: recv, recvfrom
  • For .NET code, any stream.Read

You get the picture.

The fuzzing code should appear right after the API that reads that data.

For example, C or C++ code that reads from a UDP socket and then fuzzes the data before it's consumed by the rest of the application might look like this:

char RecvBuf[1024];
int  BufLen = sizeof(RecvBuf);

int result = recvfrom(
   RecvSocket,
   RecvBuf,
   BufLen,
   0,
   (SOCKADDR *)&SenderAddr,
   &SenderAddrSize);

#ifdef _FUZZ
   Fuzz(RecvBuf,&BufLen);
#endif

Or, in C#, code that reads from an untrusted file:

FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
uint len = (uint)(fileStream.Length);
byte[] fileData = new byte[fileStream.Length];
fileStream.Read(fileData, 0, (int)len);
fileStream.Close();

#if _FUZZ_
  Malform pain = new Malform();
  fileData = pain.Fuzz(fileData);
#endif

In both code examples, Fuzz() mutates the incoming data. In the C++ case, the fuzzing code looks like this:

void Fuzz(_Inout_bytecap_(*pcbBuf) char *pBuf,
          _Inout_ size_t *pcbBuf) {

  if (!pcbBuf || !pBuf || !*pcbBuff || *pBuf) return;
  if ((rand() % 100) > 5) return; // fuzz about 5% of Buffers

  size_t cLoop = 1 + (rand() % 4);

  for (size_t j = 0; j < cLoop; j++) {

    size_t i=0, 
      iLow = rand() % *pcbBuf, 
      iHigh = 1+rand() % *pcbBuf,
      iIter = 1+rand() % 8;

    if (iLow > iHigh) 
      {size_t t=iHigh; iHigh=iLow; iLow=t;}

    char ch=0;
    switch(rand() % 9) {

      case 0 : // reset upper bits
        for (i=iLow; i < iHigh; i++) 
          pBuf[i] &= 0x7F; 
        break;

      case 1 : // set upper bits
        for (i=iLow; i < iHigh; i++) 
          pBuf[i] |= 0x80;
        break;

      case 2 : // toggle all bits
        for (i=iLow; i < iHigh; i++) 
          pBuf[i] ^= 0xFF;
        break;

      case 3 : // set to random chars
        for (i=iLow; i < iHigh; i++) 
          pBuf[i] = (char)(rand() % 256); 
        break;

      case 4 : // set NULL chars to (possibly) non-NULL
        for (i=iLow; i < iHigh; i++) 
          if (!pBuf[i]) 
            pBuf[i] = (char)(rand() % 256);
        break;

      case 5 : // swap adjacent bytes
        for (i=iLow; i < __max(iHigh-1,iLow); i+= iIter) 
          {char t=pBuf[i]; pBuf[i] = pBuf[i+1]; pBuf[i+1]=t;} 
        break;

      case 6 : // set to random chars every n-bytes
        for (i=iLow; i < __max(iHigh-1,iLow); i+= iIter) 
          pBuf[i] = (char)(rand()%256);
        break;

      case 7 : // set bytes to one random char
        ch=(char)(rand() % 256); 
          for (i=iLow; i < iHigh; i++) 
            pBuf[i] = ch; 
        break;

      default: // truncate stream
        *pcbBuf = iHigh; 
        break;
     }
   }
}                         

The sample C# and C++ fuzzing code is available as a ZIP file at the end of this post.

This code is an example of dumb-fuzzing, which is fuzzing with little or no regard for the data structure being manipulated. If you've never performed any kind of fuzz testing in the past, then you will probably find bugs with this simple fuzzing technique. Once you have weeded out the low-hanging bugs, you may need to turn your attention to smarter fuzzers. For example, in theory, this code would find few if any bugs in a PNG parser, because PNG files have a built in check-sum, so if you fuzz a PNG file, you'd have to recalculate the checksum to get decent code coverage.

When I showed this code during my presentation, I urged people to add it to their applications today if they currently don't do fuzz testing, and simply run their applications through their normal testing processes. Within three days of my presentation I received emails from people saying they had found bugs. I have no doubt others did too.

One of the comments I made during the session was,"If you can't spend the time on great fuzzing, fuzz anyway" and adding a "layer of hurt" is a reasonable start.

Please feel free to sound off if you have ideas to help improve the code and let us know what you think, either through email or comments to this post.

Attachment: Code.zip
Comments
  • I just wrote a post over on the SDL blog about how to get started with fuzzing,...

  • I like to compare fuzzing to the job of testing bullet proof vests.  

    See also:

    Fuzzing: Brute Force Vulnerability Discovery by Michael Sutton, Adam Greene, Pedram Amini

  • a {color : #0033CC;} a:link {color: #0033CC;} a:visited.local {color: #0033CC;} a:visited {color : #800080;}

  • Hello, Michael here... Over the last couple of years, I've released information about various Microsoft

Page 1 of 1 (4 items)
Leave a Comment
  • Please add 2 and 5 and type the answer here:
  • Post