Freigeben über


Aktivieren der BinaryFormatter-Zwischenablageunterstützung (nicht empfohlen)

Vorsicht

BinaryFormatter Support wird nicht empfohlen. Verwenden Sie sie nur als temporäre Migrationsbrücke für Ältere Anwendungen, die nicht sofort zu den neuen typsicheren APIs migrieren können. Dieser Ansatz birgt erhebliche Sicherheitsrisiken.

In diesem Artikel wird beschrieben, wie Sie eingeschränkte BinaryFormatter Unterstützung für Windows Forms-Zwischenablagevorgänge in .NET 10 konfigurieren. Für Legacyanwendungen, die Zeit für die Migration benötigen, stellen Sie eingeschränkte Funktionalität durch explizite Konfiguration wieder her, da BinaryFormatter in der Laufzeit von .NET 9 aufgrund von Sicherheitsrisiken entfernt wurde.

Vollständige Migrationsanleitungen zu den neuen typsicheren APIs finden Sie unter Windows Forms-Zwischenablage und DataObject-Änderungen in .NET 10.

Von Bedeutung

Dieser Inhalt gilt nur für moderne .NET und nicht für .NET Framework, sofern nicht anders angegeben.

Voraussetzungen

Bevor Sie fortfahren, überprüfen Sie diese Konzepte:

  • Wie Ihre Anwendung BinaryFormatter derzeit in Vorgängen mit der Zwischenablage verwendet.
  • Die Sicherheitslücken, die zur Entfernung von BinaryFormatter führten.
  • Ihre Migrationszeitachse zu den neuen typsicheren Zwischenablage-APIs.

Weitere Informationen finden Sie in den folgenden Artikeln:

Sicherheitswarnungen und Risiken

BinaryFormatter ist aus folgenden Gründen unsicher und veraltet:

  • Sicherheitsanfälligkeiten bezüglich beliebiger Codeausführung: Angreifer können während der Deserialisierung bösartigen Code ausführen und Ihre Anwendung Remoteangriffen offenlegen.
  • Denial of Service-Angriffe: Böswillige Zwischenablagedaten können übermäßigen Arbeitsspeicher oder CPU-Ressourcen verbrauchen, was Abstürze oder Instabilität verursacht.
  • Informationsveröffentlichungsrisiken: Angreifer extrahieren möglicherweise vertrauliche Daten aus dem Arbeitsspeicher.
  • Keine Sicherheitsgrenzen: Das Format ist grundsätzlich unsicher, und Konfigurationseinstellungen können es nicht schützen.

Aktivieren Sie diese Unterstützung nur als temporäre Brücke, während Sie Ihre Anwendung so aktualisieren, dass sie die neuen typsicheren APIs verwendet.

Installieren des Kompatibilitätspakets

Fügen Sie dem Projekt das nicht unterstützte BinaryFormatter Kompatibilitätspaket hinzu. Dieses Paket bietet die erforderliche Laufzeitunterstützung für BinaryFormatter Vorgänge:

<ItemGroup>
  <PackageReference Include="System.Runtime.Serialization.Formatters" Version="10.0.0*-*"/>
</ItemGroup>

Hinweis

Dieses Paket ist als nicht unterstützt und veraltet gekennzeichnet. Verwenden Sie sie nur für temporäre Kompatibilität während der Migration.

Unsichere Serialisierung in Ihrem Projekt aktivieren

Legen Sie die EnableUnsafeBinaryFormatterSerialization-Eigenschaft auf true in der Projektdatei fest. Diese Eigenschaft weist den Compiler an, die Verwendung von BinaryFormatter zuzulassen:

<PropertyGroup>
  <TargetFramework>net10.0</TargetFramework>
  <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>

Ohne diese Einstellung generiert Ihre Anwendung Kompilierungsfehler, wenn sie versucht, APIs zu verwenden BinaryFormatter .

Konfigurieren der Windows Forms-Laufzeitoption

