valerybrozhinsky - stock.adobe.c
Was ist Shellcode und wie wird er für Angriffe eingesetzt?
Viele Anwendungen in Unternehmen sind nicht ausreichend gegen Shellcode-Angriffe gesichert. Erfahren Sie hier, was Shellcode so besonders macht und wie Sie sich schützen können.
In jüngerer Vergangenheit Zeit wird immer wieder der Begriff Shellcode genannt. Er wird für eine gefährliche Angriffsmethode verwendet, bei der Schwachstellen in Software ausgenutzt werden, um die Kontrolle über eine kompromittierte Maschine zu übernehmen.
Das Wort Shellcode ist schnell erklärt: Es steht für Code, mit dem eine neue Shell gestartet werden kann. Eine Shell ist eine Kommandozeile, um darin Befehle auszuführen. Unter Linux gibt es zum Beispiel die Shell /bin/sh und unter Windows cmd.exe.
Heutzutage wird der Begriff aber auch für jeglichen Code verwendet, der ausgeführt werden kann, nachdem er in eine bereits laufende Anwendung eingespeist wurde – selbst wenn dabei keine dedizierte Shell mehr geöffnet wird.
Ein Shellcode wird meist über entweder eine Stack- oder eine Heap-basierte Buffer-Overflow-Schwachstelle (die am häufigsten für diese Art von Angriffen genutzten Sicherheitslücken in Programmcode überhaupt) oder durch spezielle String-Formatierungen eingeschleust.
Das funktioniert so: Zunächst sorgt ein Exploit für einen kritischen Fehler in der attackierten Anwendung. Danach führt die Software den Shellcode und anschließend die vom Angreifer gewollten Befehle aus. Auf diese Weise kann der Shellcode auch die Nutzungs- und Zugriffsrechte des missbrauchten Prozesses übernehmen.
Häufig dient dieses Vorgehens dazu, zum Beispiel ein Rootkit oder einen Trojaner heimlich zu installieren, auf dem angegriffenen System vorhandene Sicherheitsprogramme zu beenden oder um weitere Schadsoftware herunterzuladen und zu installieren.
Shellcode-Exploits im Detail
Jeder, der sich mit der Entwicklung von Shellcode beschäftigt, benötigt umfassendes Wissen in Maschinencode sowie den Programmiersprachen C und C++, in der Architektur moderner Prozessoren und dem Aufbau des attackierten Betriebssystems.
So ist ein Shellcode für Windows in der Regel komplett anders aufgebaut als ein Shellcode für Linux. Das Microsoft-Betriebssystem hat zum Beispiel kein direktes Kernel-Interface, wie es unter Linux zu finden ist. Außerdem ändern sich die Adressen der in Windows-DLLs (Dynamic Link Libraries) zu findenden Funktionen nahezu mit jeder neuen Windows-Version, während Linux über ein fixes Nummerierungssystem für alle Aktionen auf Basis des Kernels verfügt.
Der Hauptgrund für eine potentielle Ausführung von Shellcode liegt jedoch darin, dass viele Anwendungen oder Libraries die Daten nicht ausreichend validieren, mit denen sie arbeiten. Die Betriebssysteme weisen dedizierte und zudem begrenzte Speichermengen aus, in denen Daten wie Variablen, Werte und Arrays abgelegt werden können.
Diese Speicherbereiche, auch Buffer oder Puffer genannt, werden meist beim Start einer Anwendung oder auch erst dann dynamisch angelegt, wenn sie bereits läuft. Wenn neue Daten diesen Puffer überschreiten, dann verbreiten sie sich in andere Speicherbereiche des betroffenen Systems. Dabei werden die dort vorher vorhandenen Daten entweder teilweise oder sogar komplett überschrieben. Es kommt zu einem sogenannten Puffer-Überlauf oder Buffer Overflow.
Softwareentwickler müssen sich deswegen gründlicher denn je damit beschäftigen, wie viele Daten in bestimmte Bereiche des Programmcodes geschrieben werden können. In höheren Programmiersprachen wie Java oder C# sind solche Programmierfehler nicht mehr so leicht zu machen.
Da aber ein großer Teil der in Unternehmen genutzten Anwendungen in anfälligen Programmiersprachen wie C und C++ geschrieben wurde und immer noch wird, werden uns diese Exploits noch für einen längeren Zeitraum begleiten. Zahlen aus der Common Vulnerabilities and Exposures Database (CVE) der US-Organisation NIST (National Institute of Standards and Technology) zeigen, dass sich die durch Buffer Overflows verursachten Schwachstellen in den Jahren 2017 und 2018 massiv erhöht haben.
Die Situation wird weiter verschlimmert, weil viele Angreifer mittlerweile sich selbst-verschlüsselnde, polymorphe und weitere zwar statische aber nicht mehr standardkonforme Kodierungen für ihre Malware verwenden. Herkömmliche auf vergleichsweise einfachen Signaturen aufsetzende IDS-Systeme (Intrusion Detection Systems) können damit erstellten Shellcode meist nicht aufspüren. Im Internet finden sich darüber hinaus mehrere Datenbanken wie die Exploit Database oder 0dayToday, die öffentlich verfügbare Shellcode-Exploits anbieten.
Shellcode-Arten
Wie bereits erwähnt, sind Stack- oder Heap-basierte Buffer Overflows die am häufigsten anzutreffenden Beispiele für Shellcode. Ein klassischer Angriff via Shellcode ist etwa der Missbrauch der JpegOfDeath-Schwachstelle in der Bibliothek gdiplus.dll.
Damit kann absichtlich eine Situation eingeleitet werden, die für einen Buffer Overflow sorgt. Jeder, der eine JPEG-Datei öffnet, die mit dem JpegOfDeath-Exploit manipuliert wurde, sorgt für einen Buffer Overflow auf seinem System. So kann dann Shellcode in den Speicher eingeschleust und anschließend ausgeführt werden.
Ein Exploit besteht normalerweise aus zwei Hauptkomponenten: Dem für den Missbrauch verwendeten eigentlichen Exploit-Code und der sogenannten Payload. Das ist der Teil, der es dem Angreifer ermöglicht seinen Schadcode auszuführen. Das Ziel des Exploits ist nicht nur den Shellcode einzuschleusen, sondern auch den Ausführungspfad des angegriffenen Programms auf den Shellcode umzulegen, so dass der Code in der Payload gestartet werden kann.
Mit diesem Trick kann seine Ausführung durch das Überschreiben einer Stack-Return-Adresse mit der Adresse des Shellcodes ausgelöst werden. Die missbrauchte Subroutine kehrt dann nicht mehr zu ihrem eigentlichen Verursachen, dem Caller, zurück, sondern ruft den Shellcode auf, der dann die neue Shell öffnet.
Auch wenn Stack- und Heap-basierte Buffer Overflows die häufigsten Shellcode-Exploits sind, können Angreifer auch auf andere immer wieder zu findende Schwachstellen wie Integer Overflows, Format Strings, Race Conditions und Memory Corruption zurückgreifen. Auch eine Payload kann so ausgelegt werden, dass sie zunächst in eine Schleife geleitet wird und dann auf weitere Befehle des Angreifers wartet.
Im Prinzip ist also fast alles möglich, was den Angriff erweitern kann. Shellcode kann außerdem lokal oder remote ausgeführt werden. Lokaler Shellcode wird zum Beispiel verwendet, wenn der Angreifer einen direkten physischen Zugriff auf einen Rechner hat, während ein remote Shellcode genutzt wird, um einen Prozess auf einem anderen Computer von einer entfernten Maschine aus über das Netzwerk anzugreifen.
So kann man sich gegen Shellcode schützen
Um sich gegen Exploits zu schützen, mit denen Shellcode in anfällige Programme eingeschleust wird, sollten Unternehmen eine mehrschichtige Strategie wählen. Die Angreifer verwenden nicht selten automatisierte Tools, um Anwendungen aufzuspüren, die anfälligen Code enthalten.
Die Firewalls in den Unternehmen und andere Kontrollmöglichkeiten müssen deswegen so eingerichtet werden, dass sie unerwünschte und schädliche Verbindungen durch diese Werkzeuge erkennen und stoppen können. Darüber hinaus werden Monitoring-Lösungen benötigt, die ungewöhnliches Verhalten im Netzwerk erkennen und in eine Quarantäne verschieben. Mit Hilfe von statischen und verhaltensbasierten künstlichen Intelligenzen (KI) können Angriffe zudem blockiert werden, bevor sie dauerhafte Schäden anrichten können.
Des Weiteren müssen alle in einem Unternehmen genutzten Anwendungen überprüft und gegebenenfalls gehärtet werden, um sie widerstandsfähiger gegen diese Art von Exploits zu machen. Dazu werden zusätzliche Sicherheitskontrollen wie Advanced Memory Protection und Data Execution Prevention benötigt. Intern entwickelte und genutzte Anwendungen sollten regelmäßigen statischen sowie dynamischen Tests unterzogen werden, bei denen auch versucht wird, Shellcode direkt in einen laufenden Prozess einzuschleusen. Dafür können Tools wie Metasploit und PowerSploit genutzt werden.
Zuletzt sollten auch Penetration-Tools eingesetzt werden, um herauszufinden, ob die getroffenen Sicherheitsmaßnahmen auch wirklich effektiv sind. Mit ihnen kann geprüft werden, ob Exploits gefunden und vor allem verhindert werden, mit denen Shellcode ausgeführt werden könnte.