xorl %eax, %eax

FreeBSD PPP(8)/NAT 65535 Port Integer Overflow

leave a comment »

This bug was reported by Aragon Gouveia on 19 July 2009 and it affects (at least) 8.0-BETA1 release of FreeBSD. This should not be considered as a critical vulnerability (in my opinion) since it only affects systems using ppp(8) and using NAT to forward port 65535. The buggy code can be found at src/usr.sbin/ppp/nat_cmd.c like this:

int
nat_RedirectPort(struct cmdargs const *arg)
{
  if (!arg->bundle->NatEnabled) {
    prompt_Printf(arg->prompt, "Alias not enabled\n");
    return 1;
  } else if (arg->argc == arg->argn + 3 || arg->argc == arg->argn + 4) {
    char proto_constant;
    const char *proto;
    struct in_addr localaddr;
    u_short hlocalport, llocalport;
    struct in_addr aliasaddr;
    u_short haliasport, laliasport;
    struct in_addr remoteaddr;
    u_short hremoteport, lremoteport;
    struct alias_link *link;
    int error;

    proto = arg->argv[arg->argn];
    if (strcmp(proto, "tcp") == 0) {
  ...
    while (laliasport <= haliasport) {
      link = PacketAliasRedirectPort(localaddr, htons(llocalport),
				     remoteaddr, htons(lremoteport),
                                     aliasaddr, htons(laliasport),
				     proto_constant);

      if (link == NULL) {
        prompt_Printf(arg->prompt, "nat port: %d: error %d\n", laliasport,
                      error);
        return 1;
      }
      llocalport++;
      laliasport++;
      if (hremoteport)
        lremoteport++;
    }

    return 0;
  }

  return -1;
}

As you can see, llocalport, haliasport, hremoteport and lremoteport are allo of them declared as unsigned short integers, meaning 2 bytes long and consequenlty, they have a range of 0-65535. The while loop iterates as long as the local alias NAT port is less than, or equal to the host’s port. However, as you can see both are incremented regardless of their values. Because of this, if user attempts to use port 65535 this will result in an infinite loop since laliasport will wrap around and iterate forever. To fix this, they changed the above loop like this:

– while (laliasport <= haliasport) { + do { link = LibAliasRedirectPort(la, localaddr, htons(llocalport), remoteaddr, htons(lremoteport), aliasaddr, htons(laliasport), @@ -187,10 +187,9 @@ nat_RedirectPort(struct cmdargs const *a return 1; } llocalport++; - laliasport++; if (hremoteport) lremoteport++; - } + } while (laliasport++ < haliasport); return 0; [/sourcecode]

Written by xorl

August 9, 2009 at 14:18

Posted in bugs, freebsd

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s