touch-packages team mailing list archive
-
touch-packages team
-
Mailing list archive
-
Message #75410
[Bug 1448396] Re: DNS Query poisoning Application UDP socket descriptor
** Information type changed from Private Security to Public
--
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to eglibc in Ubuntu.
https://bugs.launchpad.net/bugs/1448396
Title:
DNS Query poisoning Application UDP socket descriptor
Status in eglibc package in Ubuntu:
New
Bug description:
Problem Description:
When DNS query is fired from ubuntu (14.04) it uses random source port
to send outgoing DNS request. It has been observed that random source
port is not being checked if the port is already in use by other user
application. As a result When DNS server sends the response, response
is received by user application which may cause corruption/security
issues in the application code.
To make the problem easily reproducible we have increased few system
limits to create 25000 UDP servers so that UDP port conflict with DNS
happen frequntly
Steps to Reproduce problem:
========================
Step 1. Increase limit
Per-User Limit
Open file: /etc/security/limits.conf
Paste following towards end:
* hard nofile 500000
* soft nofile 500000
root hard nofile 500000
root soft nofile 500000
System-Wide Limit
Set this higher than user-limit set above.
Open /etc/sysctl.conf
Add following:
fs.file-max = 2097152
Step 2. Reboot ubuntu
Step 3. Verify new limits
Use following command to see max limit of file descriptors:
#cat /proc/sys/fs/file-max
Hard Limit
#ulimit -Hn
Soft Limit
#ulimit -Sn
Step 4. Put following code in server.c and compile it (gcc server.c -o
server). This will bind 25K UDP ports.
/*
* server.c
*
* Author: Vipin Kumar Gahlaut
*
* CoreEmbedded Technologies Pvt Ltd
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#define MAX_CONNECTIONS 25000
#define MAX_IP_STR 16
#define MAX_EPOLL_EVENTS_PER_RUN 1
int setup_udp_server(char *ip, int port)
{
int sock;
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons (port);
saddr.sin_addr.s_addr = inet_addr(ip);
if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("Failed to created UDP Socket :%m\n");
return -1;
}
if (bind (sock, (struct sockaddr *)&saddr, sizeof (saddr)) < 0)
{
close (sock);
printf("Failed to bind on UDP port :%m\n");
return -1;
}
return sock;
}
int main (int argc, char *argv[])
{
char ip[MAX_IP_STR];
char buf[1024];
int efd,sfd,nfds;
struct epoll_event ev,*events;
int i=0,len;
struct sockaddr_in saddr;
socklen_t addrlen=sizeof(struct sockaddr_in);
if(argc < 2)
{
printf("Usage: server <ip>\n");
exit(0);
}
if(strlen(argv[1]) >= MAX_IP_STR)
{
printf("Failed: Invalid IP Address\n");
exit(0);
}
strcpy(ip,argv[1]);
if((efd = epoll_create1(0)) < 0)
{
printf("Failed: epoll_create1: %m\n");
exit(0);
}
for(i=0; i<MAX_CONNECTIONS; i++)
{
if((sfd=setup_udp_server(ip, 0)) < 0)
{
exit(0);
}
ev.events = EPOLLIN | EPOLLET | EPOLLERR;
ev.data.fd = sfd;
if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &ev) < 0)
{
printf("Couldn't add client socket to epoll set: %m\n");
exit(0);
}
if (getsockname(sfd, (struct sockaddr *)&saddr, &addrlen ))
{
printf("Failed to get port for socket: %m\n");
exit(0);
}
printf("FD: %d Port: %d Number of active servers: %d\n",sfd, ntohs(saddr.sin_port), i);
}
events = (struct epoll_event *)malloc(
MAX_EPOLL_EVENTS_PER_RUN * sizeof(struct epoll_event));
if(events == NULL)
{
exit(0);
}
while(1)
{
nfds = epoll_wait(efd, events, MAX_EPOLL_EVENTS_PER_RUN, -1);
if (nfds < 0)
{
printf("epoll_wait failed: %m\n");
exit(0);
}
for(i = 0; i < nfds; i++)
{
if (getsockname(events[i].data.fd, (struct sockaddr *)&saddr, &addrlen ))
{
printf("Failed to get port for socket: %m\n");
exit(0);
}
printf("epoll waked on fd: %d port %d\n",events[i].data.fd,ntohs(saddr.sin_port));
if(events[i].events & EPOLLIN)
{
len = recvfrom(events[i].data.fd, buf, 1024, 0,
(struct sockaddr *)&saddr, &addrlen);
printf("Received %d bytes on %d fd %m\n",len, events[i].data.fd);
printf("Source IP:Port %s:%d\n",inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
}
}
}
close(efd);
return 0;
}
Step 5. Run server program by providing IP address of machine (example
./server 192.168.0.2)
Step 6. User following shell script in another terminal to initiate
DNS queries
#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 100 ]; do
nslookup www.ubuntu.com
done
Step 7. Observe that sometime DNS response is received by ./server
instead of DNS client
Problem Analysis: We have observed on wireshark that when problem
happens source port used by DNS client/resolver library etc is one of
the source port on which user application (in this case server) is
already bind on that port and using it.
This is a big concern because it causes problem both in DNS client
(times out) and user application received spurious data. To my opinion
this is a security issue as I am receiving data on a port that I have
not exposed to anybody and depending on data it my crash/hijack my
application. So I am also marking this bug as a security vulnerability
so that security team can better asses the situation.
Please note that With small number of UDP server chances of port
conflict reduces but does not eliminate problem. DNS clinet/resolver
library must have checked if source port is already in use or better
to bind on port 0 (zero) so that system allocates available port not
just random port. DNS client need to use random **available** port not
just a random port.
ProblemType: Bug
DistroRelease: Ubuntu 14.04
Package: libc6-dev 2.19-0ubuntu6
ProcVersionSignature: Ubuntu 3.13.0-24.46-generic 3.13.9
Uname: Linux 3.13.0-24-generic i686
ApportVersion: 2.14.1-0ubuntu3
Architecture: i386
CurrentDesktop: Unity
Date: Sat Apr 25 13:03:30 2015
InstallationDate: Installed on 2014-05-20 (339 days ago)
InstallationMedia: Ubuntu 14.04 LTS "Trusty Tahr" - Release i386 (20140417)
SourcePackage: eglibc
UpgradeStatus: No upgrade log present (probably fresh install)
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1448396/+subscriptions