DMA-Gerät zu früh in der Boot-Phase aktiviert

Beschreibung

DMA-Gerät zu früh in der Boot-Phase aktiviert tritt auf, wenn ein DMA-fähiges (Direct Memory Access) Gerät Zugriff auf Speicheradressen hat, bevor Sicherheitsfunktionen wie IOMMU/SMMU konfiguriert wurden. Bevor eine Speicherschutzeinheit vollständig konfiguriert ist, können böswillige Peripheriegeräte die fehlenden Beschränkungen ausnutzen, um unbefugte Speicheroperationen durchzuführen. Die Schwachstelle entsteht aus dem Boot-Timing, das DMA vor den Sicherheitskontrollen ermöglicht.

Risiko

Frühzeitiger DMA-Zugriff schafft schwerwiegende Sicherheitsauswirkungen. Böswillige Peripheriegeräte können während des Boots beliebigen Speicher lesen/schreiben. Sichere Boot-Ketten können umgangen werden. Anmeldeinformationen und kryptografische Schlüssel können extrahiert werden. Persistente Firmware-Implantate können installiert werden. Speicherschutz ist während anfälliger Zeitfenster unwirksam. Angriffe können erfolgen, bevor das Betriebssystem die Kontrolle übernimmt.

Lösung

Stellen Sie sicher, dass die IOMMU/SMMU-Konfiguration vor dem Aktivieren von DMA-Übertragungen abgeschlossen ist. Deaktivieren Sie DMA-Controller-Zugriff während der frühen Boot-Phasen. Implementieren Sie DMA-Sperrmechanismen, die bis zum Abschluss der Sicherheitskonfiguration aktiv bleiben. Richten Sie vor dem Zulassen von DMA standardmäßige restriktive IOMMU-Richtlinien ein. Authentifizieren Sie Peripheriegeräte, bevor Sie DMA-Zugriff gewähren. Verwenden Sie Hardware-Schalter, um DMA bis zum Abschluss des Boots blockiert zu halten.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Speicher lesen - Böswillige Geräte können vor IOMMU-Aktivierung beliebigen Speicher lesen.
IntegritätBereich: Integrität

Speicher modifizieren - DMA kann verwendet werden, um kritische Speicherregionen ohne Einschränkungen zu modifizieren.
ZugriffskontrolleBereich: Zugriffskontrolle

Schutzmechanismus umgehen - Speicherschutz ist unwirksam, bis IOMMU konfiguriert ist.

Beispielcode und Lösung

Verwundbarer Code

// Verwundbar: Boot-Firmware ohne DMA-Schutz

// Boot-Sequenz die DMA zu früh aktiviert
void vulnerable_boot_sequence(void) {
    // Stufe 1: Basis-Hardware-Initialisierung
    init_clock();
    init_memory_controller();

    // VERWUNDBAR: PCIe und DMA vor Sicherheits-Setup aktivieren
    enable_pcie_bus();
    enable_dma_controllers();  // DMA zu früh aktiviert!

    // An diesem Punkt können böswillige DMA-Geräte:
    // - Verschlüsselungsschlüssel aus dem Speicher lesen
    // - Boot-Code modifizieren
    // - Secure-Boot-Prüfungen umgehen

    // Stufe 2: Sicherheitsinitialisierung (ZU SPÄT)
    init_iommu();  // IOMMU konfiguriert nachdem DMA bereits aktiv
    configure_secure_boot();
    verify_firmware_signature();

    // Stufe 3: Boot fortsetzen
    load_os_kernel();
}

// Verwundbar: Keine DMA-Schutzkonfiguration
void enable_dma_controllers(void) {
    // Alle DMA-Controller ohne Einschränkungen aktivieren
    for (int i = 0; i < NUM_DMA_CONTROLLERS; i++) {
        dma_controller[i].enabled = true;
        dma_controller[i].access_all_memory = true;  // Keine Einschränkungen!
        // Kein IOMMU-Mapping konfiguriert
    }
}
// Verwundbar: DMA-Controller vor Sicherheitsinitialisierung aktiviert
// Dies erlaubt DMA-Angriffe während des frühen Boots

