11. August 2007

CCC Camp: Twisting timing in your favour

Category: CCC,Hacking — Christian @ 21:01

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.

1 Kommentar

  1. Kommentare gesperrt wegen Spam

    Comment by Christian — 7. Juni 2012 @ 08:09

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.