![]() |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Anonymous Access
Anonymous access to IIS virtual directories really means that requests from any user are welcome. There is no need for authentication. This is how most public web sites are set up. Anyone with a browser may point to a URL and get a public document. In reality IIS is configured to process anonymous requests in security context of a specific user account. The default account name is IUSR_<ComputerName>. For example, if a machine's name is SPUTNIK, then the account will be IUSR_SPUTNIK. See, for example, the picture in the "Tools Used for IIS Security Research" where a dump from Keith Brown' Token Dump component iddentifies the thread token owner as IUSR_SPUTNIK. This account is a default member of the system's Guest group. You can set up NTFS permissions on files to restrict this user. Also, another account may be chosen to process anonymous requests by editing anonymous access settings of a virtual directory. Behind the scenes the IIS process (inetinfo.exe) runs as a LocalSystem account. Threads processing anonymous web requests are impersonated as a specified user. I have written a simple code sample that illustrates how to retrieve public documents from web servers set up for anonymous access. The code is located in Iis/HttpAnonymousClient directory, and is using windows sockets. Here is its main function that contains all the logic.
#include <winsock.h>
#include "comm.h"
#include "http.h"
#define BUFSIZE (64*1024)
// Main.
int main(int argc, char *argv[])
{
SOCKET s;
unsigned long cbRead;
unsigned long cbSize = BUFSIZE;
char achData[BUFSIZE];
// Change as necessary.
char * pszServer = "sputnik"; // Notice that this might be an IP address, such as
// 10.1.5.148 or a resolvable full name of the machine
// such as webserver.mycompany.com.
char * pszDoc = "/1/1.htm";
// Initialize Winsock.
if (!InitWinsock())
return -1;
// Connect to server.
if (!ConnectSocket(pszServer, &s))
return -1;
// Build a normal HTTP GET request.
buildNormalGet(achData, &cbSize, pszDoc);
if (!SendBytes(s, (unsigned char *) achData, strlen(achData)))
return -1;
// Receive data from server.
if (!ReceiveBytes(s, (unsigned char *) achData, BUFSIZE, &cbRead))
return -1;
// Display received data.
::MessageBox(NULL, achData, "Data returned from web server", MB_OK | MB_ICONINFORMATION);
// Terminate socket.
CloseSocket(s);
TermWinsock();
return 0;
}
Basically, I open a port 80 socket on the destination machine, send over it an HTTP GET request, then read data coming back and display it. Here is what the program displays on my system.
The result of an anonymous document retrieval of the Hello, World! document.
You might be interested in how I format the HTTP GET request. Here is the code:
#include <string.h>
static char Headers[] = "HTTP/1.0\r\n"
"User-Agent: NtlmHttpClient\r\n"
"Content-type: text/html\r\n"
"Accept: */*\r\n"
"Connection: Keep-Alive\r\n";
/*
* buildNormalGet
* Builds a normal HTTP GET request.
*
* Parameters:
* pData - data buffer to build a request in.
* pcbSize - points to data size.
* pURL - URL.
* Returns - 0 if we are okay.
*/
int buildNormalGet(char * pData, unsigned long * pcbSize, char * pURL)
{
memset(pData, 0, *pcbSize);
strcpy(pData, "GET ");
strcat(pData, pURL);
strcat(pData, " ");
strcat(pData, Headers);
strcat(pData, "\r\n");
return 0;
}
For completeness I have conducted a series of experiments capturing all network traffic between client applications and a web server in different configurations. The captured data is available in Iis\NetMonCaptures directory. I had 2 client applications to play with - my custom made HttpAnonymousClient and Internet Explorer 5.0. I had used IIS 5.0 and 4.0 for experiments. The results are summmarized in the following table.
|