[TOOL] ARP Promiscuous Node Detection
From: support@securiteam.com
Date: 01/05/03
- Previous message: support@securiteam.com: "[NT] iCal Remote DoS and Path Disclosure"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
From: support@securiteam.com To: list@securiteam.com Date: 5 Jan 2003 11:31:46 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
Beyond Security would like to welcome Tiscali World Online
to our service provider team.
For more info on their service offering IP-Secure,
please visit http://www.worldonline.co.za/services/work_ip.asp
- - - - - - - - -
ARP Promiscuous Node Detection
------------------------------------------------------------------------
DETAILS
APD is a promiscuous node detection tool which uses ARP packets to
determine whether or not a host is in promiscuous mode.
Tool source code:
/*
* APD v1.1b : Arp Promiscuous Node Detection
*
* Copyright (C) 2002 Dr.Tek of Malloc() Security
* Contact: Dr.Tek <tek@superw00t.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*
*
* Malloc() Security (www.malloc.tk)
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <netdb.h>
#include <string.h>
#if __BYTE_ORDER == __BIG_ENDIAN
#define HFIX_S(x) (x)
#define HFIX_L(x) (x)
#define NFIX_S(x) (x)
#define NFIX_L(x) (x)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
#define HFIX_S(x) htons(x)
#define HFIX_L(x) htonl(x)
#define NFIX_S(x) ntohs(x)
#define NFIX_L(x) ntohl(x)
#endif
#ifndef ETH_P_ARP
#define ETH_P_ARP 0x0806
#endif
#ifndef SIOCGIFCONF
#define SIOCGIFCONF 0x8912
#endif
#define SIOCGIFHWADDR 0x8927
#ifndef TIMEOUT
#define TIMEOUT 100
#endif
typedef unsigned char uchar;
typedef unsigned short u16;
typedef unsigned long u32;
#define ARP_ETHER 1
#define ETH_HWLEN 6
#define ARP_FRAME 0x8060
#define IP_PTYPE 0x0800
#define OP_ARPREQ 2
#define IP_ALEN 4
#define MAX_DLEN 5
#define ARP_REQ 1 /* ARP Request opcode */
#define ARP_REP 2 /* ARP Reply opcode */
#define ETH_LEN 0x0e
#define ARP_LEN 0x1c
char*
inet_ntoa(u32);
u32
inet_addr(const char *);
/* structure for ETH Packet */
struct eth_pkt {
uchar t_addr[ETH_HWLEN];
uchar s_addr[ETH_HWLEN];
u16 frame_type;
};
/* structure for ARP Packet */
struct arp_pkt {
u16 hw_type;
u16 prot_type;
uchar hwaddr_sz;
uchar praddr_sz;
u16 op;
uchar sndr_hw_addr[ETH_HWLEN];
uchar sndr_ip_addr[IP_ALEN];
uchar rcpt_hw_addr[ETH_HWLEN];
uchar rcpt_ip_addr[IP_ALEN];
};
void apd_start_testing(u32 src, u32 dst,uchar *dev)
{
int haddr_sckt=0 , out_sckt=0 , c=0 , sz=0 , i ,
arp_proto=HFIX_S(ETH_P_ARP);
register int in_sckt;
struct ifreq ifr;
struct sockaddr sndarp;
uchar pkt[ETH_LEN+ARP_LEN+1];
struct eth_pkt eth_p;
struct arp_pkt arp_p;
struct arp_pkt *in_a;
uchar in_hwaddr[6];
uchar in_buf[ETH_LEN+ARP_LEN+20];
uchar pseudo_hw_d[ETH_HWLEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE};
uchar pseudo_hw_s[ETH_HWLEN] = {00,11,22,33,44,55};
uchar pseudo_hw_a[ETH_HWLEN] = {0x00,0x00,0x00,0x00,0x00,0x00};
/* Retrieving Hardware Address from NIC */
strcpy(ifr.ifr_name,dev);
if((haddr_sckt=socket(AF_INET,SOCK_DGRAM,0))<0)
{
fprintf(stderr,"Error creating pseudo socket!\n");
exit(-1);
}
if((ioctl(haddr_sckt,SIOCGIFHWADDR,&ifr))<0)
{
perror("ioctl:");
close(haddr_sckt);
exit(-1);
}
memcpy(in_hwaddr,(uchar *)ifr.ifr_hwaddr.sa_data,6);
close(haddr_sckt);
printf("==> Probing host: %s\n",inet_ntoa(dst));
sleep(2);
/* Creating out socket! */
if((out_sckt=socket(AF_INET,SOCK_PACKET, arp_proto ))<0)
{
fprintf(stderr,"Error creating socket!\n");
exit(-1);
}
/* Creating in socket! */
if((in_sckt=socket(AF_INET,SOCK_PACKET, arp_proto))<0)
{
fprintf(stderr,"Error creating socket!\n");
exit(-1);
}
bzero(pkt,ETH_LEN+ARP_LEN);
memcpy(ð_p.t_addr,pseudo_hw_d,ETH_HWLEN);
memcpy(ð_p.s_addr,pseudo_hw_s,ETH_HWLEN);
eth_p.frame_type = HFIX_S(ETH_P_ARP);
memcpy(pkt,ð_p,ETH_LEN);
arp_p.hw_type = HFIX_S(ARP_ETHER);
arp_p.prot_type = HFIX_S(IP_PTYPE);
arp_p.hwaddr_sz = ETH_HWLEN;
arp_p.praddr_sz = IP_ALEN;
arp_p.op = HFIX_S(ARP_REQ);
memcpy(&arp_p.sndr_hw_addr, in_hwaddr, ETH_HWLEN);
memcpy(&arp_p.sndr_ip_addr,&src,4);
memcpy(&arp_p.rcpt_hw_addr,pseudo_hw_a ,ETH_HWLEN);
memcpy(&arp_p.rcpt_ip_addr, &dst,4);
memcpy(pkt+ETH_LEN,&arp_p,ARP_LEN);
strcpy(sndarp.sa_data,dev);
if((sendto(out_sckt,pkt,ETH_LEN+ARP_LEN,0,&sndarp,sizeof(sndarp)))<0)
{
fprintf(stderr,"Error sending packet!\n");
exit(-1);
}
close(out_sckt);
i = fcntl(in_sckt,F_GETFL);
if ((fcntl(in_sckt,F_SETFL,i | O_NONBLOCK))<0)
{
perror("fcntl:");
close(in_sckt);
exit(-1);
}
/* Awaiting ARP Reply from possible culprit! */
while(c<TIMEOUT)
{
bzero(in_buf,ETH_LEN+ARP_LEN);
if((sz=read(in_sckt,in_buf,ETH_LEN+ARP_LEN))<0)
{
usleep(50000);
c++; /* Wait, isn't this a programming language
:P */
}
if(sz>=ETH_LEN+ARP_LEN)
{
in_a = (struct arp_pkt *) (in_buf+ETH_LEN);
if((NFIX_S(in_a->op)) == ARP_REP)
{
fprintf(stdout,"==> %s is in promiscuous
mode.\n\n",inet_ntoa(dst)); fflush(stdout);
close(in_sckt);
sleep(2);
break;
}
}
}
if(c==TIMEOUT)
{
fprintf(stdout,"==> %s is not in
promiscuous mode.\n\n",inet_ntoa(dst));
close(in_sckt);
sleep(2);
}
}
void apd_banner()
{
printf("\n\nAPD v1.1b : ARP Promiscuous Node Detection.\n");
printf("Written by: Dr.Tek of Malloc() Security\n\n");
}
u32 get_our_addr()
{
u32 i;
char hname[80+1];
struct hostent *h;
gethostname(hname,80);
i=inet_addr(hname);
if(i == -1)
{
if((h=gethostbyname(hname))==NULL)
{
fprintf(stderr,"Invalid hostname.\n");
exit(-1);
}
bcopy(h->h_addr,(char *)&i,h->h_length);
}
return i;
}
u32 resv_addr(char *haddr)
{
u32 i;
struct hostent *h;
i=inet_addr(haddr);
if(i == -1)
{
if((h=gethostbyname(haddr))==NULL)
{
fprintf(stderr,"Invalid host\n");
exit(-1);
}
bcopy(h->h_addr,(char *)&i,h->h_length);
}
return i;
}
void sig_handler(int sig);
int main(int argc , char **argv)
{
int o;
u32 ip_s ,ip_e, ip_t , tmp;
char iface_dev[MAX_DLEN];
iface_dev[MAX_DLEN]='\0';
bzero(iface_dev,MAX_DLEN);
apd_banner();
if(argc<6)
{
fprintf(stderr,"%s [options]\n\n",argv[0]);
fprintf(stderr,"Options:\n\n");
fprintf(stderr,"-s addr : Start address.\n");
fprintf(stderr,"-e addr : End address.\n");
fprintf(stderr,"-d dev : network device.\n\n\n");
exit(0);
}
while((o = getopt(argc ,argv ,"s:e:d:"))!=EOF)
{
switch(o) {
case 's':
ip_s=resv_addr((char *)optarg);
break;
case 'e':
ip_e=resv_addr((char *)optarg);
break;
case 'd':
strncpy(iface_dev,(char *)optarg,MAX_DLEN-1);
break;
}
}
ip_t=get_our_addr();
signal(SIGINT ,sig_handler);
signal(SIGTERM,sig_handler);
signal(SIGHUP ,SIG_IGN);
printf("-----[ APD starting ]-----\n\n");
sleep(2);
apd_start_testing(ip_t,ip_s,iface_dev);
ip_s = NFIX_L(ip_s);
tmp = HFIX_L(++ip_s);
while(tmp<=ip_e)
{
apd_start_testing(ip_t,tmp,iface_dev);
tmp = HFIX_L(++ip_s);
sleep(2);
if(tmp<ip_s) break;
}
printf("-----[ APD ending ] -----\n\n");
exit(0);
}
void sig_handler(int sig)
{
printf("Exiting!\n\n");
exit(0);
sleep(2);
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:tek@superw00t.com> Dr. Tek.
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Next message: support@securiteam.com: "[UNIX] OpenTopic XSS Security Hole"
- Previous message: support@securiteam.com: "[NT] iCal Remote DoS and Path Disclosure"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [PATCH 07/37] Security: De-embed task security record from task and use refcounting [ver #34]
... Remove the temporarily embedded task security record from task_struct. ... from
the task_security struct instead of from signal_struct. ... The keyring functions
then take pointers to task_security structs rather than ... goto out_free_user; ...
(Linux-Kernel) - [PATCH 11/45] Security: De-embed task security record from task and use refcounting [ver #35]
... Remove the temporarily embedded task security record from task_struct. ... from
the task_security struct instead of from signal_struct. ... if (ret < 0) ...
goto security_error; ... (Linux-Kernel) - [PATCH 07/37] Security: De-embed task security record from task and use refcounting
... Remove the temporarily embedded task security record from task_struct. ... from
the task_security struct instead of from signal_struct. ... The keyring functions
then take pointers to task_security structs rather than ... goto out_free_user; ...
(Linux-Kernel) - [PATCH 07/28] SECURITY: De-embed task security record from task and use refcounting [try #2]
... Remove the temporarily embedded task security record from task_struct. ... from
the task_security struct instead of from signal_struct. ... The keyring functions
then take pointers to task_security structs rather than ... goto security_error; ...
(Linux-Kernel) - [PATCH 7/7] SECURITY: De-embed task security record from task and use refcounting
... Remove the temporarily embedded task security record from task_struct. ... from
the task_security struct instead of from signal_struct. ... The keyring functions
then take pointers to task_security structs rather than ... goto security_error; ...
(Linux-Kernel)