Posts

Linux kernel drivers/usb/gadget/function/f_fs.c

static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
                                      struct usb_os_desc_header *h, void *data,
                                      unsigned len, void *priv)
{
        struct ffs_function *func = priv;
        u8 length = 0;

        switch (type) {

...                 ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);                 ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);                 ext_prop->data_len = le32_to_cpu(*(u32 *)                         usb_ext_prop_data_len_ptr(data, ext_prop->name_len));                 length = ext_prop->name_len + ext_prop->data_len + 14;
length is almost certain not able to hold the correct size if name_len and data_len are not small. considering that name_len comes from le16 and data_len comes from le32, it seems likely that they won't always be trivially small.

2 Recent InfoSect CVEs

axmail

In axmail

char username[20];
char fullname[31];
...
        /* Strip SSID */
        if (local) {
                pw = getpwuid(getuid());
        } else {
                strcpy(callsign, call);
                strcpy(username, callsign);
                strlwr(username);
                p = strchr(username, '-');
                if (p) *p = '\0';
                pw = getpwnam(username);
        }
...
                if (local) {
                        strcpy(username, pw->pw_name);
                        strcpy(callsign, username);
                }
                /* Strip full name from the gecos field... */
                if (strchr(pw->pw_gecos, ',') == NULL)
                        strcpy(fullname, pw->pw_gecos);
                else
                        strcpy(fullname, strtok(pw->pw_gecos, ","));

This seems to be a common legacy code bug - assumptions about username/gecos lengths etc.

Forensics Bugs (#2 rifitui)

rifitui is a tool to recover Windows recycle bins.

  int currrecoff;
  int recordsize;

...

  pread( info2_file, fourbytes, 4, 0x0C );
  recordsize = bah_to_i( fourbytes, 4 );

  record = malloc( recordsize );

...

  while (eof == 0) {
    res = pread( info2_file, record, recordsize, currrecoff );
    if (res < recordsize) {
      eof = 1;
    } else {
      filename = record + 0x04;
      index = bah_to_i( record+0x108, 4 );       drive = bah_to_i( record+0x10C, 4 );
      deltime = win_time_to_unix( record+0x110 );       deltm = localtime( &deltime );       year = deltm->tm_year + 1900;       mon = deltm->tm_mon + 1;       sprintf( ascdeltime, "%02d/%02d/%02d %02d:%02d:%02d", mon, deltm->tm_mday, year, deltm->tm_hour, deltm->tm_min, deltm->tm_sec );
      filesize = bah_to_i( record+0x118, 4 );
      printf( "%d%s%s%s%d%s%s%s%d\n", index, delim, ascdeltime, delim, drive, delim, filename, delim, filesize );     }     currrecoff = currrecoff + recordsize;
It's no…

Forensics Bugs (#1 recoverjpeg)

recoverjpeg

    const char *buffer = file_name(dir_format, file_format, begin_index + i);
      i++;
      if (verbose) {
        printf("%s %ld bytes\n", buffer, (long) size);
      }
      fdout = open(buffer, O_WRONLY | O_CREAT, 0666);
      if (fdout < 0) {
        fprintf(stderr, "Unable to open %s for writing\n", buffer);
        exit(1);
      }

...

Writes to an output file (e.g., image00000.jpg) and doesn't check for it being a symlink - hence an attacker could create a symlink pointing to a privileged file that the person running recoverjpeg has write access to. This is mitigated in /tmp /var/tmp by the Linux kernel, but it's still a bug.

unhide (part #3)

Stack overflow in unhide. There is a mismatch between the maxpathlen from a readlink (it gets both sizes wrong in any case).

An attack scenario might be that a rootkit is installed by an attacker then gets code execution (again presumably) when the sysadmin tries to "unhide" the rootkit.

char cmdcont[1000] ;
...
     char proc_exe[512] ;
...
      sprintf(mypath,"/proc/%d",my_pid);
      statuscmd = stat(mypath, &buffer) ;
      if ((statuscmd == 0) && S_ISDIR(buffer.st_mode))
      {
         pid_exists[N_PROC] = TRUE ;
         strcat(mypath,"/exe") ;
         length = readlink(mypath, cmdcont, 1000) ;
         if (-1 != length)
         {
            cmdcont[length] = 0;   // terminate the string
//            printf("cmdcont(proc_exe) = %s\n", cmdcont) ;   //DEBUG
            strcpy(proc_exe,cmdcont) ;
         }
         else
         {
            strcpy(proc_exe,"unknown exe") ;
         }
      }

unhide (part #2)

In the unhide source we have the following lines of code

// sysctl kernel.pid_max
int maxpid = 32768;

Lets look at what my Linux system that has unhide says.
# sysctl kernel.pid_max kernel.pid_max = 131072
More code in unhide:
unsigned int proc_parent_pids[65536] ;
char *proc_tasks[65536]; char *ps_pids[65536]; char *messages_pids[65536]; char message[1000] ; char description[1000] ; int ps_count = 0 ;
This looks like it's assuming 16bit PIDs.. I won't investigate further, but it's likely to be a problem that will allow for a rootkit to bypass unhide.