Erstellen oder aktualisieren Sie die Datei Ihrer Anwendung runtimeconfig.json , um den Windows Forms-spezifischen Zwischenablageschalter zu aktivieren. Mit dieser Konfiguration können Zwischenablageoperationen bei Notwendigkeit auf BinaryFormatter zurückgreifen.

{
  "runtimeOptions": {
    "configProperties": {
      "Windows.ClipboardDragDrop.EnableUnsafeBinaryFormatterSerialization": true
    }
  }
}

Von Bedeutung

Ohne diesen spezifischen Laufzeitschalter greifen Zwischenablagevorgänge nicht auf BinaryFormatter zurück, selbst wenn die allgemeine Serialisierungsunterstützung aktiviert ist. Dieser Switch ist speziell für die Zwischenablage-Funktionalität von Windows Forms und WPF erforderlich.

Implementierung von sicherheitsorientierten Typenauflösungen

Implementieren Sie auch, wenn BinaryFormatter aktiviert ist, Typen-Resolver, um die Deserialisierung auf explizit genehmigte Typen zu beschränken. Typlöser bieten Ihre einzige Verteidigung gegen böswillige Payload-Angriffe.

Erstellung eines sicheren Typauflösers

// Create a security-focused type resolver
private static Type SecureTypeResolver(TypeName typeName)
{
    // Explicit allow-list of permitted types—add only what you need
    var allowedTypes = new Dictionary<string, Type>
    {
        ["MyApp.Person"] = typeof(Person),
        ["MyApp.AppSettings"] = typeof(AppSettings),
        ["System.String"] = typeof(string),
        ["System.Int32"] = typeof(int),
        // Add only the specific types your application requires
    };

    // Only allow explicitly listed types - exact string match required
    if (allowedTypes.TryGetValue(typeName.FullName, out Type allowedType))
    {
        return allowedType;
    }

    // Reject any type not in the allow-list with clear error message
    throw new InvalidOperationException(
        $"Type '{typeName.FullName}' is not permitted for clipboard deserialization");
}
' Create a security-focused type resolver
Private Shared Function SecureTypeResolver(typeName As TypeName) As Type
    ' Explicit allow-list of permitted types—add only what you need
    Dim allowedTypes As New Dictionary(Of String, Type) From {
        {"MyApp.Person", GetType(Person)},
        {"MyApp.AppSettings", GetType(AppSettings)},
        {"System.String", GetType(String)},
        {"System.Int32", GetType(Integer)}
    } ' Add only the specific types your application requires

    ' Only allow explicitly listed types - exact string match required
    Dim allowedType As Type = Nothing
    If allowedTypes.TryGetValue(typeName.FullName, allowedType) Then
        Return allowedType
    End If

    ' Reject any type not in the allow-list with clear error message
    Throw New InvalidOperationException(
        $"Type '{typeName.FullName}' is not permitted for clipboard deserialization")
End Function

Verwenden Sie den Typlöser mit Zwischenablagevorgängen

// Use the resolver with clipboard operations
private static Type SecureTypeResolver(TypeName typeName)
{
    // Implementation from SecureTypeResolver example
    // ... (allow-list implementation here)
    throw new InvalidOperationException($"Type '{typeName.FullName}' is not permitted");
}

public static void UseSecureTypeResolver()
{
    // Retrieve legacy data using the secure type resolver
    if (Clipboard.TryGetData("LegacyData", SecureTypeResolver, out MyCustomType data))
    {
        ProcessLegacyData(data);
    }
    else
    {
        Console.WriteLine("No compatible data found on clipboard");
    }
}
' Use the resolver with clipboard operations
Private Shared Function SecureTypeResolver(typeName As TypeName) As Type
    ' Implementation from SecureTypeResolver example
    ' ... (allow-list implementation here)
    Throw New InvalidOperationException($"Type '{typeName.FullName}' is not permitted")
End Function

