Saturday, December 31, 2016

Killing dragons spawned by arithmetic-related security pitfalls

In the last week which followed my attempt to earn money with financial trading, I glanced through Black & Scholes model.

This study resulted in creation of OptionsCat, an open-source tool to work with european options. When writing this tool, I faced a lot of Arithmetic-related security pitfalls which motivated me to study it and write a blog post.  
I always come up with my own implementations for the algorithms presented throughout the finance books. That's because the writers are often careless about security pitfalls. This is a problem, or dragon from the perspective of this article, that could possibly be solved by adding a chapter about validation.

Programming languages that enable direct memory access and do not provide buffer boundary checks and arithmetic numeric checks are particularly vulnerable to integer overflow attacks. Integer overflow may occur when computing the memory size to allocate a buffer, and it often leads to buffer overflow.

Look at the following quote: 

 "Integer overflows cannot be detected after they have happened, so there is not way for an application to tell if a result it has calculated previously is in fact correct.  This can get dangerous if the calculation has to do with the size of a buffer or how far into an array to index. Of course most integer overflows are not exploitable because memory is not being directly overwritten, but sometimes they can lead to other classes of bugs, frequently buffer overflows. As well as this, integer overflows can be difficult to spot, so even well audited code can spring surprises." 
 by blexim - Phrack Volume 0x0b, Issue 0x3c, Phile #0x0a of 0x10

Some people talk to me about use of Big integer library. like LibGMP to solve it, but when you work with big int need limit that numbers, arithmetic operations with bigint when a user has input with large length can causes Denial of service... The use of Integers is not hard to find at the stock markets. but double is than common and can bring to you a problem, if you don't control the length, for example:

#include < math.h>
#include < stdio.h> 

double mul_code(double x,double y) 
  double result=0;
  return result = x*y;

int main()
 double a=90000000000, b=20000000000000;

 printf("Result: %f\n", mul_code(a,b));
 return 0;

If you compile it and run, returns something like "1799999999999999916112.*(dirts...)". You ask to me "why return it ?", you don' t validate operation and pass the limit of carry, this causes undefined behavior, overflow...

Killing dragons in integers 

There are lots of ways for you solve, one is validate user input, this way you can use automatons, regular expressions, strnlen() to try put limit in the number of length. Remember phrack; the correct way to test for integer overflow during multiplication is to test before the multiplication, test if number is negative, replace functions like atoi() to strtol()...

Some operating systems has solutions at libraries for mitigate the problem, for example OSX have os/overflow.h, with this header you can do something like it:

#include < "os/overflow.h">
if (os_mul_overflow(m, n, &bytes)) {
    /* Overflow occured.  Handle appropriately. */
} else {
    /* Allocate "bytes" space. */

Other way to mitigate, this way is from OpenBSD:

#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t)*4))
// based in OpenBSD reallocarray() function
void *reallocarray (void *ptr, size_t nmemb, size_t size) 
 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) 
  DEBUG("integer overflow block");
  return NULL;

 void *p = realloc (ptr, nmemb*size);

 if (p == NULL) 
  return NULL;

 return p;

Other approaches that you can see, is the using libraries and other ways to write safe code with integers, sometimes calling each function safe_add(), safe_sub(), safe_mul() and safe_div() is very boring when have large expressions, thinking about it i writed a solution, look my project Here!

Killing dragons in double

At the Cert C book by Robert Seacord has a example to solve problem at double, the derivatives and futures has a lot of operations with double, one way to detect possible bug is using the function fetestexcept() :

 double ret=(1.0/(pow(2*PI,0.5)))*exp(-0.5*x*x);
double norm_pdf(const double x) 
 double ret=(1.0/(pow(2*PI,0.5)))*exp(-0.5*x*x);
 int fpeRaised=0;


   if(fpeRaised!=32 && fpeRaised!=0)
  DEBUG("error here!");
     perror("Log: \n");
  ret = 0;


 return ret;

At inputs don't use atof() function, replace to strtod(), other examples with double look this following code here.

Thank you for reading.
Cheers !

1 comment: