Tuesday, February 2, 2016

What's in a prime? Ask socat...

Today it was announced that the tool socat, which is supposed to offer encrypted connections, has a glaring encryption flaw.  I teach this tool in the SEC660 course at SANS and mention it in another of other courses.  I've used the tool operationally in penetration tests, trusting that the code was secure.

But I am not a cryptographer. Heck, I don't even rate as a mathematician.  So I certainly didn't notice that a 1024 bit number used as a prime in crypto calculations wasn't actually a prime.  So much of our crypto today is built on the premise that a very large number that is the result of multiplying two primes (a semi prime) is exceedingly difficult to factor.  The problem is that factoring is exponentially easier if you happen to know that one of those numbers isn't really prime at all.  Good luck figuring that out.  Doubt I'm right?  Tell me which of these looks like a prime number.  Don't rush, I'll wait.
Guess which number might be prime...
Of course it's not easy to figure out the answer. That's the point. Crypto assessments are very difficult to do (and more difficult to do right).  FYI, the one on the top is the non-prime number that was in use by socat.  I changed some digits around in the bottom number.  I have no idea if it is prime either.  Given the mathematical odds, I seriously doubt it is.

And that's what has happened with socat.  The tools uses a number that isn't prime when it should be prime.  This impacts the Diffie-Hellman key exchange, meaning that the secret key could be eavesdropped on much more easily by an attacker than originally intended.

In their advisory, socat lists impacted versions.  It looks like some older versions are not impacted.  But one question being asked is who generated the supposed prime number?  If this was committed to the code base by an attacker with eavesdropping capability (e.g. a nation state), the attacker could potentially decrypt traffic that the sender thought was secure.  Below, you can see the code changes, with the old 1024 bit value being replaced with a new 2048 bit value.

New 2048 bit prime
At Rendition Infosec, we regularly tell clients that they should always consider code reviews before relying on any software (even open source).  Unfortunately, it's really hard to find a crypto backdoor like this.  How does one really figure out whether a particular number like this is a prime?  Hire a mathematician?  Probably not.  I'll just say that it's a hard problem.

But looking at overall code quality is relatively easy by comparison.  One thing we can look for that is pretty easy to identify are vulnerable functions.  One such function is strcpy, which should be replaced in all cases with strncpy.  Unfortunately, even the current code for socat has many.
jake@server$ grep strcpy *.c
hostan.c:      strcpy(ifr.ifr_name, ifp->ifr_name);
xio-exec.c:      strcpy(tmp+1, pargv[0]);
xio-exec.c:      strcpy(tmp, pargv[0]);

xio-ip4.c:      strcpy(namebuff, "ADDR");
xio-ip4.c:      strcpy(namebuff, "PORT");
xio-ip6.c:      strcpy(namebuff, "ADDR");
xio-ip6.c:      strcpy(namebuff, "PORT");
xiolockfile.c:   strcpy(s, lockfile);
xio-proxy.c:      strcpy(header, authhead);

xio-readline.c:   strcpy(cp, "using "); cp = strchr(cp, '\0');
xio-readline.c:      strcpy(cp, "readline on stdin for reading"); cp = strchr(cp, '\0');
xio-readline.c:      strcpy(cp, " and ");  cp = strchr(cp, '\0');
xio-readline.c:      strcpy(cp, "stdio for writing"); cp = strchr(cp, '\0');
xio-socket.c:   strcpy(val, ifr.ifr_name);
xio-socket.c:   strcpy(namebuff, lr);
xio-socket.c:      strcpy(namebuff, lr);

xiotransfer.c:      strcpy(timestamp, ctime(&nowt));
xiotransfer.c:      strcpy(timestamp, ctime(&now));
xio-unix.c:   strcpy(namebuff, "ADDR");
There are 19 calls to the vulnerable function strcpy.  Of the 19, only 7 (those in bold) would appear to be potentially exploitable. Additional work would be required to figure out whether they are actually exploitable.  It's worth noting as well that just because the programmer replaces strcpy with strncpy, the code is not necessarily secure.  The programmer might for instance mistake the size of the destination buffer.  These are especially concerning when you discover that a separate vulnerability (also patched in the latest version) resulted in a stack based buffer overflow. 

After looking at the code in xio-exec.c, we find that it is not vulnerable due to the way memory is allocated to the tmp variable.
      if ((tmp = Malloc(strlen(pargv[0])+2)) == NULL) {
         return STAT_RETRYLATER;
      }
      if (dash) {
         tmp[0] = '-';
         strcpy(tmp+1, pargv[0]);
      } else {
         strcpy(tmp, pargv[0]);
      }
I haven't looked at the others, or some of the other possible vulnerable functions.  That's something I'll leave for someone else.

Recommendations
My recommendations? Update socat now if you use it. If an attacker with nation-state level access inserted the non-prime number in the code, they could easily be eavesdropping.  But also, consider whether the security posture of the overall socat code base is concerning.  The use strcpy is just bad programming hygiene.  I'm not saying there's a vulnerability here, but the use of vulnerable functions is an overall indication of security posture.  There's rarely fire without smoke.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.