Public Shared Sub UseSecureTypeResolver()
    ' Retrieve legacy data using the secure type resolver
    Dim data As MyCustomType = Nothing
    If Clipboard.TryGetData("LegacyData", AddressOf SecureTypeResolver, data) Then
        ProcessLegacyData(data)
    Else
        Console.WriteLine("No compatible data found on clipboard")
    End If
End Sub

Sicherheitsrichtlinien für Typenlöser

Befolgen Sie beim Implementieren von Typlösern die folgenden grundlegenden Sicherheitsrichtlinien:

Explizite Zulassungslisten verwenden

  • Standardmäßig ablehnen: Nur explizit aufgelistete Typen zulassen.
  • Keine Wildcards: Musterabgleich oder namespacebasierte Berechtigungen vermeiden.
  • Exakter Abgleich: Erfordert genaue Zeichenfolgenvergleiche für Typnamen.

Überprüfen aller Eingaben

  • Typnamenüberprüfung: Stellen Sie sicher, dass Typnamen den erwarteten Formaten entsprechen.
  • Assemblyeinschränkungen: Beschränken Sie Typen auf bekannte, vertrauenswürdige Assemblys.
  • Versionsüberprüfung: Berücksichtigen Sie versionsspezifische Typeinschränkungen.

Sicheres Behandeln unbekannter Typen

  • Auslösen von Ausnahmen: Wird immer für nicht autorisierte Typen ausgelöst.
  • Protokollversuche: Erwägen Sie die Protokollierung nicht autorisierter Zugriffsversuche.
  • Löschen von Fehlermeldungen: Geben Sie spezifische Ablehnungsgründe für das Debuggen an.

Regelmäßige Wartung

  • Regelmäßig überwachen: Überprüfen und aktualisieren Sie die Liste zulässiger Typen.
  • Nicht verwendete Typen entfernen: Entfernen Sie Berechtigungen für Typen, die nicht mehr benötigt werden.
  • Dokumententscheidungen: Bewahren Sie eine klare Dokumentation auf, warum jeder Typ zulässig ist.

Testen der Konfiguration

Testen Sie nach dem Konfigurieren BinaryFormatter der Unterstützung Ihre Anwendung, um sicherzustellen, dass sie ordnungsgemäß funktioniert:

  1. Überprüfen Sie Zwischenablagevorgänge: Testen Sie sowohl das Speichern als auch das Abrufen von Daten mit Ihren benutzerdefinierten Typen.
  2. Testtyplöser: Vergewissern Sie sich, dass nicht autorisierte Typen ordnungsgemäß abgelehnt werden.
  3. Sicherheit überwachen: Beobachten Sie unerwartete Typenauflösungsversuche.
  4. Leistungstests: Stellen Sie sicher, dass der Typlöser die Leistung nicht erheblich beeinträchtigt.
public static void TestBinaryFormatterConfiguration()
{
    // Test data to verify configuration
    var testPerson = new Person { Name = "Test User", Age = 30 };

    try
    {
        // Test storing data (this should work with proper configuration)
        Clipboard.SetData("TestPerson", testPerson);
        Console.WriteLine("Successfully stored test data on clipboard");

        // Test retrieving with type resolver
        if (Clipboard.TryGetData("TestPerson", SecureTypeResolver, out Person retrievedPerson))
        {
            Console.WriteLine($"Successfully retrieved: {retrievedPerson.Name}, Age: {retrievedPerson.Age}");
        }
        else
        {
            Console.WriteLine("Failed to retrieve test data");
        }

        // Test that unauthorized types are rejected
        try
        {
            Clipboard.TryGetData("TestPerson", UnauthorizedTypeResolver, out Person _);
            Console.WriteLine("ERROR: Unauthorized type was not rejected!");
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"SUCCESS: Unauthorized type properly rejected - {ex.Message}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Configuration test failed: {ex.Message}");
    }
}

private static Type SecureTypeResolver(TypeName typeName)
{
    var allowedTypes = new Dictionary<string, Type>
    {
        ["ClipboardExamples.Person"] = typeof(Person),
    };

    if (allowedTypes.TryGetValue(typeName.FullName, out Type allowedType))
    {
        return allowedType;
    }

    throw new InvalidOperationException($"Type '{typeName.FullName}' is not permitted");
}

