Posts

Showing posts from February, 2018

InfoSect's Month of Pointless Bonus Bugs (#34)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bonus Bug #34

Another bios decompression bug. This time in awardeco.

typedef struct
        {
                byte    HeadLen;
                byte    HeadCrc;
                byte    Method[5];
                dword   PackLen;
                dword   RealLen;
                dword   TStamp;
                byte    Attr;
                byte    Level;
                byte    FilenameLen;
                byte    FileName[12];
                word    CRC16;
                byte    DOS;
                word    Empty;

        } LZHHead;

...
/*---------------------------------
        XtractAwd
----------------------------------*/
byte XtractAwd(FILE *ptx, byte Action, dword DecoOff, dword FirstOff, byte i
sASUS)
        {

        FILE *pto;
        interfacing interface;
        byte PartTotal=0, CntMods…

InfoSect's Month of Pointless Bonus Bugs (#33)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #33

In bchunk, a program to do conversion between CD's bin/cue and iso/cdr.

/*
 *      Convert a mins:secs:frames format to plain frames
 */

long time2frames(char *s)
{
        int mins = 0, secs = 0, frames = 0;
        char *p, *t;

        if (!(p = strchr(s, ':')))
                return -1;
        *p = '\0';
        mins = atoi(s);

        p++;
        if (!(t = strchr(p, ':')))
                return -1;
        *t = '\0';
        secs = atoi(p);

        t++;
        frames = atoi(t);

        return 75 * (mins * 60 + secs) + frames;
}


A negative return value is clearly not correct, but there is no sign check.

                      printf(" %s %s", p, t);
                        track->startsect = time2frames(t);
                        t…

InfoSect's Month of Pointless Bonus Bugs (#32)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bonus Bug #32

In the package abootimg, a program for working with android boot images, it's possible to craft a boot image to trigger a buffer overflow and other issues when abootimg accesses it.

struct boot_img_hdr
{
    unsigned char magic[BOOT_MAGIC_SIZE];

    unsigned kernel_size;  /* size in bytes */
    unsigned kernel_addr;  /* physical load addr */

    unsigned ramdisk_size; /* size in bytes */
    unsigned ramdisk_addr; /* physical load addr */

    unsigned second_size;  /* size in bytes */

    unsigned second_addr;  /* physical load addr */

...
    case extract:
      open_bootimg(bootimg, "r");
      read_header(bootimg);
      write_bootimg_config(bootimg);
      extract_kernel(bootimg);
      extract_ramdisk(bootimg);
      extract_second(bootimg);
      break;


...
vo…

InfoSect's Month of Pointless Bonus Bugs (#31)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bonus Bug #31

In the package amideco, which is some kind of ami bios extractor we have a simple stack overfow. Not that useful since it's not running at privs, but maybe in some scenarios it's a client side..

   switch(AMIVer)
        {
        case 95:
                PartTotal = Xtract95(ptx, HelpID, ConstOff, Offset, argv[1]);
                        break;
        case 94:

...

byte Xtract95(FILE *ptx, byte Action, dword ConstOff, dword Offset, byte* fname)
        {

        FILE *pto;
        interfacing interface;
        byte    PartTotal = 0;
        PARTTag part;
        byte    Buf[64];
        byte    MyDirName[64]     =       "--DECO--";
        dword   i;
        byte    sLen = 0;

        byte    doDir   = 0;
        /*
        For the case of multiple 0x20 module…

InfoSect's Month of Pointless Bugs (#30)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #30

In fcrackzip:

int REGPARAM
check_unzip (const char *pw)
{
  char buff[1024];
  char path[1024];
  char escpw[256];
  int status;

  escape_pw (escpw, pw);
  path_for_shell (path, file_path[0]);

  sprintf (buff, "unzip -qqtP \"%s\" %s " DEVNULL, escpw, path);

  status = system (buff);

#undef REDIR

  if (status == EXIT_SUCCESS)
    {
      printf("\n\nPASSWORD FOUND!!!!: pw == %s\n", pw);
      exit (EXIT_SUCCESS);
    }

  return !status;

}

Lets look at escape_pw():
char * escape_pw (char *dest, const char *str) {   /* backslash shell special charatcers */
  char ch, *p = dest;   size_t len = strlen(str);   int i;
  for (i = 0; i < len; i++)   {     ch = str[i];
    switch (ch)     {     /* ASCII table order */     case '"':     case '$':     case 0x2…

InfoSect's Month of Pointless Bugs (#29)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #29

In bsdgames/robots:


# define        MAXNAME         16

...
typedef struct {         u_int32_t       s_uid;         u_int32_t       s_score;         u_int32_t       s_auto;         u_int32_t       s_level;         char            s_name[MAXNAME]; } SCORE;
...
void set_name(scp)         SCORE   *scp; {         PASSWD  *pp;         static char unknown[] = "???";
        if ((pp = getpwuid(scp->s_uid)) == NULL)                 pp->pw_name = unknown;         strncpy(scp->s_name, pp->pw_name, MAXNAME); }
This bug allows s_name to possibly not be NUL terminate for long login names. Note like previous bugs, dropping privs is not checked for failure.

InfoSect's Month of Pointless Bugs (#27)

Dr Silvio Cesare

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #27

In bsdgames/atc

typedef struct {
        char    name[10];
        char    host[256];
        char    game[256];
        int     planes;
        int     time;
        int     real_time;
} SCORE;

...
        SCORE           score[100], thisscore;

               if ((pw = (struct passwd *) getpwuid(getuid())) == NULL) {
                        fprintf(stderr, 
                                "getpwuid failed for uid %d.  Who are you?\n",
                                (int)getuid());
                        return (-1);
                }
                strcpy(thisscore.name, pw->pw_name);

Login names can be greater than 10 bytes. Note also that the game doesn't check that dropping privs may fail, leading to a potential privileged buffer overflow.

InfoSect's Month of Pointless Bugs (#26)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #26

In bsdgames/sail

int
lo_main(void)
{
        FILE *fp;
        char sbuf[32];

...
       while (fread((char *)&log, sizeof log, 1, fp) == 1 &&                log.l_name[0] != '\0') {                 if (longfmt && (pass = getpwuid(log.l_uid)) != NULL)                         sprintf(sbuf, "%10.10s (%s)", log.l_name, pass->pw_name);                 else                         sprintf(sbuf, "%20.20s", log.l_name);
Lets look at what the max username length is on my specific system:
$ getconf LOGIN_NAME_MAX 256
Now if we combine this with the fact the calls to setegid() don't check the return value and may fail (see http://blog.infosectcbr.com.au/2018/02/infosects-month-of-pointless-bugs-3.html)  we may have a bug chain leading …

InfoSect's Month of Pointless Bugs (#25)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #25

In the ltris game

SDL_Surface* load_surf(char *fname, int f)
{
    SDL_Surface *buf;
    SDL_Surface *new_sur;
    char path[ 512 ];
    SDL_PixelFormat *spf;
#ifdef USE_PNG
    char png_name[32];
#endif

#ifdef USE_PNG
    /* override file name as all graphics were changed from
    bitmap to png so the extension must be corrected */
    memset( png_name, 0, sizeof( png_name ) );
    strncpy( png_name, fname, strlen( fname ) - 4 );
    strcat( png_name, ".png" );
    get_full_bmp_path( path, png_name );
    buf = load_png( path );

#else

The above isn't thought through very well.. using strlen(fname)-4 for the length of the copy, even though it's a fixed 32 bytes? It's probably a typo or a brain snap.
Lets see if we can find code where it's greater than 32 byte…

InfoSect's Month of Pointless Bugs (#24)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #24

In the omega-rpg game:

void player_dump( void )
{
  FILE *dumpfile;
  char dump_name[ 32 ];

  /* build player dump file name as "charactername.txt" */
  strncpy( dump_name, Player.name, 27 );

  strcat( dump_name, ".txt" );


strncpy is not guaranteed to NUL terminate. This might lead to a buffer overflow in the proceeding strcat.

InfoSect's Month of Pointless Bugs (#23)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #23

This is another small bug in the lbreakout2 network game server. The name string may not be NUL terminated after the strncpy.

 static void parse_packet_channel( ServerUser *user, ServerChannel *channel )
{
    int id;
    unsigned char type;
    char name[16];
    ServerUser *recv;
    ServerGameCtx ctx;
    ServerChannel *newchannel;

...

    case MSG_ENTER_CHANNEL:
strncpy(name,msg_read_string(),16);
                if ( strchr( name, ' ' ) ) {
                    sprintf( errbuf, _("Channel name must not contain blanks!") );
                    send_info( user, MSG_ERROR, errbuf );
                    break;
                }

InfoSect's Month of Pointless Bugs (#28)

Dr Silvio Cesare

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #28

The canfield game in bsdgames doesn't check if dropping privs can fail - see http://blog.infosectcbr.com.au/2018/02/infosects-month-of-pointless-bugs-3.html


bsdgames/canfield/canfield/canfield.c

       if (uid < 0)
                uid = 0;
        dbfd = open(_PATH_SCORE, O_RDWR);

        /* Revoke setgid privileges */
        setregid(getgid(), getgid());

        if (dbfd < 0)
                return;

InfoSect's Month of Pointless Bugs (#22)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #22

In the freesweep game:
void* xmalloc(size_t num) {         void *vec = NULL;
        vec = (void*)malloc(sizeof(unsigned char) * num);
        if (vec == NULL)         {                 SweepError("Out of Memory. Sorry");                 exit(EXIT_FAILURE);         }
        return vec; }
...
struct BestEntry* NewBestEntry(GameStats *Game) {         struct BestEntry *b = NULL;         time_t now;         char *buf = NULL, *p = NULL;
        b = (struct BestEntry*)xmalloc(sizeof(struct BestEntry) * 1);
        /* fill in some attributes */         b->area = Game->Height * Game->Width;         b->mines = Game->NumMines;         b->time = Game->Time;
        /* do the username */         buf = getenv("USER");         if (buf == NULL)         {            …

InfoSect's Month of Pointless Bugs (#21)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #21

In bsdgames/phantasia

int
main(argc, argv)
        int     argc;
        char  **argv;
{
        bool    noheader = FALSE;       /* set if don't want header */
        bool    headeronly = FALSE;     /* set if only want header */
        bool    examine = FALSE;        /* set if examine a character */
        time_t  seconds;                /* for time of day */
        double  dtemp;                  /* for temporary calculations */

        initialstate();                 /* init globals */

...

void initialstate() {         struct stat sb;
        Beyond = FALSE;         Marsh = FALSE;         Throne = FALSE;         Changed = FALSE;         Wizard = FALSE;         Timeout = FALSE;         Users = 0;         Windows = FALSE;         Echo = TRUE;
        /* setup login name */         if…

InfoSect's Month of Pointless Bugs (#20)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #20

There is a null pointer dereference in bsdgames/sail. If argv is NULL, then strrchr will segfault. It's not exploitable. It's interesting because sail is sgid games.

int
main(int argc, char **argv)
{
        char *p;
        int a,i;
        int fd;

        gid = getgid();
        egid = getegid();
        setegid(gid);

        fd = open("/dev/null", O_RDONLY);
        if (fd < 3)
                exit(1);
        close(fd);

        srandom((u_long)time(NULL));

        if ((p = strrchr(*argv, '/')) != NULL)
                p++;
        else
                p = *argv;

To trigger:

$ cat hack.c
#include <unistd.h>
int
main(int argc, char *argv[])
{
execve(argv[1], NULL, NULL);

}
$ gcc hack.c -o /tmp/a.out
$ /tmp/a.out /usr/games/sail  Segmentation fault

InfoSect's Month of Pointless Bugs (#19)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #19

bsdgames/snake doesn't check dropping privs - see http://blog.infosectcbr.com.au/2018/02/infosects-month-of-pointless-bugs-3.html

InfoSect's Month of Pointless Bugs (#18)

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #18

bsdgames/tetris doesn't check dropping privs - see http://blog.infosectcbr.com.au/2018/02/infosects-month-of-pointless-bugs-3.html

InfoSect's Month of Pointless Bugs (#17)

Dr Silvio Cesare

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #17

The robots game in bsdgames doesn't check if dropping privs can fail - see http://blog.infosectcbr.com.au/2018/02/infosects-month-of-pointless-bugs-3.html

InfoSect's Month of Pointless Bugs (#16)

Dr Silvio Cesare

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #16

bsdgames/sail doesn't check dropping privs - see http://blog.infosectcbr.com.au/2018/02/infosects-month-of-pointless-bugs-3.html

E.g,

int
main(int argc, char **argv)
{
        char *p;
        int a,i;
        int fd;

        gid = getgid();
        egid = getegid();
        setegid(gid);

InfoSect's Month of Pointless Bugs (#15)

Dr Silvio Cesare

InfoSect, Canberra's hackerspace, regularly runs public group sessions to perform code review and vulnerability discovery. Over the next 30 days, I'll highlight the source code of 30 unknown vulnerabilities.

Bug #15

This is an interesting stack overflow with a long argv[0] string. argv[0] is typically the program name of the process/executable, but can be attacker controlled. The code below assumes argv[0] is related to a pathname max len of 1024, which is incorrect in any case on modern filesystems, but is in fact not related to pathname lengths at all.

bsdgames/hack/hack.main.c int main(argc, argv) int argc; char *argv[]; { int fd; #ifdef CHDIR char *dir; #endif /* Check for dirty tricks with closed fds 0, 1, 2 */ fd = open("/dev/null", O_RDONLY); if (fd < 3) exit(1); close(fd); hname = argv[0]; +++ hname = argv[0] …