Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent fingerprinting ZMap by randomizing the IP ID #798

Merged
merged 14 commits into from Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion examples/probe-modules/module_tcp_cisco_backdoor.c
Expand Up @@ -17,6 +17,7 @@

#include "../../lib/includes.h"
#include "../fieldset.h"
#include "aesrand.h"
phillip-stephens marked this conversation as resolved.
Show resolved Hide resolved
#include "probe_modules.h"
#include "packet.h"

Expand Down Expand Up @@ -64,7 +65,7 @@ static int synscan_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw,

static int synscan_make_packet(void *buf, UNUSED size_t *buf_len,
ipaddr_n_t src_ip, ipaddr_n_t dst_ip, uint8_t ttl,
uint32_t *validation, int probe_num,
uint32_t *validation, int probe_num, aesrand_t *aes,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to make sure here that we're not passing in the same entropy that's passed in from the uint32_t *validation parameter. It might make sense to pass in IPID directly too since that's more tightly typed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, I've moved to only generating the ip_id in send.c here and passing it directly in.

Also, I changed to using random_bytes which reads from /dev/urandom, should be completely distinct from any other RNG in our code.

UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
Expand All @@ -85,6 +86,8 @@ static int synscan_make_packet(void *buf, UNUSED size_t *buf_len,
ip_header->ip_dst.s_addr, tcp_header);

ip_header->ip_sum = 0;
// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);
ip_header->ip_sum = zmap_ip_checksum((unsigned short *)ip_header);

return EXIT_SUCCESS;
Expand Down
5 changes: 4 additions & 1 deletion src/probe_modules/module_bacnet.c
Expand Up @@ -76,7 +76,8 @@ int bacnet_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw, void **arg)

int bacnet_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num, UNUSED void *arg)
uint32_t *validation, int probe_num, aesrand_t* aes,
UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand All @@ -87,6 +88,8 @@ int bacnet_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ip_header->ip_dst.s_addr = dst_ip;
ip_header->ip_ttl = ttl;
ip_header->ip_sum = 0;
// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);

udp_header->uh_sport =
htons(get_src_port(num_ports, probe_num, validation));
Expand Down
5 changes: 4 additions & 1 deletion src/probe_modules/module_dns.c
Expand Up @@ -776,7 +776,8 @@ int get_dns_question_index_by_probe_num(int probe_num) {

int dns_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num, UNUSED void *arg)
uint32_t *validation, int probe_num,
aesrand_t* aes, UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand Down Expand Up @@ -808,6 +809,8 @@ int dns_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ip_header->ip_src.s_addr = src_ip;
ip_header->ip_dst.s_addr = dst_ip;
ip_header->ip_ttl = ttl;
// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);
// Above we wanted to look up the dns question index (so we could send 2 probes for the same DNS query)
// Here we want the port to be unique regardless of if this is the 2nd probe to the same DNS query so using
// probe_num itself to set the unique UDP source port.
Expand Down
6 changes: 5 additions & 1 deletion src/probe_modules/module_icmp_echo.c
Expand Up @@ -163,7 +163,8 @@ static int icmp_echo_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw,
static int icmp_echo_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, UNUSED port_n_t dst_port,
uint8_t ttl, uint32_t *validation,
UNUSED int probe_num, UNUSED void *arg)
UNUSED int probe_num, aesrand_t* aes,
UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand All @@ -187,6 +188,9 @@ static int icmp_echo_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
size_t ip_len = sizeof(struct ip) + ICMP_MINLEN + icmp_payload_len;
ip_header->ip_len = htons(ip_len);

// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);

ip_header->ip_sum = 0;
ip_header->ip_sum = zmap_ip_checksum((unsigned short *)ip_header);
*buf_len = ip_len + sizeof(struct ether_header);
Expand Down
6 changes: 5 additions & 1 deletion src/probe_modules/module_icmp_echo_time.c
Expand Up @@ -55,7 +55,8 @@ static int icmp_echo_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw,
static int icmp_echo_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, UNUSED port_n_t dport,
uint8_t ttl, uint32_t *validation,
UNUSED int probe_num, UNUSED void *arg)
UNUSED int probe_num, aesrand_t* aes,
UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand Down Expand Up @@ -88,6 +89,9 @@ static int icmp_echo_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
sizeof(struct icmp_payload_for_rtt);
ip_header->ip_len = htons(ip_len);

// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);

ip_header->ip_sum = 0;
ip_header->ip_sum = zmap_ip_checksum((unsigned short *)ip_header);

