Saturday, 24 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 = 0;
        NewLZHHead head;
        byte Buf[32], Buf2[128], Len = 0xFF;
        dword i, k, CurPos = 0;

        byte SkipMech = 0;

...

              case Xtract:
                /*      Xtracting Part  */

                printf("\n  %2.2i (%24.24s): ", CntMods++, head.FileName );
                printf(" %5.5X => %6.6X, %2.2i%, ID: %8.8X",            
                            head.PackLen,                                   
    
                            head.RealLen,
                            ( 100 * head.PackLen / head.RealLen),           
    
                            head.TStamp);                                   
    
                                                                            
    

                memcpy(Buf2,head.FileName,head.FilenameLen);

                Buf2[head.FilenameLen] = '\x0';

No input validation on FilenameLen. It's only 1 byte, but it doesn't check for the sign, so you can overflow the 128 byte buffer on the stack with up to 255 bytes. 

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);
                        track->start = track->startsect * SECTLEN;
...

        printf("Writing tracks:\n\n");
        for (track = tracks; (track); track = track->next)
                writetrack(binf, track, basefile);
                
...

int writetrack(FILE *bf, struct track_t *track, char *bname)
{
        char *fname;
        FILE *f;
        char buf[SECTLEN+10];
        long sz, sect, realsz, reallen;
        char c, *p, *p2, *ep;
        int32_t l;
        int16_t i;
        float fl;
        
...
        if (fseek(bf, track->start, SEEK_SET)) {
                fprintf(stderr, " Could not fseek to track location: %s\n", strerror(errno));
                exit(4);
        }
        
        reallen = (track->stopsect - track->startsect + 1) * track->bsize;

Is it a useful bug to a security researcher? Can the above be misused with a negative startsect variable? My goal isn't to verify or trigger the bug in this particular case. It's just to identify unsafe code that is clearly buggy and that should be fixed. At this point, are we doing dev work, or security work?

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;

    
...

void read_header(t_abootimg* img)
{
  size_t rb = fread(&img->header, sizeof(boot_img_hdr), 1, img->stream);
  if ((rb!=1) || ferror(img->stream))

...

  if (check_boot_img_header(img))
    abort_printf("%s: not a valid Android Boot Image.\n", img->fname);
}

If we can bypass check_boot_img_header we can do some things..

int check_boot_img_header(t_abootimg* img)
{
  if (strncmp(img->header.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
    fprintf(stderr, "%s: no Android Magic Value\n", img->fname);
    return 1;
  }

...

  unsigned n = (img->header.kernel_size + page_size - 1) / page_size;
  unsigned m = (img->header.ramdisk_size + page_size - 1) / page_size;
  unsigned o = (img->header.second_size + page_size - 1) / page_size;

  unsigned total_size = (1+n+m+o)*page_size;

  if (total_size > img->size) {
    fprintf(stderr, "%s: sizes mismatches in boot image\n", img->fname);
    return 1;
  }

This is a simple integer overflow to calculate total_size. Lets find some potential places for heap overflows..

void extract_second(t_abootimg* img)
{
  unsigned psize = img->header.page_size;
  unsigned ksize = img->header.kernel_size;
  unsigned rsize = img->header.ramdisk_size;
  unsigned ssize = img->header.second_size;

  if (!ssize) // Second Stage not present
    return;

  unsigned n = (rsize + ksize + psize - 1) / psize;
  unsigned soffset = (1+n)*psize;

  printf ("extracting second stage image in %s\n", img->second_fname);

  void* s = malloc(ksize);
  if (!s)
    abort_perror(NULL);

  if (fseek(img->stream, soffset, SEEK_SET))
    abort_perror(img->fname);

  size_t rb = fread(s, ssize, 1, img->stream);
  if ((rb!=1) || ferror(img->stream))
    abort_perror(img->fname);

This is bad code. It's using malloc(ksize) but using ssize for the read. If we use the boot img header check bypass, we should be able to do bad things.


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 modules
        */
        byte    Multiple = 0, j = 0;


        sLen = StrLen(fname);
        for ( i = sLen; i > 0; i-- )
            {
                if( *(fname + i) == '/' || *(fname + i ) == '\\' ) { i++; break; }
            }

        memcpy(MyDirName, (fname + i), sLen - i);

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 0x27: /* single quote */
    case '\\':
    case '`':
      /* backslash special characters */
      *p++ = '\\';
      *p++ = ch;
      break;
    default:
      *p++ = ch;
    }
  }

  /* terminate string */
  *p = '\0';

  return dest;
}

It doesn't do any filtering or escaping on the - character. If we make a password begin with - we can make unzip think we are passing an option. This causes the system() command do something unexpected and not report the correct password unzipped the file.

Lets create a zip file with a password "--".

# fcrackzip --length 2-2 out.zip 
possible pw found: jW ()
possible pw found: oG ()
possible pw found: o[ ()
possible pw found: qo ()
possible pw found: rM ()
possible pw found: t7 ()
possible pw found: u- ()
possible pw found: x3 ()
possible pw found: zW ()
possible pw found: B7 ()
possible pw found: Dx ()
possible pw found: D% ()
possible pw found: HD ()
possible pw found: IK ()
possible pw found: J! ()
possible pw found: S: ()
possible pw found: TV ()
possible pw found: 0* ()
possible pw found: 2g ()
possible pw found: 5n ()
possible pw found: 6! ()
possible pw found: 9O ()
possible pw found: $o ()
possible pw found: %I ()
possible pw found: /J ()
possible pw found: )m ()
possible pw found: -2 ()
possible pw found: -- ()

It finds the password correctly. But you really want to use the -u option, otherwise you will get too many false positives.

# fcrackzip -u --length 2-2 out.zip 
#

It didn't detect it. A truly pointless bug.

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.

Thursday, 22 February 2018

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 to a stack overflow at the privilege of gid games.

Wednesday, 21 February 2018

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 bytes:

Font* load_font(char *fname)
{
    Font    *fnt = 0;
    FILE    *file = 0;
    char    path[512];
    int     i;

    get_full_font_path( path, fname );

    fnt = malloc(sizeof(Font));
    if (fnt == 0) {
        fprintf(stderr, "load_font: not enough memory\n");
        exit(1);
    }

    if ((fnt->pic = load_surf(path, SDL_HWSURFACE)) == 0)

Looks like we can make it large. Hence, a buffer overflow.

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.

Tuesday, 20 February 2018

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;

Monday, 19 February 2018

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)
        {
                SweepError("You do not have a username!");
                buf = "unknown";
        }
        strncpy(b->name, buf, sizeof(b->name)-1);

This may be a small bug, but b->name is not guaranteed to be NUL terminated. I included the xmalloc code because if calloc was used for memory allocation, then it would have been zeroed out. However, calloc was not used. Malloc does not zero memory.

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 ((Login = getlogin()) == NULL)
                Login = getpwuid(getuid())->pw_name;

...

+++ back to main()

        /* update some important player statistics */
        strcpy(Player.p_login, Login);

+++ how big is Player.p_login?

struct  player          /* player statistics */
    {
    double      p_experience;   /* experience */
    double      p_level;        /* level */
...
    char        p_login[SZ_LOGIN];      /* login */
    };

+++ ok.. so lets look at SZ_LOGIN

#define SZ_LOGIN        9               /* size of login (incl. trailing nul) */

So this code assumes login names are only 8 chars long? Otherwise there is a buffer overflow. The Player structure is in the bss section.

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

Sunday, 18 February 2018

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);