module vulnerable_boot_controller (
    input wire clk,
    input wire reset_n,
    input wire power_on,
    output reg dma_enable,
    output reg security_init_done
);

    reg [3:0] boot_stage;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_stage <= 4'b0000;
            dma_enable <= 1'b0;
            security_init_done <= 1'b0;
        end else begin
            case (boot_stage)
                4'b0000: begin
                    // Stufe 0: Einschalten
                    if (power_on) boot_stage <= 4'b0001;
                end

                4'b0001: begin
                    // Stufe 1: VERWUNDBAR - DMA sofort aktivieren
                    // Sicherheit ist noch nicht initialisiert!
                    dma_enable <= 1'b1;  // DMA zu früh aktiviert!
                    boot_stage <= 4'b0010;
                end

                4'b0010: begin
                    // Stufe 2: Basis-Hardware initialisieren
                    // DMA ist bereits aktiv - Angreifer kann auf Speicher zugreifen
                    boot_stage <= 4'b0011;
                end

                4'b0011: begin
                    // Stufe 3: Sicherheit initialisieren (ZU SPÄT!)
                    // DMA-Angriffe könnten bereits stattgefunden haben
                    security_init_done <= 1'b1;
                    boot_stage <= 4'b0100;
                end

                4'b0100: begin
                    // Stufe 4: Boot abgeschlossen
                    // System könnte bereits kompromittiert sein
                end
            endcase
        end
    end

endmodule

// Verwundbar: Kein IOMMU-Schutz während des frühen Boots
module vulnerable_dma_controller (
    input wire clk,
    input wire dma_request,
    input wire [31:0] src_addr,
    input wire [31:0] dst_addr,
    input wire [15:0] length,
    output reg dma_complete
);

    // DMA-Controller ohne Zugriffskontrolle
    // Jedes Gerät kann beliebige Speicheradressen lesen/schreiben

    always @(posedge clk) begin
        if (dma_request) begin
            // Keine Adressvalidierung
            // Keine Berechtigungsprüfung
            // Direkter Speicherzugriff gewährt
            perform_dma_transfer(src_addr, dst_addr, length);
            dma_complete <= 1'b1;
        end
    end

endmodule

Sichere Lösung

// Sicher: Boot-Firmware mit korrekter DMA-Schutzsequenz

void secure_boot_sequence(void) {
    // Stufe 1: Basis-Hardware-Initialisierung
    // DMA-Geräte bleiben deaktiviert
    init_clock();
    init_memory_controller();

    // Stufe 2: IOMMU VOR Aktivierung von DMA initialisieren
    init_iommu();
    configure_iommu_dma_remapping();
    enable_iommu_protection();

    // Stufe 3: Secure Boot konfigurieren
    configure_secure_boot();
    verify_firmware_signature();

    // Stufe 4: Speicherschutz einrichten
    configure_memory_regions();
    enable_memory_encryption();

    // Stufe 5: JETZT PCIe/DMA mit aktivem Schutz aktivieren
    enable_pcie_bus_with_iommu();
    enable_dma_controllers_restricted();

    // Stufe 6: Sicheren Boot fortsetzen
    load_verified_os_kernel();
}

// Sicher: DMA-Controller mit Einschränkungen aktiviert
void enable_dma_controllers_restricted(void) {
    // Überprüfen ob IOMMU aktiv ist
    if (!is_iommu_enabled()) {
        panic("DMA kann nicht ohne IOMMU-Schutz aktiviert werden");
    }

    for (int i = 0; i < NUM_DMA_CONTROLLERS; i++) {
        // IOMMU-Mapping für jeden DMA-Controller konfigurieren
        configure_dma_iommu_mapping(i);

        // Mit Einschränkungen aktivieren
        dma_controller[i].enabled = true;
        dma_controller[i].iommu_required = true;
        dma_controller[i].allowed_regions = get_safe_dma_regions();

        // Aktivierung für Audit protokollieren
        log_dma_controller_enabled(i);
    }
}

// Sicher: IOMMU-Initialisierung
void init_iommu(void) {
    // IOMMU-Hardware aktivieren
    iommu_hardware_enable();

    // Standard-Richtlinie: alle DMA verweigern
    iommu_set_default_policy(IOMMU_DENY_ALL);

    // Interrupt-Remapping konfigurieren
    iommu_configure_interrupt_remapping();

    // DMA-Remapping aktivieren
    iommu_enable_dma_remapping();

    // Überprüfen ob IOMMU betriebsbereit ist
    if (!iommu_verify_operational()) {
        panic("IOMMU-Initialisierung fehlgeschlagen");
    }
}
// Sicher: DMA-Controller erst nach Sicherheitsinitialisierung aktiviert
// IOMMU-Schutz von Boot-Beginn an aktiv

