Add capabilities check for CAP_NET_RAW (root always has it)

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2023-05-16 21:02:29 +02:00
parent 8a299112b8
commit e3550c1a47
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
3 changed files with 58 additions and 0 deletions

View File

@ -21,6 +21,47 @@ static const unsigned int capabilityIDs[] = { CAP_CHOWN , CAP_DAC_OVERRIDE ,
static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP"};
static const unsigned int numCaps = sizeof(capabilityIDs) / sizeof(*capabilityIDs);
bool check_capability(const unsigned int cap)
{
// First assume header version 1
int capsize = 1; // VFS_CAP_U32_1
cap_user_data_t data = NULL;
cap_user_header_t hdr = calloc(sizeof(*hdr), capsize);
// Determine capabilities version used by the current kernel
capget(hdr, NULL);
// Check version
if (hdr->version != LINUX_CAPABILITY_VERSION_1)
{
// If unknown version, use largest supported version (3)
// Version 2 is deprecated according to linux/capability.h
if (hdr->version != LINUX_CAPABILITY_VERSION_2)
{
hdr->version = LINUX_CAPABILITY_VERSION_3;
capsize = 2; // VFS_CAP_U32_3
}
else
{
// Use version 2
capsize = 2; // VFS_CAP_U32_2
}
}
// Get current capabilities
data = calloc(sizeof(*data), capsize);
capget(hdr, data);
// Check if the capability is available
const bool available = ((data->permitted & (1 << cap)) && (data->effective & (1 << cap)));
// Free memory
free(hdr);
free(data);
return available;
}
bool check_capabilities(void)
{
// First assume header version 1

View File

@ -10,6 +10,7 @@
#ifndef CAPABILITIES_H
#define CAPABILITIES_H
bool check_capability(const unsigned int cap);
bool check_capabilities(void);
#endif //CAPABILITIES_H

View File

@ -16,6 +16,9 @@
#include "dhcp-discover.h"
// sleepms()
#include "timers.h"
// check_capability()
#include "capabilities.h"
#include <linux/capability.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
@ -184,7 +187,9 @@ static int create_arp_socket(const int ifindex, const char *iface, const char **
if(arp_socket < 0)
{
*error = strerror(errno);
#ifdef DEBUG
printf("Unable to create socket for ARP communications on interface %s: %s\n", iface, *error);
#endif
return -1;
}
@ -196,7 +201,9 @@ static int create_arp_socket(const int ifindex, const char *iface, const char **
if (bind(arp_socket, (struct sockaddr*) &sll, sizeof(struct sockaddr_ll)) < 0)
{
*error = strerror(errno);
#ifdef DEBUG
printf("Unable to bind socket for ARP communications on interface %s: %s\n", iface, *error);
#endif
close(arp_socket);
return -1;
}
@ -208,7 +215,9 @@ static int create_arp_socket(const int ifindex, const char *iface, const char **
if (setsockopt(arp_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
{
*error = strerror(errno);
#ifdef DEBUG
printf("Unable to set timeout for ARP communications on interface %s: %s\n", iface, *error);
#endif
close(arp_socket);
return -1;
}
@ -530,6 +539,13 @@ static void print_results(struct thread_data *thread_data)
int run_arp_scan(const bool scan_all)
{
// Check if we are capable of sending ARP packets
if(!check_capability(CAP_NET_RAW))
{
puts("Error: Insufficient permissions or capabilities (needs CAP_NET_RAW). Try running as root (sudo)");
return EXIT_FAILURE;
}
arp_all = scan_all;
puts("Discovering IPv4 hosts on the network using the Address Resolution Protocol (ARP)...\n");