Wednesday, 14 February 2018

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]

...

        /*
         * Find the creation date of this game,
         * so as to avoid restoring outdated savefiles.
         */
        gethdate(hname);


bsdgames/hack/hack.unix.c

void
gethdate(name)
        char           *name;
{
#if 0
        /* old version - for people short of space */

        char *np;

        if(stat(name, &hbuf))
            error("Cannot get status of %s.",
                (np = strrchr(name, '/')) ? np+1 : name);
#else
        /* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */


        /*
         * The problem with   #include  <sys/param.h>   is that this include fil
e
         * does not exist on all systems, and moreover, that it sometimes includ
es
         * <sys/types.h> again, so that the compiler sees these typedefs twice.
         */
#define         MAXPATHLEN      1024

        const char           *np, *path;
        char            filename[MAXPATHLEN + 1];
        if (strchr(name, '/') != NULL || (path = getenv("PATH")) == NULL)
                path = "";

        for (;;) {
                if ((np = strchr(path, ':')) == NULL)
                        np = path + strlen(path);       /* point to end str */
                if (np - path <= 1)     /* %% */
                        (void) strcpy(filename, name);

+++ buffer overflow since we control name which is argv[0]

                else {

To trigger this crash..

cat /tmp/trigger/hack_overflow.c

#include <unistd.h>
#include <stdlib.h>
char buf[1500];
int
main(int argc, char *argv[], char *envp[])
{
 char *myargv[] = { buf, NULL };
 setenv("PATH", ":hi", 1);
 for (int i = 0; i < sizeof(buf); i++)
  buf[i] = 'A';
 buf[sizeof(buf) - 1] = 0;
 execve("/usr/games/hack", myargv, envp);
}

Silvio@kali:~$ gcc /tmp/trigger_hack_overflow.c -o /tmp/trigger_hack_overflow
silvio@kali:~$ /tmp/trigger_hack_overflow 
*** buffer overflow detected ***: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bfb)[0x7fd6d8eddbfb]
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7fd6d8f661e7]
/lib/x86_64-linux-gnu/libc.so.6(+0xf7320)[0x7fd6d8f64320]
/lib/x86_64-linux-gnu/libc.so.6(+0xf6682)[0x7fd6d8f63682]

Exploiting the Lorex 2K Indoor Wifi at Pwn2Own Ireland

Introduction In October InfoSect participated in Pwn2Own Ireland 2024 and successfully exploited the Sonos Era 300 smart speaker and Lor...