Expand Down
4 changes: 3 additions & 1 deletion src/probe_modules/module_tcp_synackscan.c
Expand Up @@ -54,7 +54,7 @@ static int synackscan_make_packet(void *buf, UNUSED size_t *buf_len,
ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num,
UNUSED void *arg)
aesrand_t* aes, UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand All @@ -66,6 +66,8 @@ static int synackscan_make_packet(void *buf, UNUSED size_t *buf_len,
ip_header->ip_src.s_addr = src_ip;
ip_header->ip_dst.s_addr = dst_ip;
ip_header->ip_ttl = ttl;
// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);

tcp_header->th_sport =
htons(get_src_port(num_ports, probe_num, validation));
Expand Down
6 changes: 5 additions & 1 deletion src/probe_modules/module_tcp_synscan.c
Expand Up @@ -53,7 +53,7 @@ static int synscan_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw,
static int synscan_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num,
UNUSED void *arg)
aesrand_t* aes, UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand All @@ -73,6 +73,10 @@ static int synscan_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
tcp_header->th_sum = tcp_checksum(ZMAP_TCP_SYNSCAN_TCP_HEADER_LEN,
ip_header->ip_src.s_addr,
ip_header->ip_dst.s_addr, tcp_header);

// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);

// checksum value must be zero when calculating packet's checksum
ip_header->ip_sum = 0;
ip_header->ip_sum = zmap_ip_checksum((unsigned short *)ip_header);
Expand Down
2 changes: 1 addition & 1 deletion src/probe_modules/module_tcp_synscan.h
Expand Up @@ -27,7 +27,7 @@ int synscan_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw,

int synscan_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
uint8_t ttl, uint32_t *validation, int probe_num,
UNUSED void *arg);
aesrand_t* aes, UNUSED void *arg);

void synscan_print_packet(FILE *fp, void *packet);

Expand Down
6 changes: 5 additions & 1 deletion src/probe_modules/module_udp.c
Expand Up @@ -270,7 +270,8 @@ int udp_init_perthread(void *buf, macaddr_t *src, macaddr_t *gw, void **arg_ptr)

int udp_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num, UNUSED void *arg)
uint32_t *validation, int probe_num, aesrand_t* aes,
UNUSED void *arg)
{
struct ether_header *eth_header = (struct ether_header *)buf;
struct ip *ip_header = (struct ip *)(&eth_header[1]);
Expand All @@ -285,6 +286,9 @@ int udp_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
htons(get_src_port(num_ports, probe_num, validation));
udp_header->uh_dport = dport;

// set the IP id field to be a random value using the fast AES generator
ip_header->ip_id = (u_short)aesrand_getword(aes);

ip_header->ip_sum = 0;
ip_header->ip_sum = zmap_ip_checksum((unsigned short *)ip_header);

Expand Down
3 changes: 2 additions & 1 deletion src/probe_modules/module_udp.h
Expand Up @@ -64,7 +64,8 @@ void udp_print_packet(FILE *fp, void *packet);

int udp_make_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num, void *arg);
uint32_t *validation, int probe_num, aesrand_t* aes,
void *arg);
int udp_make_templated_packet(void *buf, size_t *buf_len, ipaddr_n_t src_ip,
ipaddr_n_t dst_ip, port_n_t dport, uint8_t ttl,
uint32_t *validation, int probe_num, void *arg);
Expand Down
2 changes: 1 addition & 1 deletion src/probe_modules/probe_modules.h
Expand Up @@ -52,7 +52,7 @@ typedef int (*probe_make_packet_cb)(void *packetbuf, size_t *buf_len,
ipaddr_n_t src_ip, ipaddr_n_t dst_ip,
port_n_t dst_port, uint8_t ttl,
uint32_t *validation, int probe_num,
void *arg);
aesrand_t* aes, void *arg);

typedef void (*probe_print_packet_cb)(FILE *, void *packetbuf);

Expand Down
3 changes: 2 additions & 1 deletion src/send.c
Expand Up @@ -228,6 +228,7 @@ int send_run(sock_t st, shard_t *s)
zconf.probe_module->thread_initialize(
buf, zconf.hw_mac, zconf.gw_mac, &probe_data);
}
aesrand_t* aes_rand_gen = aesrand_init_from_seed(random());
pthread_mutex_unlock(&send_mutex);

// adaptive timing to hit target rate
Expand Down Expand Up @@ -376,7 +377,7 @@ int send_run(sock_t st, shard_t *s)
zconf.probe_module->make_packet(
buf, &length, src_ip, current_ip,
htons(current_port), ttl, validation, i,
probe_data);
aes_rand_gen, probe_data);
if (length > MAX_PACKET_SIZE) {
log_fatal(
"send",
Expand Down