private static Type UnauthorizedTypeResolver(TypeName typeName)
{
    // Intentionally restrictive resolver to test rejection
    throw new InvalidOperationException($"No types are permitted by this test resolver");
}
Public Shared Sub TestBinaryFormatterConfiguration()
    ' Test data to verify configuration
    Dim testPerson As New Person With {.Name = "Test User", .Age = 30}

    Try
        ' Test storing data (this should work with proper configuration)
        Clipboard.SetData("TestPerson", testPerson)
        Console.WriteLine("Successfully stored test data on clipboard")

        ' Test retrieving with type resolver
        Dim retrievedPerson As Person = Nothing
        If Clipboard.TryGetData("TestPerson", AddressOf SecureTypeResolver, retrievedPerson) Then
            Console.WriteLine($"Successfully retrieved: {retrievedPerson.Name}, Age: {retrievedPerson.Age}")
        Else
            Console.WriteLine("Failed to retrieve test data")
        End If

        ' Test that unauthorized types are rejected
        Try
            Dim testResult As Person = Nothing
            Clipboard.TryGetData("TestPerson", AddressOf UnauthorizedTypeResolver, testResult)
            Console.WriteLine("ERROR: Unauthorized type was not rejected!")
        Catch ex As InvalidOperationException
            Console.WriteLine($"SUCCESS: Unauthorized type properly rejected - {ex.Message}")
        End Try

    Catch ex As Exception
        Console.WriteLine($"Configuration test failed: {ex.Message}")
    End Try
End Sub

Private Shared Function SecureTypeResolver(typeName As TypeName) As Type
    Dim allowedTypes As New Dictionary(Of String, Type) From {
        {"ClipboardExamples.Person", GetType(Person)}
    }

    Dim allowedType As Type = Nothing
    If allowedTypes.TryGetValue(typeName.FullName, allowedType) Then
        Return allowedType
    End If

    Throw New InvalidOperationException($"Type '{typeName.FullName}' is not permitted")
End Function

Private Shared Function UnauthorizedTypeResolver(typeName As TypeName) As Type
    ' Intentionally restrictive resolver to test rejection
    Throw New InvalidOperationException($"No types are permitted by this test resolver")
End Function

Planen Ihrer Migrationsstrategie

Während BinaryFormatter die Unterstützung temporäre Kompatibilität bietet, entwickeln Sie einen Migrationsplan, um zu den neuen typsicheren APIs zu wechseln:

  1. Verwendung identifizieren: Katalogisieren Sie alle Zwischenablagevorgänge mit benutzerdefinierten Typen.
  2. Priorisieren Sie die Migration: Konzentrieren Sie sich zuerst auf die sicherheitsempfindlichsten Vorgänge.
  3. Inkrementell aktualisieren: Migrieren Sie jeweils einen Vorgang, um das Risiko zu reduzieren.
  4. Testen Sie sorgfältig: Stellen Sie sicher, dass neue Implementierungen gleichwertige Funktionen bieten.
  5. BinaryFormatter entfernen: Deaktivieren Sie die Unterstützung, sobald die Migration abgeschlossen ist.

Bereinigen von Ressourcen

Nachdem Sie zu den neuen typsicheren Zwischenablage-APIs migriert haben, entfernen Sie die BinaryFormatter Konfiguration, um die Sicherheit zu verbessern.

  1. Entfernen Sie den System.Runtime.Serialization.Formatters Paketverweis.
  2. Entfernen Sie die EnableUnsafeBinaryFormatterSerialization Eigenschaft aus der Projektdatei.
  3. Entfernen Sie die Windows.ClipboardDragDrop.EnableUnsafeBinaryFormatterSerialization Einstellung von Ihrem runtimeconfig.json.
  4. Löschen Sie Implementierungen des Typlösers, die nicht mehr benötigt werden.