|
Dieser Artikel wurde manuell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen. Weitere Informationen
|
Übersetzung
Original
|
Gewusst wie: Ausführen von teilweise vertrauenswürdigem Code in einer Sandbox
AppDomain.CreateDomain( string friendlyName, Evidence securityInfo, AppDomainSetup info, PermissionSet grantSet, params StrongName[] fullTrustAssemblies);
So führen Sie eine Anwendung in einer Sandbox aus
-
Erstellen Sie den Berechtigungssatz, der der nicht vertrauenswürdigen Anwendung gewährt werden soll. Die Mindestberechtigung, die Sie gewähren können, ist die Execution-Berechtigung. Sie können auch zusätzliche Berechtigungen gewähren, die Sie für nicht vertrauenswürdigen Code als sicher erachten, z. B. IsolatedStorageFilePermission. Mit dem folgenden Code wird ein neuer Berechtigungssatz erstellt, der nur die Execution-Berechtigung enthält. PermissionSet permSet = new PermissionSet(PermissionState.None); permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
Alternativ können Sie einen vorhandenen benannten Berechtigungssatz verwenden, z. B. Internet. Evidence ev = new Evidence(); ev.AddHostEvidence(new Zone(SecurityZone.Internet)); PermissionSet internetPS = SecurityManager.GetStandardSandbox(ev);
Die GetStandardSandbox-Methode gibt abhängig von der Zone im Beweis einen Internet-Berechtigungssatz oder einen LocalIntranet-Berechtigungssatz zurück. GetStandardSandbox erstellt auch Identitätsberechtigungen für einige der als Verweise übergebenen Beweisobjekte. -
Signieren Sie die Assembly mit der Hostingklasse (in diesem Beispiel Sandboxer), die den nicht vertrauenswürdigen Code aufruft. Fügen Sie den zum Signieren der Assembly verwendeten StrongName dem StrongName-Array des fullTrustAssemblies-Parameters für den CreateDomain-Aufruf hinzu. Die Hostingklasse muss als voll vertrauenswürdige Klasse ausgeführt werden, damit teilweise vertrauenswürdiger Code ausgeführt werden kann oder Dienste für die teilweise vertrauenswürdige Anwendung bereitgestellt werden können. Der StrongName einer Assembly wird folgendermaßen gelesen: StrongName fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>();
.NET Framework-Assemblys wie mscorlib und System.dll müssen der Liste der voll vertrauenswürdigen Assemblys nicht hinzugefügt werden, da sie als voll vertrauenswürdige Assemblys aus dem globalen Assemblycache geladen werden. -
Initialisieren Sie den AppDomainSetup-Parameter der CreateDomain-Methode. Mit diesem Parameter können viele Einstellungen der neuen AppDomain gesteuert werden. Die ApplicationBase-Eigenschaft ist eine wichtige Einstellung und sollte sich von der ApplicationBase-Eigenschaft für die AppDomain der Hostinganwendung unterscheiden. Wenn die ApplicationBase-Einstellungen identisch sind, kann die teilweise vertrauenswürdige Anwendung die Hostanwendung ausnutzen, indem sie diese anweist, eine von ihr definierte Ausnahme (mit voller Vertrauenswürdigkeit) zu laden. Dies ist ein weiterer Grund, weshalb die Verwendung eines Catch-Blocks (Ausnahme) nicht empfohlen wird. Das Risiko von Angriffen kann reduziert werden, indem die Anwendungsbasis des Hosts und der Sandkastenanwendung auf unterschiedliche Werte festgelegt werden. AppDomainSetup adSetup = new AppDomainSetup(); adSetup.ApplicationBase = Path.GetFullPath(pathToUntrusted);
-
Rufen Sie die CreateDomain(String, Evidence, AppDomainSetup, PermissionSet, StrongName[])-Methodenüberladung auf, um die Anwendungsdomäne mit den angegebenen Parametern zu erstellen. Die Signatur für diese Methode lautet wie folgt: public static AppDomain CreateDomain(string friendlyName, Evidence securityInfo, AppDomainSetup info, PermissionSet grantSet, params StrongName[] fullTrustAssemblies)Zusätzliche Informationen: Dies ist die einzige Überladung der CreateDomain-Methode, die einen PermissionSet als Parameter akzeptiert und folglich die einzige Überladung, mit der Sie eine teilweise vertrauenswürdige Anwendung laden können. Mit dem evidence-Parameter wird kein Berechtigungssatz berechnet. Er wird von anderen Funktionen des .NET Framework zur Identifikation verwendet. Die ApplicationBase-Eigenschaft des info-Parameters muss für diese Überladung festgelegt werden. Der fullTrustAssemblies-Parameter enthält das params-Schlüsselwort, d. h., es muss kein StrongName-Array erstellt werden. Die Übergabe von keinem (null), einem oder mehr starken Namen als Parameter ist zulässig. Im Folgenden sehen Sie den Code zum Erstellen der Anwendungsdomäne:
AppDomain newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly); -
Laden Sie den Code in die erstellte Sandkasten-AppDomain. Dies kann auf zwei Arten ausgeführt werden: -
Rufen Sie die ExecuteAssembly-Methode für die Assembly auf. -
Erstellen Sie mit der CreateInstanceFrom-Methode eine Instanz einer von AppDomain abgeleiteten Klasse im neuen MarshalByRefObject.
Die zweite Methode ist vorzuziehen, da sie die Übergabe von Parametern an die neue AppDomain-Instanz vereinfacht. Die CreateInstanceFrom-Methode stellt zwei wichtige Funktionen bereit: -
Sie können eine CodeBase verwenden, die auf einen Speicherort zeigt, der die Assembly nicht enthält. -
Für volle Vertrauenswürdigkeit (PermissionState.Unrestricted) kann zum Erstellen eine Assert-Methode verwendet werden, die das Erstellen einer Instanz einer kritischen Klasse ermöglicht. (Dies ist immer dann der Fall, wenn die Assembly nicht über Transparenzmarkierungen verfügt und als voll vertrauenswürdige Assembly geladen wird.) Mit dieser Funktion darf daher nur Code erstellt werden, den Sie als vertrauenswürdig erachten. Außerdem wird empfohlen, in der neuen Anwendungsdomäne nur Instanzen voll vertrauenswürdiger Klassen zu erstellen.
ObjectHandle handle = Activator.CreateInstanceFrom( newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName, typeof(Sandboxer).FullName );Wenn Sie in einer neuen Domäne eine Instanz einer Klasse erstellen möchten, muss die Klasse die MarshalByRefObject-Klasse erweitern. class Sandboxer:MarshalByRefObject
-
-
Entpacken Sie die neue Domäneninstanz in einem Verweis in dieser Domäne. Dieser Verweis wird verwendet, um den nicht vertrauenswürdigen Code auszuführen. Sandboxer newDomainInstance = (Sandboxer) handle.Unwrap();
-
Rufen Sie die ExecuteUntrustedCode-Methode in der soeben erstellten Instanz der Sandboxer-Klasse auf. newDomainInstance.ExecuteUntrustedCode(untrustedAssembly, untrustedClass, entryPoint, parameters);
Dieser Aufruf wird in der Sandkastenanwendungsdomäne mit eingeschränkten Berechtigungen ausgeführt. public void ExecuteUntrustedCode(string assemblyName, string typeName, string entryPoint, Object[] parameters) { //Load the MethodInfo for a method in the new assembly. This might be a method you know, or //you can use Assembly.EntryPoint to get to the entry point in an executable. MethodInfo target = Assembly.Load(assemblyName).GetType(typeName).GetMethod(entryPoint); try { // Invoke the method. target.Invoke(null, parameters); } catch (Exception ex) { //When information is obtained from a SecurityException extra information is provided if it is //accessed in full-trust. (new PermissionSet(PermissionState.Unrestricted)).Assert(); Console.WriteLine("SecurityException caught:\n{0}", ex.ToString()); CodeAccessPermission.RevertAssert(); Console.ReadLine(); } }System.Reflection wird verwendet, um in der teilweise vertrauenswürdigen Assembly ein Handle von einer Methode abzurufen. Das Handle kann verwendet werden, um Code sicher mit minimalen Berechtigungen auszuführen. Beachten Sie im vorherigen Code die Assert für die Berechtigung Voll vertrauenswürdig, bevor Sie SecurityException drucken. new PermissionSet(PermissionState.Unrestricted)).Assert()
Der Assert für volle Vertrauenswürdigkeit wird verwendet, um erweiterte Informationen aus der SecurityException abzurufen. Ohne die Assert-Methode stellt die ToString-Methode der SecurityException fest, dass der Stapel teilweise vertrauenswürdigen Code enthält, und die zurückgegebenen Informationen werden eingeschränkt. Dies kann Sicherheitsprobleme verursachen, wenn der teilweise vertrauenswürdige Code diese Informationen lesen könnte. Das Risiko wird jedoch reduziert, indem UIPermission nicht gewährt wird. Die volle Vertrauenswürdigkeit sollte sparsam und nur dann verwendet werden, wenn Sie sicher sind, dass dies nicht dazu führen kann, dass teilweise vertrauenswürdiger Code zu voller Vertrauenswürdigkeit erhöht wird. Im Allgemeinen sollte nicht vertrauenswürdiger Code nicht in der gleichen Funktion und nach dem Aufrufen eines Asserts für volle Vertrauenswürdigkeit aufgerufen werden. Es empfiehlt sich, den Assert nach der Verwendung immer zurückzusetzen.
using System;
using System.IO;
namespace UntrustedCode
{
public class UntrustedClass
{
// Pretend to be a method checking if a number is a Fibonacci
// but which actually attempts to read a file.
public static bool IsFibonacci(int number)
{
File.ReadAllText("C:\\Temp\\file.txt");
return false;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.Remoting;
//The Sandboxer class needs to derive from MarshalByRefObject so that we can create it in another
// AppDomain and refer to it from the default AppDomain.
class Sandboxer : MarshalByRefObject
{
const string pathToUntrusted = @"..\..\..\UntrustedCode\bin\Debug";
const string untrustedAssembly = "UntrustedCode";
const string untrustedClass = "UntrustedCode.UntrustedClass";
const string entryPoint = "IsFibonacci";
private static Object[] parameters = { 45 };
static void Main()
{
//Setting the AppDomainSetup. It is very important to set the ApplicationBase to a folder
//other than the one in which the sandboxer resides.
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = Path.GetFullPath(pathToUntrusted);
//Setting the permissions for the AppDomain. We give the permission to execute and to
//read/discover the location where the untrusted code is loaded.
PermissionSet permSet = new PermissionSet(PermissionState.None);
permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
//We want the sandboxer assembly's strong name, so that we can add it to the full trust list.
StrongName fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>();
//Now we have everything we need to create the AppDomain, so let's create it.
AppDomain newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly);
//Use CreateInstanceFrom to load an instance of the Sandboxer class into the
//new AppDomain.
ObjectHandle handle = Activator.CreateInstanceFrom(
newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
typeof(Sandboxer).FullName
);
//Unwrap the new domain instance into a reference in this domain and use it to execute the
//untrusted code.
Sandboxer newDomainInstance = (Sandboxer) handle.Unwrap();
newDomainInstance.ExecuteUntrustedCode(untrustedAssembly, untrustedClass, entryPoint, parameters);
}
public void ExecuteUntrustedCode(string assemblyName, string typeName, string entryPoint, Object[] parameters)
{
//Load the MethodInfo for a method in the new Assembly. This might be a method you know, or
//you can use Assembly.EntryPoint to get to the main function in an executable.
MethodInfo target = Assembly.Load(assemblyName).GetType(typeName).GetMethod(entryPoint);
try
{
//Now invoke the method.
bool retVal = (bool)target.Invoke(null, parameters);
}
catch (Exception ex)
{
// When we print informations from a SecurityException extra information can be printed if we are
//calling it with a full-trust stack.
(new PermissionSet(PermissionState.Unrestricted)).Assert();
Console.WriteLine("SecurityException caught:\n{0}", ex.ToString());
CodeAccessPermission.RevertAssert();
Console.ReadLine();
}
}
}