module secure_boot_controller (
    input wire clk,
    input wire reset_n,
    input wire power_on,
    input wire iommu_ready,
    input wire security_verified,
    output reg dma_enable,
    output reg security_init_done
);

    reg [3:0] boot_stage;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_stage <= 4'b0000;
            dma_enable <= 1'b0;  // DMA standardmäßig deaktiviert
            security_init_done <= 1'b0;
        end else begin
            case (boot_stage)
                4'b0000: begin
                    // Stufe 0: Einschalten - DMA bleibt deaktiviert
                    if (power_on) boot_stage <= 4'b0001;
                end

                4'b0001: begin
                    // Stufe 1: IOMMU zuerst initialisieren
                    // DMA während dieser Phase noch deaktiviert
                    boot_stage <= 4'b0010;
                end

                4'b0010: begin
                    // Stufe 2: Warten bis IOMMU bereit ist
                    if (iommu_ready) boot_stage <= 4'b0011;
                    // DMA noch deaktiviert
                end

                4'b0011: begin
                    // Stufe 3: Sicherheitseinstellungen initialisieren
                    // Speicherschutz konfigurieren, Secure Boot
                    boot_stage <= 4'b0100;
                end

                4'b0100: begin
                    // Stufe 4: Sicherheitskonfiguration verifizieren
                    if (security_verified) begin
                        security_init_done <= 1'b1;
                        boot_stage <= 4'b0101;
                    end
                end

                4'b0101: begin
                    // Stufe 5: JETZT DMA mit IOMMU-Schutz aktivieren
                    // Sicherheit ist vollständig initialisiert
                    dma_enable <= 1'b1;  // Sicher jetzt zu aktivieren
                    boot_stage <= 4'b0110;
                end

                4'b0110: begin
                    // Stufe 6: Boot abgeschlossen mit aktivem Schutz
                end
            endcase
        end
    end

endmodule

// Sicher: DMA-Controller mit IOMMU-Integration
module secure_dma_controller (
    input wire clk,
    input wire reset_n,
    input wire dma_request,
    input wire [31:0] src_addr,
    input wire [31:0] dst_addr,
    input wire [15:0] length,
    input wire [7:0] device_id,
    input wire iommu_enabled,
    output reg dma_complete,
    output reg dma_error
);

    // IOMMU-Abfragesignale
    wire iommu_permit;
    wire [31:0] translated_src;
    wire [31:0] translated_dst;

    // IOMMU-Integration
    iommu_checker iommu (
        .device_id(device_id),
        .src_addr(src_addr),
        .dst_addr(dst_addr),
        .length(length),
        .permit(iommu_permit),
        .translated_src(translated_src),
        .translated_dst(translated_dst)
    );

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            dma_complete <= 1'b0;
            dma_error <= 1'b0;
        end else if (dma_request) begin
            // Prüfen ob IOMMU aktiviert ist
            if (!iommu_enabled) begin
                dma_error <= 1'b1;  // Ablehnen wenn IOMMU nicht bereit
                dma_complete <= 1'b0;
            end
            // IOMMU-Berechtigung prüfen
            else if (!iommu_permit) begin
                dma_error <= 1'b1;  // Zugriff durch IOMMU verweigert
                dma_complete <= 1'b0;
            end
            else begin
                // Übersetzte Adressen von IOMMU verwenden
                perform_dma_transfer(translated_src, translated_dst, length);
                dma_complete <= 1'b1;
                dma_error <= 1'b0;
            end
        end
    end

endmodule

Ausgenutzt in der Praxis

Thunderclap-Angriff auf Thunderbolt-Geräte (2019)

Forscher demonstrierten, wie böswillige Thunderbolt-Geräte DMA-Angriffe durchführen könnten, um Betriebssystem-Sicherheitsmechanismen zu umgehen, da IOMMU-Schutz entweder fehlte oder während der frühen Boot-Phasen nicht aktiv war.

PCILeech für DMA-basierte Speicherangriffe (2016)

PCILeech zeigte, wie ungeschützte DMA über verschiedene Schnittstellen verwendet werden könnte, um Speicherinhalte zu lesen, Passwörter zu extrahieren und Sicherheitskontrollen auf Systemen ohne ordnungsgemäßen IOMMU-Schutz zu umgehen.


Tools zum Testen und Ausnutzen

  • PCILeech — DMA-Angriffsoftware über verschiedene Hardware.

  • Inception — FireWire/Thunderbolt DMA-Angriffstool.


CVE-Beispiele

  • CVE-2019-12819 — IOMMU-Umgehung durch DMA-Zugriff während des Boots.

  • CVE-2020-0069 — DMA-Angriff ermöglicht Privilegieneskalation.


Referenzen

  1. MITRE Corporation. "CWE-1190: DMA Device Enabled Too Early in Boot Phase." https://cwe.mitre.org/data/definitions/1190.html

  2. Thunderclap Project. "Security Vulnerabilities in Modern Computers." https://thunderclap.io/

  3. Intel. "IOMMU Configuration Guide."