Building Open Source Network Security Tools Invictus Ferramenta
Building Open Source Network Security Tools Invictus Ferramenta Mike Schiffman The RSA Conference, April 2003
Today’s Presentation is an Overview of This:
Agenda 1. Introduction and Overview 2. The Modular Model of Network Security Tools 3. The Component and Technique Layers 4. Network Security Tool Classification 5. Active and Passive Reconnaissance Technique Details 6. Modeling Existing Tools 7. Inside a Network Security Tool: Firewalk Internals 8. Questions and Comments
Primer on Mike Schiffman • Researcher, Cisco Systems • Critical Infrastructure Assurance Group (CIAG), Cisco Systems • Technical Advisory Board for Qualys, IMG Universal • Consulting Editor for Wiley & Sons • R&D, Consulting and Speaking background: • Firewalk, Libnet, Libsf, Libradiate, Various whitepapers and reports • Done time with: @stake, Guardent, Cambridge Technology Partners, ISS • Author: • Building Open Source Network Security Tools, Wiley & Sons • Hacker’s Challenge Book I, Osborne Mc. Graw-Hill • Hacker’s Challenge Book II, Osborne Mc. Graw-Hill
Overview • What you will learn today • A new model for conceptualizing and describing network security tools • How to apply this model to existing tools • How to use this model to rapidly build new tools • Common network security tool techniques and how they are codified • What you should already know • General understanding of the TCP/IP protocol suite • Primarily layers 1 – 3 (OSI layers 2 – 4) • General network security concepts • For example; the difference between packet sniffing and port scanning • The C programming language
Before we start… • Where should I spend my focus…? • Lots of material • Show of hands… • Libnet • Libpcap • The Paradigm and NST terminology • Code?
Paradigm Overview
Technically Accurate. Not Tangible. What is a Network Security Tool? A network security tool is an algorithmic implement that is esigned to probe, assess, or increase the overall safety of or mitigate We need something risk associated withbetter… an entity across a communications medium. (there is something better) Unwieldy. Too Clinical.
A (New) Paradigm • Functional • Tangible and Visual • Specifies a simple taxonomy for grouping and ordering tools • Tool Classifications • Separates a network security tool into three layers or tiers • Component, Technique, Control • Hierarchical dependencies • An object at a higher layer has dependencies on one or more objects below it
The Modular Model of Network Security Tools
The Component Layer • Most fundamental layer • Answers the question “How does this tool do what it does? ” • Task oriented and specific • Components tend to outlay the developmental requirements and restraints of the tool • Software Development Lifecycle • C programming libraries • Robust, portable and generally simple APIs • Libpcap, Libnet, Libsf, Libnids, Libdnet, Open. SSL
The Component Layer with Dependencies
The Technique Layer • Answers the question: “What does this tool do? ” • More abstract and solution focused • The core essence of the tool is captured at this layer • When building or classifying tools, we start here • Class taxonomy is set at this layer • Packet Sniffing (Passive Reconnaissance) • Port Scanning (Active Reconnaissance) • Vulnerability Testing (Attack and Penetration) • Firewalling (Defensive)
Network Security Tool Taxonomy • Simple method allowing for tool grouping • Tied to the Technique Layer • Tools may certainly fit in more than one category (Venn diagram) • Passive Reconnaissance • Active Reconnaissance • Attack and Penetration • Defensive
The Technique Layer with Classification Bindings
Classification Overview
Passive Reconnaissance Tools • Gather information in an ostensibly non-detectable or unobtrusive way • Tend to have long lifecycles in terms of utility • Changes no state on the entity • Tcpdump • Ethereal • Mailsnarf
Active Reconnaissance Tools • Gather information in a detectable way, often by sending network traffic and waiting for responses • Tend to have long lifecycles in terms of utility • Changes very little if any state on the entity • Firewalk • Strobe • Nmap • Traceroute
Attack and Penetration Tools • Test for the existence of and/or exploit vulnerabilities • Tools can have a very limited lifetime • i. e. : Remote overflow in IIS version 5. 0 • Often supported by Reconnaissance Tools • Nessus • SSH CRC 32 overflow exploit • apache-scalp. c
Defensive Tools • Keeps an entity safe often by protecting data or detecting illicit activity • Tend to be more complex and have extended execution lifetimes • Snort • GPG • PF (packet filter on Open. BSD)
The Control Layer • General abstract “glue layer” • Can be thought of as a delivery mechanism for techniques • Less concerned with security-related topics as with program cohesion • Not the focus of this presentation • Command Control • Reporting • Data Correlation and Storage
The Model and The Software Development Lifecycle
Component Layer Details Libpcap Libnet Libnids Libsf Libdnet Open. SSL
Component Layer Details: Libpcap • Library for packet capture and filtering • Support for live capture and offline storage • Useful for building applications that need to do the following: • Network statistics collection • Network debugging • Security monitoring • Often found in active and passive reconnaissance tools
Typical Libpcap Usage
Component Layer Details: Libnet • Library for packet construction and injection • Useful for building applications that need to do the following: • Network security testing • Network bandwidth testing • Network utility • Definitely the most debonair and sophisticated of the components – truly a discriminating programmer’s component • New version (1. 1. 1) is much more robust than its predecessors • Simple interface for novice users or • Powerful advanced interface • Often found in active reconnaissance and attack and penetration tools
Typical Libnet Usage
Libnet Supported Protocols
Component Layer Details: Libnids • Library that simulates a NIDS E-box • An E-box’s job is to sample the environment in which it is specialized for, and convert occurrences in the environment into standard data objects for subsequent storage and/or analysis. • Built on top of libpcap and libnet • Offers the following: • IP defragmentation • TCP stream reassembly • Time-based TCP port scan detection • Often found in defensive tools
Component Layer Details: Libsf • Library for IP stack fingerprinting to perform remote OS detection • Built on top of libpcap and libnet • active and passive fingerprinting methods • Based off of the nmap database and P 0 f databases • Often found in reconnaissance tools
Typical Libsf Usage
Libsf Active Fingerprinting Tests • Seven active tests can be performed using fringe packets: • TCP SYN to an open port • TCP NULL packet to an open port • TCP FIN|SYN|PSH|URG packet to an open port • TCP ACK packet to an open port • TCP SYN packet to a closed port • TCP ACK packet to a closed port • TCP FIN|PSH|URG to a closed port
Libsf Passive Fingerprinting Tests • Eight passive tests can be preformed across incoming TCP SYN packets: • Determine original IP TTL • IP packet size • IP DF bit on or off • TCP window scale option present • TCP MSS option present • TCP SACK option present • TCP NOP option present • TCP window size
Component Layer Details: Libdnet • Library for miscellaneous low-level network routines • Robust network address manipulation • Kernel ARP cache lookup and manipulation • Kernel route table lookup and manipulation • Network interface lookup and manipulation • Network firewall rule manipulation • Ethernet frame and IP packet transmission • Binary buffer manipulation • Random number manipulation • Often found in all tools
Component Layer Details: Open. SSL • Library for SSL / TLS and general cryptography • SSL/TLS protocols • Symmetric cryptographic operations (ciphers, message digests) • Asymmetric cryptographic operations (digital signatures, enveloping) • Public Key Infrastructure (PKI), including OCSP, rich X 509 certificate support, certificate verification, certificate requests, and CRLs • Often found in defensive tools
Technique Layer Details Packet Sniffing Port Scanning IP Expiry Firewalking
Technique Layer Details: Packet Sniffing • Passive Reconnaissance Technique • Used to capture packets on a network • Very powerful and useful in its own right • However it is also a fundamental building block in more complex tools • Ethernet • 1972, Bob Metcalfe, ALOHA became Ethernet • Shared medium (CSMA/CD) • Promiscuous mode instructs card to listen to every frame • Only works with stations in the same collision domain • Bridges, switches, routers, VLANS break sniffing
Technique Layer Details: Packet Sniffing • Packet Demultiplexing • Breaking apart an Ethernet frame and passing it the protocol chain • Protocol Decoding • Dissection of the packet at a given OSI layer
Technique Layer Details: Packet Sniffing Processing
Sample Packet Sniffing Code Snippet packet = (u_char *)pcap_next(vp->p, &vp->h); /* * Figure out which layer 2 protocol the frame belongs to and call * the corresponding decoding module. The protocol field of an * Ethernet II header is the 13 th + 14 th byte. This is an endian * independent way of extracting a big endian short from memory. We * extract the first byte and make it the big byte and then extract * the next byte and make it the small byte. */ switch (vp->packet[12] << 0 x 08 | vp->packet[13]) { case 0 x 0800: /* IPv 4 */ decode_ip(&vp->packet[14], vp->flags); break; case 0 x 0806: /* ARP */ decode_arp(&vp->packet[14], vp->flags); break; default: /* We're not bothering with 802. 3 or anything else */ decode_unknown(&vp->packet[14], vp->flags); break; }
Technique Layer Details: Port Scanning • Active Reconnaissance Technique • Used to determine TCP and UDP port status • Open, Closed, and optionally what application is listening • Many Considerations • Protocol • Detection and Filtering • Time and Bandwidth
Technique Layer Details: Port Scanning Mechanics • Full-open • Ident • FTP bounce • Half-open • Side effect RST • Parallel • UDP • Stealth • FIN • XMAS (URG|ACK|PSH) • NULL • Fragmented IP
Technique Layer Details: Port Scanning
Sample Port Scanning Code Snippet int fd, n, c; struct sockaddr_in addr; u_short port_list[] = {22, 23, 25, 80, 6000, 0}; addr. sin_family = AF_INET; addr. sin_addr. s_addr = 0 x 200 a 8 c 0; /* 192. 168. 0. 2 in network byte order */ for (n = 0; port_list[n] != 0; n++) { addr. sin_port = htons(port_list[n]); fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { /* error */ } c = connect(fd, (struct sockaddr *)&addr, sizeof (addr)); if (c == -1) { /* error */ } else if (c == 0) { printf("port %d openn", port_list[n]); } else { printf("port %d closedn", port_list[n]); } close(fd); }
Technique Layer Details: IP Expiry • Active Reconnaissance Technique • Used to map network devices en route to a target host • Van Jacobson, 1988, Traceroute • Originally used to trace IP packets to a particular destination host • Was extended into Firewalking
Technique Layer Details: IP Expiry Transports • Protocol specific terminal packet semantics • UDP • Open port: undefined (no response) • Closed port: ICMP port unreachable • ICMP echo reply • TCP SYN • Open port: SYN|ACK • Closed port: RST
Technique Layer Details: IP Expiry
c = libnet_write(l); if (c == -1) { /* error */ } fprintf(stderr, "Hop %02 d: ", ttl); pcap_t *p; for (done = icmp = ip = 0, ttl = 1; ttl </* 31 read && !done; ttl++) loop */ libnet_t *l; { for (start = time(NULL); (time(NULL) - start) < 2; ) time_t start; icmp = libnet_build_icmpv 4_echo( { u_char *packet; ICMP_ECHO, /* type */ packet = (u_char *)pcap_next(p, &ph); int c, ttl, done; 0, code */ if /* (packet == NULL) char *device = "fxp 0"; 0, { /* checksum */ struct pcap_pkthdr ph; 242, /* id */ continue; libnet_ptag_t icmp, ip; ttl, } /* sequence */ u_long src_ip = 0 x 1400000 a; /* 10. 0. 0. 20 in network byte order */ NULL, payload */ /* /* assume ethernet here for simplicity */ u_long dst_ip = 0 x 1403000 a; /* 10. 0. 3. 20 in network byte order */ 0, /*=payloadsiz*/ ip_h (struct libnet_ipv 4_hdr *)(packet + 14); struct libnet_icmpv 4_hdr *icmp_h; l, context */ if /* (ip_h->ip_p == IPPROTO_ICMP) struct libnet_ipv 4_hdr *ip_h, *oip_h; icmp); { /* libnet id */ char errbuf[LIBNET_ERRBUF_SIZE]; if (icmp == -1) icmp_h = (struct libnet_icmpv 4_hdr *)(packet + 34); { /* expired in transit */ l = libnet_init(LIBNET_RAW 4, NULL, errbuf); /* error */ if (icmp_h->icmp_type == ICMP_TIMXCEED && if (l == NULL) } icmp_h->icmp_code == ICMP_TIMXCEED_INTRANS) { ip = libnet_build_ipv 4( { /* error */ LIBNET_IPV 4_H + LIBNET_ICMPV 4_ECHO_H, /* length oip_h*/ = (struct libnet_ipv 4_hdr *)(packet + 42); } 0, /* TOS if*/ (oip_h->ip_id == htons(242)) p = pcap_open_live(device, 60, 0, 500, errbuf); 242, /* IP{ID */ if (p == NULL) 0, /* IP Frag */ fprintf(stderr, "%sn", { ttl, /* TTL */ libnet_addr 2 name 4(ip_h->ip_src. s_addr, 0)); /* error */ IPPROTO_ICMP, /* protocol */ break; } 0, /* checksum */ } src_ip, /* } src ip */ dst_ip, /* ip */ response */ /*dst terminal NULL, /* */ ifpayload (icmp_h->icmp_type == ICMP_ECHOREPLY) 0, /* { payloadsiz*/ l, /* context */ if (icmp_h->icmp_id == 242 && icmp_h->icmp_seq == ttl) ip); /* libnet id */ { if (ip == -1) fprintf(stderr, "%sn", { libnet_addr 2 name 4(ip_h->ip_src. s_addr, 0)); /* error */ done = 1; } break; } } Sample IP Expiry Code Snippet
Technique Layer Details: Firewalking • Active Reconnaissance Technique • Based off of IP expiry • Used to determine ACL filtering rules on a packet forwarding device • Schiffman, Goldsmith, 1998
Technique Layer Details: Firewalking • Send out a TCP or UDP packet with an IP TTL one greater of the target gateway • Packet passed by gateway ACL: ICMP TTL expired in transit • Packet denied by gateway: No response • Requires two hosts, target and metric • Target is the target gateway to be scanned • Metric is a host or gateway downstream from the target • Doesn’t have to be reachable
Technique Layer Details: Firewalking
Technique Layer Details: Firewalking (Phase One: Hopcount Ramping)
Technique Layer Details: Firewalking (Phase Two: Scanning, Packet is not Filtered)
Technique Layer Details: Firewalking (Phase Two: Scanning, Packet is Filtered)
Firewalk Packet Loss • Packets can be dropped for a variety of reasons • IP is an unreliable network • However, what if there is a prohibitive filter on a gateway prior to the target? • We would get false negatives reporting our packet is being filtered on the target when in fact it is being filtered by another host…
Technique Layer Details: Firewalking (Phase Two: Early Filtering of Packets)
Firewalk Early Packet Filtering Solution • We have two solutions: • Performing a “creeping walk” on each intermediate hop en route to the target. This will determine which gateway has the prohibitive filter • Physically relocate the scanning host to another part of the network so it no longer has to pass through the prohibitive filter in question • This may not always be an option
Firewalk Adjacent Target and Metric • Target and metric and topologically adjacent • Metric is exactly one hop downstream from the target • If packet violates ACL, nothing happens out of the ordinary • Scan times out and ACL is noted • If packet is passed by the target, it is processed as per RFC 1122 • Results vary, but packet is generally processed as per the protocol specific terminal packet semantics as with IP expiry • Using this, additional scanning can be performed
Technique Layer Details: Firewalking (Phase Two: Scanning, Adjacent Target and Metric)
Modeling Existing Tools
Traceroute Modeled
The Firewalk Tool Modeled
Inside a Network Security Tool: Firewalk Internals
Firewalk Overall Flow fw_shutdown(&fp); usage(argv[0]); #if (HAVE_CONFIG_H) /* we shouldbreak; probably record proper exit status */ break; #include ". . /include/config. h" return (EXIT_SUCCESS); case 'i': default: #endif } /* interface */ usage(argv[0]); #include ". . /include/firewalk. h" fp->device = optarg; }". . /version. h" #include void} break; int usage(u_char case *argv 0) 'n': c = argc optind; int firewalk(struct firepack { /* do not**fp) use names */ if (c != 2) main(int { argc, char *argv[]) fprintf(stderr, fp->flags "Usage &= : %s ~FW_RESOLVE; [options] target_gateway metricn" { { int done, i, [-d j; %d - %d] destination port to use (ramping phase)n" "tt break; /* int c; u_short bport, cport, eport; "tt case [-h] 'p': program helpn" * firepack We should only have two arguments at this point, the target struct *fp; "tt [-i /* select device] firewalk interfacen" protocol */ * gateway and the metric. char /* inform *port_list the user = do NULL; what's */ "tt fp->protocol [-n] not resolve = what fw_prot_select(optarg); IP addresses into hostnamesn" */ printf("%s-based char"tt errbuf[FW_ERRBUF_SIZE]; scan. n", [-p break; TCP | UDP] firewalk protocoln" usage(argv[0]); (*fp)->protocol ? "TCP" : "UDP"); "tt case[-r] 'r': strict == RFCIPPROTO_TCP adherencen" } printf("Firewalk printf("Ramping phase 5. 0 [gateway source port: ACL scanner]n"); %d, destination port: %dn", "tt [-S /*the Strict x y, RFC z] port adherence range */ to /* initialize network components */ scann" (*fp)->sport, (*fp)->dport); "tt fp->flags [-s %d %d] |= FW_STRICT_RFC; source portn" if argv[optind], &&argv[optind + 1], == port_list) == /* (fw_init_net(&fp, if ((*fp)->flags (*fp)->protocol IPPROTO_TCP) [-T break; 1&-FW_STRICT_RFC 1000] packet read timeout in msn" 1) {* "tt Initialize the main control context. We keep all of our "tt case[-t 'S': 1 - %d] IP time to liven" {* printf("Using program state strict here and RFC this adherence. n"); is by just about every "tt [-v] /* scan program these versionn" ports */ used %sn", fprintf(stderr, "fw_init_network(): fp->errbuf); }* function in the program. "ttdone; port_list [-x 1 - %d] = optarg; expire vectorn" printf("Hotfoot */ goto through %s using %s as a metric. n", "n", break; FW_PORT_MIN, FW_PORT_MAX, FW_PORT_MIN, argv 0, } if (fw_init_context(&fp, libnet_addr 2 name 4(((* errbuf) fp)->gateway), == -1) FW_PORT_MAX, case 's': state initialization printf("Firewalk completed successfully. n"); { ((*fp)->flags) & FW_RESOLVE), /* source FW_IP_HOP_MAX, port */ FW_XV_MAX); /* execute scan: phase one, and hopefully phaseerrbuf); two */ fprintf(stderr, libnet_addr 2 name 4(((* "fw_init_control(): fp)->metric), %sn", exit(EXIT_SUCCESS); fp->sport = fw_str 2 int(optarg, "source port", switch (firewalk(&fp)) goto ((*fp)->flags) done; & FW_RESOLVE)); } FW_PORT_MIN, FW_PORT_MAX); { } /* break; case -1: * */ PHASE ONE: Firewalk hopcount ramping /* EOF case 'T': case FW_SERIOUS_ERROR: /* * process A standard commandline IP */expiryfrom scan is initiated towards /* Traceroute-style time error to arguments wait packets end */ /* grievous offor some sortto */findother while * the ((c metric, = getopt(argc, with the argv, intent "d: fhi: no: p: r. S: s: T: t: vx: ")) being how many"read hops!=timer", away EOF)the fp->pcap_timeout = fw_str 2 int(optarg, fprintf(stderr, "firewalk(): %sn", fp->errbuf); {* target gateway is from the scanning host. We'll increment FW_PCAP_TIMEOUT_MIN, FW_PCAP_TIMEOUT_MAX); the break; * hopcounter switch (c) and update packet template each pass through theloop. break; FW_ABORT_SCAN: */ case { case 't': /* hop count exceeded or metric en route */ printf("Ramping case 'd': Phase: n"); /* set initial IP aborted: TTL */ fprintf(stderr, "Scan fp->errbuf); for (done = fp->ttl /* i 0, destination = 0; !done port && ito < FW_IP_HOP_MAX; use %s. n", during ramping i++)phase */ = fw_str 2 int(optarg, "initial TTL", break; { fp->dport. FW_IP_HOP_MIN, = fw_str 2 int(optarg, "ramping FW_IP_HOP_MAX); destination FW_USER_INTERRUPT: port", case /* send a series of probes (currently one) */ break; "Scan aborted by user. n"); for fprintf(stderr, (j = 'v': 0; j < 1; FW_PORT_MIN, j++) FW_PORT_MAX); case break; { break; /* version */ default: fprintf(stderr, caseprintf(FW_BANNER 'f': "%2 d "version (TTL %2 d): ", i + VERSION); 1, (*fp)->ttl); : %sn", printf("n. Scan completed successfully. n"); if (fw_packet_inject(fp) /* stack fingerprint == of -1) each host */ goto done; break; { |= FW_FINGERPRINT; casefp->flags 'x': } break; /* /* expire vector */ done: casefp->xv 'h': * Perhaps this write error"expire was transient. = fw_str 2 int(optarg, vector", We'll hope fw_report_stats(&fp); /* * program for the help best. */ Inform the user and continue. FW_XV_MIN, FW_XV_MAX);
Firewalk Initialization int /* setup /* the metric */ /*/* get the datalink size */ fw_init_net(struct if * (((*fp)->metric Set pcap filter firepack = libnet_name 2 addr 4((*fp)->l, and **fp, determine char *gw, outgoing char packet *m, m, char 1)) size. *port_list) == The -1) filter *switch Build(pcap_datalink((*fp)->p)) a probe packet template. We'll use this packet template { { * will be determined by the scanning protocol: int *{ over and over for each write to the network, modifying certain #if HAVE_BPF *snprintf((*fp)->errbuf, UDP scan: FW_ERRBUF_SIZE, * fields case (IP DLT_SLIP: TTL, firepack UDP/TCP ports course checksums as we go). fw_init_context(struct **fp, and charof *errbuf) int*one; icmp[0] "libnet_name 2 addr 4(): == 11 or icmp[0] == 3 %sor (metric: udp %s)", */ (*fp)->packet_offset = 0 x 10; { #endif * TCP scan: libnet_geterror((*fp)->l), m); if break; == -1) *fp(fw_packet_build_probe(fp) = (struct firepack *)malloc(sizeof(struct firepack)); char *return errbuf[PCAP_ERRBUF_SIZE]; icmp[0] (-1); == 11 or icmp[0] == 3 or tcp[14] == 0 x 12 or tcp[14] { case if (*fp == DLT_RAW: NULL) } * == 0 x 4 or tcp[14] == 0 x 14 /* error (*fp)->packet_offset msg set in fw_packet_build_probe() = 0 x 00; */ { /* */ get a libnet context */ return break; (-1); snprintf(errbuf, FW_ERRBUF_SIZE, "malloc(): %s", strerror(errno)); (*fp)->l /* switch sanity((*fp)->protocol) =check libnet_init(LIBNET_LINK, */ (*fp)->device, errbuf); } case DLT_PPP: return (-1); if{((*fp)->gateway ((*fp)->l == NULL) == (*fp)->metric) return (1); (*fp)->packet_offset = 0 x 04; } { case IPPROTO_UDP: break; memset(*fp, 0, sizeof(struct firepack)); snprintf((*fp)->errbuf, if (fw_set_pcap_filter(FW_BPF_FILTER_UDP, FW_ERRBUF_SIZE, "libnet_init(): fp) == -1) %s", case DLT_EN 10 MB: { "target errbuf); gateway and metric cannot be the same"); /* setdefault: defaults here */ return (-1); /* err msg set in fw_set_pcap_filter() */ = (*fp)->ttl(*fp)->packet_offset = 1; /*0 x 0 e; initial probe IP TTL */ } return (-1); break; (*fp)->sport = 53; /* source port (TCP and UDP) */ } } (*fp)->dport = 33434; /* ala traceroute */ /* get our/* device port IP + list if stuff UDP the */ user situated didn't*/ specify one*/ (*fp)->protocol = IPPROTO_UDP; if (libnet_plist_chain_new((*fp)->l, ((*fp)->device (*fp)->packet_size == NULL) = LIBNET_IPV 4_H &(*fp)->plist, + LIBNET_UDP_H; (*fp)->id = getpid(); { port_list break; == NULL ? strdup(FW_DEFAULT_PORT_LIST) : (*fp)->pcap_timeout = FW_REPLY_TIMEOUT; (*fp)->device port_list) case IPPROTO_TCP: == -1) = libnet_getdevice((*fp)->l); (*fp)->xv = 1; } { if (fw_set_pcap_filter(FW_BPF_FILTER_TCP, fp) == -1) (*fp)->flags |= FW_RESOLVE; snprintf((*fp)->errbuf, { FW_ERRBUF_SIZE, /* get the "libnet_plist_chain_new(): source /* err address msg set of in ourfw_set_pcap_filter() outgoing %sn", libnet_geterror((*fp)->l)); interface */ */ /* setup our signal handler to handle a ctrl-c */ (*fp)->sin. sin_addr. s_addr return (-1); = libnet_get_ipaddr 4((*fp)->l); if (catch_sig(SIGINT, catch_sigint) == -1) } } { /* get setup a pcap the /* IP target context + TCP gateway */ */ snprintf(errbuf, FW_ERRBUF_SIZE, "catch_sig(): %s", if (((*fp)->gateway (*fp)->p =(*fp)->packet_size pcap_open_live((*fp)->device, = libnet_name 2 addr 4((*fp)->l, = LIBNET_IPV 4_H FW_SNAPLEN, + LIBNET_TCP_H; gw, 0, 1)) 0, == errbuf); -1) strerror(errno)); { (((*fp)->p) == NULL) if return (-1); { snprintf((*fp)->errbuf, /* randomize the TCP FW_ERRBUF_SIZE, sequence number */ } snprintf((*fp)->errbuf, libnet_seed_prand((*fp)->l); "libnet_name 2 addr 4(): FW_ERRBUF_SIZE, %s (target"pcap_open_live(): gateway: %s)", %s", (*fp)->seq libnet_geterror((*fp)->l), errbuf); = libnet_get_prand(LIBNET_PRu 32); gw); return (1); returnbreak; (-1); } } default: sprintf((*fp)->errbuf, "fw_init_network(): unsupported protocol"); return (-1); }
Firewalk Packet Construction int a = arp_open(); fw_packet_build_probe(struct fw_packet_build_tcp(struct firepack **fp) if (a == NULL) { /* /*{build our IPv 4 header */ arp_t /* *build Now *a; we a TCP need header to get */the MAC address of our first hop gateway. (*fp)->ip snprintf((*fp)->errbuf, = libnet_build_ipv 4( FW_ERRBUF_SIZE, "arp_open()"); route_t (*fp)->tcp * Dnet *r; to = the libnet_build_tcp( rescue! We start by doing a route table lookup return (*fp)->packet_size, (-1); /* packetlength */ * toarp_entry determine the IP address we use to get the TCP port */ struct (*fp)->sport, arp; /* to source 0, /* IP tos */ } * destination host (the metric). struct route_entry (*fp)->dport, route; /* dest TCP port */ (*fp)->id, /* IP id */ /* get the MAC of the first hop gateway */ */ (*fp)->seq, /* sequence number */ arp_pa 0, = route_gw; /* IP frag bits */ /* r = first route_open(); 0 L, build our transport layer header *//* ACK number */ if (arp_get(a, (*fp)->ttl, &arp) < 0) /* IP time to live */ switch if (r == ((*fp)->protocol) TH_SYN, NULL) /* control flags */ { (*fp)->protocol, /* transport protocol */ {{ 1024, /* window size */ snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, "route_get()"); 0, /* checksum */ case 0, IPPROTO_UDP: checksum */ snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, /* "route_open()"); arp_close(a); (*fp)->sin. sin_addr. s_addr, /* IP source */ route_close(r); if (fw_packet_build_udp(fp) == -1) /* urgent */ 0, return (*fp)->metric, (-1); /* IP destination */ return { (*fp)->packet_size (-1); - LIBNET_IPV 4_H, /* TCP size */ } NULL, /* IP payload */ } NULL, /* error msg set in fw_packet_build_udp() /* IP payload */ */ arp_close(a); 0, /* IP payload size */ 0, return (-1); /* IP payload size */ (*fp)->l, /* libnet context */ /* convert } (*fp)->l, the metric address to dnet's native /* libnet addr_tcontext format */ /* build our 0); ethernet header */ /* No saved ptag */ if (addr_aton(libnet_addr 2 name 4((*fp)->metric, break; 0); /* No 0), saved ptag */ if (libnet_autobuild_ethernet( case &route_dst) IPPROTO_TCP: < 0) if ((*fp)->ip (u_char== *)&arp. arp_ha. addr_eth, -1) if { ((*fp)->tcp if (fw_packet_build_tcp(fp) == -1) { ETHERTYPE_IP, { snprintf((*fp)->errbuf, { FW_ERRBUF_SIZE, "addr_aton()"); snprintf((*fp)->errbuf, (*fp)->l) == -1) FW_ERRBUF_SIZE, "libnet_build_ipv 4() %s", snprintf((*fp)->errbuf, route_close(r); /* error msg set. FW_ERRBUF_SIZE, in fw_packet_build_tcp() "libnet_build_tcp() */ %s", { libnet_geterror((*fp)->l)); return (-1); libnet_geterror((*fp)->l)); snprintf((*fp)->errbuf, return (-1); FW_ERRBUF_SIZE, } return } (-1); } "libnet_autobuild_ethernet() %s", }/* get the break; route entry telling us how to reach the metric */ libnet_geterror((*fp)->l)); return if (route_get(r, default: (1); &route) < 0) arp_close(a); } { sprintf((*fp)->errbuf, return (-1); snprintf((*fp)->errbuf, "fw_packet_build_probe(): FW_ERRBUF_SIZE, unknown "route_get()"); protocol"); } route_close(r); return (-1); } return (-1); return (1); } } route_close(r);
Firewalk Ramping Phase /* if (!done) switch (fw_packet_capture(fp)) * PHASE { ONE: { Firewalk hopcount ramping * A standard if (fw_packet_update_probe(fp, Traceroute-style case FW_PACKET_IS_UNREACH_EN_ROUTE: IP expiry scan 0) == is-1) initiated towards * the metric, { with FW_PACKET_IS_TTL_EX_EN_ROUTE: case the intent being to find how many hops away the * target gateway /* error is iffrom ((*fp)->flags msg the set scanning in fw_packet_update_probe & FW_BOUND) host. We'll increment */ the * hopcounter and return update { (-1); packet template each pass through the loop. */ } printf("Binding host reached. n"); printf("Ramping } Phase: n"); done = 1; for (done } = 0, i = 0; } !done && i < FW_IP_HOP_MAX; i++) { if (done && !((*fp)->flags break; & FW_BOUND)) /* { send a series case FW_PACKET_IS_TERMINAL_TTL_EX: of probes (currently one) */ for (j /* = 0; case j < 1; FW_PACKET_IS_TERMINAL_UNREACH: j++) { * If we're case "done" FW_PACKET_IS_TERMINAL_SYNACK: but not "bound" then we hit the metric fprintf(stderr, * before case we. FW_PACKET_IS_TERMINAL_RST: hit "%2 d the(TTL target %2 d): gateway. ", i + This 1, (*fp)->ttl); means the target if * (fw_packet_inject(fp) gateway is /* not any en terminal route == to -1)the metric. response will end Game's phaseover one kids. */ {*/ done = 1; sprintf((*fp)->errbuf, /* break; * "metric Perhaps case -1: responded this writebefore error target; was transient. must not. We'll be enhope route"); return * (FW_ABORT_SCAN); for the case FW_SERIOUS_ERROR: best. Inform the user and continue. } */ /* err msg set in fw_packet_capture() */ if (!done) fprintf(stderr, return (FW_SERIOUS_ERROR); "fw_packet_inject(): %sn", { case(*fp)->errbuf); FW_USER_INTERRUPT: /* if continue; we fall /*through user hit down ctrl-c here, */we've exceeded our hopcount */ } sprintf((*fp)->errbuf, return (FW_USER_INTERRUPT); "hopcount exceeded"); return } (FW_ABORT_SCAN); } }
Firewalk Scanning Phase /* send a series of probes (currently one) */ /* for (j = 0; j < 1; j++) * PHASE TWO: { Firewalk scanning * A series of fprintf(stderr, probes are sent "port from to %3 d: the", metric cport); with the bound IP * TTL. If a given (*fp)->stats. ports_total++; probe is accepted through the target gateway's * ACL, we willif receive an ICMP TTL expired in transit from the (fw_packet_inject(fp) == -1) * binding host{If we receive no response after the timeout expires, * it is assumed the /*probe violated the ACL on the target and was * dropped. * Perhaps this write error was transient. We'll */ * hope for the best. Inform the user and continue. */ (*fp)->ttl += (*fp)->xv; printf("Scan bound at fprintf(stderr, %d hops. n", (*fp)->ttl); "fw_packet_inject(): %sn", printf("Scanning Phase: n"); (*fp)->errbuf); for (done = 0, i = 0; continue; !done; i++) { } if (!libnet_plist_chain_next_pair((*fp)->plist, /* we don't care what the return value &bport, is this &eport)) time */ { switch(fw_packet_capture(fp)) /* we've{exhausted our portlist and we're done */ done = 1; case FW_USER_INTERRUPT: continue; return (FW_USER_INTERRUPT); } case -1: while (!(bport >case eport) FW_SERIOUS_ERROR: && bport != 0) { /* err msg set in fw_packet_capture() */ cport = bport++; return (FW_SERIOUS_ERROR); if (fw_packet_update_probe(fp, default: cport) == -1) { /* empty */ /* error } msg set in fw_packet_update_probe */ return (-1); } } } return (1); }
Firewalk Capture switchfor (!(((*fp)->flags) (timed_out = 0; &!timed_out FW_BOUND) && ? fw_packet_verify_ramp(fp) loop; ) : casefw_packet_verify_scan(fp)) FW_PORT_IS_OPEN_RST: { /* SCANNING: A+response from a 0, closed TCP port */ { c = select(pcap_fd 1, &read_set, 0, &timeout); fp); switch casefw_report(FW_PORT_IS_OPEN_RST, FW_PACKET_IS_TTL_EX_EN_ROUTE: (c) (*fp)->stats. packets_caught_interesting++; { /* RAMPING: TTL expired en route to gateway (standard) */ return case fw_report(FW_PACKET_IS_TTL_EX_EN_ROUTE, -1: (FW_PORT_IS_OPEN_RST); fp); case(*fp)->stats. packets_caught_interesting++; FW_PORT_IS_OPEN_UNREACH: snprintf((*fp)->errbuf, FW_ERRBUF_SIZE, /* SCANNING: A port unreachable response */ return (FW_PACKET_IS_TTL_EX_EN_ROUTE); "select() %s", strerror(errno)); fp); casefw_report(FW_PORT_IS_OPEN_UNREACH, FW_PACKET_IS_UNREACH_EN_ROUTE: return (-1); (*fp)->stats. packets_caught_interesting++; case /* RAMPING: 0: Unreachable en route to gateway (uncommon) */ return (FW_PORT_IS_OPEN_UNREACH); fw_report(FW_PACKET_IS_UNREACH_EN_ROUTE, timed_out = 1; fp); case(*fp)->stats. packets_caught_interesting++; FW_PORT_IS_OPEN_TTL_EX: continue; /* SCANNING: A TTL expired */ default: return (FW_PACKET_IS_TTL_EX_EN_ROUTE); fp); casefw_report(FW_PORT_IS_OPEN_TTL_EX, FW_PACKET_IS_TERMINAL_TTL_EX: if (FD_ISSET(pcap_fd, &read_set) == 0) (*fp)->stats. packets_caught_interesting++; /* { RAMPING: TTL expired at destination (rare) */ return (FW_PORT_IS_OPEN_TTL_EX); fw_report(FW_PACKET_IS_TERMINAL_TTL_EX, timed_out = 1; fp); case(*fp)->stats. packets_caught_interesting++; FW_PACKET_IS_BORING: continue; default: return } (FW_PACKET_IS_TERMINAL_TTL_EX); casecontinue; FW_PACKET_IS_TERMINAL_UNREACH: /* fall through to read the packet */ } } /* RAMPING: Unreachable at destination (uncommon) */ } (*fp)->packet fw_report(FW_PACKET_IS_TERMINAL_UNREACH, = (u_char *)pcap_next((*fp)->p, &pc_hdr); fp); if ((*fp)->packet (*fp)->stats. packets_caught_interesting++; == NULL) { return (FW_PACKET_IS_TERMINAL_UNREACH); case /*FW_PACKET_IS_TERMINAL_SYNACK: no NULL packets please */ continue; fw_report(FW_PACKET_IS_TERMINAL_SYNACK, fp); } (*fp)->stats. packets_caught_interesting++; (*fp)->stats. packets_caught++; return (FW_PACKET_IS_TERMINAL_SYNACK); case FW_PACKET_IS_TERMINAL_RST: fw_report(FW_PACKET_IS_TERMINAL_RST, fp); (*fp)->stats. packets_caught_interesting++; return (FW_PACKET_IS_TERMINAL_RST); case FW_PORT_IS_OPEN_SYNACK: /* SCANNING: A response from an open TCP port */ fw_report(FW_PORT_IS_OPEN_SYNACK, fp); (*fp)->stats. packets_caught_interesting++; return (FW_PORT_IS_OPEN_SYNACK);
Firewalk Packet Verification (ramping phase)
Firewalk Packet Verification (Scanning Phase)
Conclusion • Modular Model of Network Security Tools • Components and Techniques • This was not an exhaustive list of Components or Techniques… • Examples of how to code Techniques using Components
Questions and Comments? mike@infonexus. com http: //www. packetfactory. net
- Slides: 76