11. August 2007
Fefes ersten Vortrag habe ich ja leider verpasst, aber zum zweiten Vortrag bin ich dann doch rein, obwohl ich anfangs ein wenig skeptisch war. Ein paar Sachen muss man Fefe jedoch neidlos zugestehen … was C angeht hat er richtig Ahnung. Die Kernaussage war dafür recht schlicht: „Lesbarer Code ist wichtiger als Optimierung“.
Don’t use Inline
- das macht der Compiler von alleine wo es sinnvoll ist
- in modernen Compilern ist da eine sehr gute Optimierung
Range checks
- kann man immer machen
- optimiert der Compiler gegebenenfalls automatisch weg wo sie unnötig sind
Strength Reduction
- der Compiler macht automatisch shifts draus
Sizeof
- optimiert der Compiler automatisch, auch bei mehrfachem Einsatz
- keine „magic numbers“ verwenden
Tail recursion
- kann man in eine nichtrekursive Funktion auflösen
- macht der gcc automatisch
- nicht icc und sun-cc
Aliasing
- der Compiler muss hier sehr vorsichtig optimieren
- (außer der gcc, der optimiert alles weg, aber dafür hat Fefe ja einen Bugreport geschrieben)
- hier ist manuelle Optimierung möglich (aber lohnt sich kaum)
Dead Code
- Compiler/Linker kann Code bzw. Objectfiles weglassen
- Beim kompilieren von Bibliotheken jede Funktion in ein eigenes Objectfile packen
Inline Assembler
- braucht man praktisch nie
- ist blöd zu debuggen
- besser nicht (lohnt sich auch kaum bei modernen Compilern)
Shifting
- schwer in C zu programmieren
- optimiert der Compiler automatisch
Pre- vs. Post-Operation
- auch hier kaum noch Optimierungsmöglichkeiten
Memory Hierarchien
- hier lässt sich am meisten tunen
- ein Cache Miss schlägt mit 250 CPU-Cycles Penalty zu buche
- das ist meist der teuerste Schaden und am wichtigsten zu optimieren
Aha … also gute Neuigkeiten für Spaghettiprogrammierer wie mich … einfach weitermachen, der Compiler optimiert das schon. 🙂
Gil Dabah, u.a. Autor des diStorm Disassembler hat in diesem Vortrag die Möglichkeiten des Binary Patchings am Beispiel von zwei Microsoft Lücken (VML, ANI) vorgestellt und dabei ein wenig Werbung für seinen Arbeitgeber ZERT (Zeroday Emergency Response Team) gemacht. Insgesamt war der Vortrag aber sehr ausgewogen, er hat nicht nur auf Vorteile des Binary Patchings hingewiesen sondern auch auf die möglichen Probleme und Gefahren und es den Teilnehmern überlassen, daraus ihren Schluss zu ziehen. Der Vortrag hat mir auch aus diesem Grund recht gut gefallen.
Patching wird von Gil definiert als Änderung von Daten oder Code, die das Verhalten eines Programms verändern. Das vielleicht bekannteste Beispiel von Binary Patching sind Game Cracks, nach deren Anwendung sich ein Spiel ohne zugehörige CD bzw. Registrierungscode spielen lässt.
Typische Probleme beim Patchen von Binaries sind:
- verschiedene Binary Versionen
- Code Änderungen / Verschiebungen des Programmcodes im Binary
- Kein Platz im Binary für Zusatzcode
- Konkurrierendes Hot Patching von Microsoft
- Windows File Protection, das Änderungen an Systembibliotheken verhindert
- Virenscanner Probleme (modifizierte Binaries)
Insgesamt ist daher das Ändern von Systemdateien gar nicht so einfach. Der Binärpatch kann auf verschiedene Art erzeugt werden:
PE-Patching
- Ein Portable Executable Binary ist ein komplettes ausführbares Programm unter Windows.
- Beim PE-Patching wird das komplette Programm angepasst, was auch Änderungen der PE-Struktur erfordert
- In kurzer Zeit nicht verläßlich durchzuführen, da meist größere Änderungen erforderlich sind
- Insgesamt sehr aufwendig
Per-Version Patching
- Jede einzelne Version eines Binaries wird passend gepatcht
- Benötigt alle vorhandenen Programmversionen
- Wenn einzelne Versionen unbekannt sind, kann der Patch nicht angewandt werden
Hot Patching Bytes
- Möglich, wenn der Patch nur an wenigen Stellen angewandt werden muss
- 7 Bytes sind oft nicht genug
Spot Patching
- Einfach, da lediglich Search & Replace verwendet wird
- Geht nicht, wenn z.B. die Patch-Signatur nicht statisch ist
Eine Lücke, für die ZERT einen Patch entwickelt hat ist die VML (Vector Markup Language) Lücke, ein Zeroday, der am 19.09.2006 von Adam Thomas von Sunbelt Software gefunden wurde. Die Lücke wurde zu diesem Zeitpunkt aktiv im Internet genutzt, um in Systeme einzubrechen. der VML-Bug ist ein einacher Stack-based Buffer Overflow in der Datei VGX.DLL, die von allen Internet Explorer 6 Versionen in Windows XP SP2 verwendet wird. DEP (Data Execution Prevention) würde vor dem Exploit schützen, wird jedoch standardmäßig beim IE nicht verwendet. Der Angriff benötigt lediglich fehlerhafte Attribute in der VML-Fill-Methode und ist daher einfach auszuführen. Ein typischer „surf and geht owned“-Exploit.
<v.rect><v.fill method=“AAAAAAA…“></v.fill></v.rect>
Das Patchen des VML-Binaries ging relativ einfach vonstatten, da VGX.DLL eine In-proc DLL ist die registriert und deregistriert werden kann. Der Ablauf erfolgt dann wie folgt:
- Einlesen der VGS.DLL
- Finden der Signatur
- Patchen des Binaries
- Speichern der gepatchten PATCHEDVGX.DLL
- Deregistrieren der VGX.DLL
- Registrieren der PATCHEDVGX.DLL
Beim ANI-Fehler musste zum Patchen eine andere Methode angewandt werden, da die USER32.DLL sich so nicht ändern lässt. Die verwendete Technik nennt sich in-memory patching:
- Mittels knownDLLs die Patch-DLL jedem Prozeß hinzuladen
- Im RAM die USER32.DLL finden und patchen
Allerdings wird diese Technik in 64 Bit Vista nicht mehr funktionieren, da nur signierte Bibliotheken geladen werden können.
Fazit und Risikomanagement:
- Don’t use 3rd-party patches!
- Do you trust patches from people that don’t own the source code?
- What about liability and vendor support?
- If not patched, you are already vulnerable!
- Do you want to stay unprotected?
- ZERT supplies source code of the patches
Am Ende bleibt es halt doch immer dem Sicherheitsbeauftragten und dem Administrator überlassen zu entscheiden, was sie tun wollen.
Lisa Thalheim hat im Vortrag Twisting Time ein paar Probleme konkurrierender Programme vorgestellt. Dabei ging es um typische Programmierfehler, die zu Concurrency Bugs führen. Ursache sind entweder Programme oder Threads von Programmen, die parallel (simultaneously) ablaufen können und entweder gemeinsam auf eine Ressource zugreifen oder miteinander kommunizieren müssen. Hier treten leicht schwer zu findende und unregelmäßig auftretende Fehler auf.
Der Vortrag selbst war eigentlich ein reiner Grundlagenvortrag, von meiner Einschätzung her das Niveau eines Proseminars an der Uni. Für Leute, die damit noch nie zu tun hatten sicher interessant, da alle Grundlagen erklärt wurden, für Programmierer die sich damit schon beschäftigt hatten eher langweilig, da außer ein paar anschaulichen Source Code Abschnitten nichts wirklich neues vorgestellt wurde. Im Zusammenhang mit dem Stichwort „Twisting Time“ hätte ich mir vielleicht auch noch einen Hinweis auf zeitkritische Sidechannel-Angriffe vorstellen können.
Typische Fehler sind:
- Deadlocks (das Programm hängt komplett)
- Livelocks (das Programm hängt in einer Endlosschleife)
- Fehlerhafte Kommunikation
- Fehler in der gemeinsamen Datennutzung
- Race Conditions
Race Conditions sind für den Angreifer in der Regel am interessantesten.
Die Ursachen für Race Conditions sind praktisch immer drei Hauptursachen:
- Vergessene Locks in konkurrierenden Zugriffen
- File System Races (TOCTOU-Fehler)
- Signal Races
Race Condition am Beispiel eines Ringpuffers
#define CELLS 32
int rbf[CELLS];
int rbf_idx = 0;
uint32_t num_elems;
void rbf_store( int data ) {
if (rbf_idx == CELLS)
rbf_idx = 0;
rbf[rbf_idx] = data;
rbf_idx++;
num_elems++;
}
Wenn dieser Code konkurrierend abläuft, kann es passieren, dass die if-Abfrage des ersten Threads einen rbf_idx-Wert kleiner CELLS ergibt, danach wird dieser Thread angehalten, ein zweiter Thread für die if-Abfrage durch, ebenfalls mit einem Wert in rbf_idx kleiner CELLS, der erste Thread schreibt folglich in den Puffer und erhöht den Index, anschließend schreibt der zweite Thread in den Buffer (wobei damit der reservierte Speicherbereich bereits überschritten wird) und erhöht den Index. Da rbf_idx jetzt bereits größer ist als CELLS, wird in Zukunft immer über den eigentlich reservierten Speicher des Buffers hinaus geschrieben. Ursache für diesen Fehler ist ein vergessener Lock, der den Bereich rbf_store sichert, da dieser Bereich nur einmal konkurrierend betreten werden darf.
Locking Fehler liegen entweder an komplett fehlenden Locks bzw. fehlender Synchronisation, da sich der Entwickler der Konkurrenz nicht bewusst war oder inkonsequentem Einsatz, bei dem einzelne Funktionen nicht richtig gesichert werden.
File System Race Condition
$TempDir = $Config{'tmpdir'} . "logwatch." . $$ . "/";
if ( -d $TempDir ) { rmdir ($TempDir); }
if ( -e $TempDir ) { unlink ($TempDir); }
mkdir ($TempDir,0700);
Bei File System Race Conditions handelt es sich praktisch immer um TOCTOU-Fehler (Time Of Check vs. Time Of Use). Ein Zustand wird zu einem Zeitpunkt A geprüft und das Wissen über diesen Zustand zu einem Zeitpunkt B verwendet, ohne zu beachten, dass sich dieser Zustand auf einem Multithreaded-System in der Zwischenzeit geändert haben kann. TOCTOU-Fehler treten besonders gerne bei temporären Dateien auf und sind sehr schwer zu vermeiden, da es in Unix keine atomare (d.h. nicht unterbrechbare Aktion) zum Prüfen und Anlegen einer Datei gibt. Exploits sind oft über Symlinks möglich, die Präsentation gibt hier ein cleveres Beispiel einer temporären Syslog-Datei verlinkt auf /root/.bash.
Signal Races
Signal Races sind die dritte Klasse häufiger Race Conditions und am schwierigsten zu verstehen. Dabei werden Signal-Handler konkurrierend eingesetzt, beispielsweise beim Beenden von Programmen oder Schreiben von Logfiles. Der klassische Fehler ist der Aufruf einer non_reentrant Funktion (d.h. einer Funktion die z.B. aufgrund interner Variablen nicht konkurrierend mehrfach aufgerufen werden darf) oder die Verwendung von non_reentrant Signal Handlers.
Signal Races findet man beispielsweise im Zusammenhang mit sigaction() und nicht offensichtlich erkennbar mehrfach genutzten Ressourcen (z.B. libc-Funktionen mit internen statischen Variablen die bei konkurrierenden Aufrufen überschrieben werden). In C++ kann man nach Singletons wie instanceOf suchen.
Die sehenswerte Präsentation (PDF, 1.0 MB) enthält die kompletten Source Code Beispiele.
Auf dem Camp wurde der Vortrag zu RFID von Milosch Meriac, dem Hauptentwickler der RFID-Hardware und von Henryk Plötz gehalten, der an der Software schraubt. Der Vortrag war recht ähnlich zum RFID-Vortrag von Harald Welte und Milosch Meriac auf dem letzten Congress.
RFID-Standards
Als Einleitung wurde wieder der RFID-Standard ISO 14443 vorgestellt, der Proximity Integrated Circuit Cards (PICC) definiert. Der Standard beschreibt im Detail
1. Physical Characteristics
2. RF Power & Signal Interface
3. Initialization & Anti-collision
4. Transmission Protocol
Hauptsächlich gibt es zwei verschiedene Kartentypen, Typ A, die Mifare-Karten von Phillips und Typ B, die z.B. bei ePassports zum Einsatz kommen. ISO 14443 setzt Amplitude Shift Keying (ASK) Modulation ein, die so kodierten Signale des Receivers (PDC) sind aus 5-10 m empfangbar, die Antwortsignale der Karte (PICC) liegen 60-80 dB unter der Signalstärke des Senders und sind typischerweise aus maximal 2 m empfangbar. Ein Anti-Collision-Protokoll soll unterschiedliche Karten in Reichweite des Empfängers trennen. Dazu werden UIDs (Unique Identifier mit 4, 7 oder 10 Byte) verwendet. Auf dem Congress im Dezember gab es dazu einen interessanten Vortrag einer holländischen Gruppe, die durch gezielte Erzeugung von Kollisionen einzelne Karten ausblenden konnte.
Kartentypen
ISO 14443A
- 16×4 = 64 Byte Speicher
- 10 Byte Read-Only Factory-Programmed, davon 7 Byte UID
- 6 Byte PROM, davon 2 Byte Lock-Bits
- 48 Byte nutzbarer Speicher
- Keine Verschlüsselung
- Keine Security-Funktionen außer der UID
Mifare Classic
- Weitverbreiteter Standardtyp
- 1-4 KB Speicher
- Proprietärer Stream-Cipher („Crypto1“) mit 48 Byte Schlüssellänge, bisher nicht gebrochen
- 4 Byte UID
- ACLs für einen Speicherbereich für Geldwerte auf den nur mit INCREASE/DECREASE-Kommandos zugegriffen werden kann
- Multiple User-Areas mit unterschiedlichen Schlüsseln
- Multi-Application-fähig
Mifare DESfire
- Mifare Classic-kompatibel
- DES/3DES Verschlüsselung
- 7 Byte UID
T=CH
- In ISO 14443-4 definiert
- APDUs vergleichbar zu kontaktbasierten Karten nach ISO 7816
- Wird in vielen ePassports verwendet
Hardware
Milosch hat sehr schön die benötigte Hardware beschrieben, im einfachsten Fall reicht eine triviale Kupferspule mit LED und Kondensator. Für die komplexeren Angriffe gibt es einen von ihm entwickelten RFID Sniffer/Sender, mit dem auch trivial Replay-Angriffe möglich sind. Die benötigte Hardware kann man entweder bei www.OpenPCD.org fertig kaufen oder anhand der Anleitungen und Vorlagen selbst bauen.
Work in Progress
Ein paar Sachen funktionieren noch nicht ganz:
- Anticollision tut noch nicht so 100%, aber daran arbeitet das Team
- Bereitstellen von Mifare-Samples um die Verschlüsselung zu brechen
- OpenPDC/OpenPICC OS nach FreeRTOS portieren
Und für folgendes benötigen die Jungs dringend Hilfe:
- Brechen der Mifare-Verschlüsselung
- OpenPCD und OpenPICC in ein Standalone-Sniffer/Replay-Gerät kombinieren
- RFID Fuzzing Suite
Hier kann jeder mithelfen!
Seit jetzt, heute, Mitternacht gilt der neue § 202c StGB.
Bildnachweis: Chaos Computer Club