Condividi tramite


Proteggere un servizio negoziato

Per impostazione predefinita, i servizi negoziati sono disponibili solo per l'utente locale e per i processi coinvolti nella sessione di Visual Studio che l'ha attivata. In questi valori predefiniti, le considerazioni sulla sicurezza per i servizi negoziati non sono diverse da quelle di altro codice in esecuzione in questi processi, tra cui:

  • Dal punto di vista del modello di minaccia, si presuppone che le estensioni eseguite all'interno del processo di Visual Studio siano completamente attendibili. Le estensioni che esauriscono il processo devono considerare le chiamate al servizio di Visual Studio come superamento di un limite di attendibilità.
  • Il codice deve convalidare gli argomenti nei punti di ingresso per confermare che rientrano nei modelli/intervalli previsti.
  • Durante la lettura dei dati dal disco, considerare che i dati potrebbero essere stati manomessi.
  • Quando si ricevono dati da una rete o da Internet, prestare attenzione durante l'analisi o la deserializzazione dei dati per evitare vulnerabilità comuni.

Quando il servizio viene registrato con il ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients flag impostato, si applicano diverse considerazioni di sicurezza aggiuntive critiche. La parte restante di questo articolo è incentrata su queste considerazioni.

Controlli di autorizzazione per le operazioni sensibili

Acquisizione del servizio di autorizzazione

Il servizio negoziato deve avere un costruttore che accetta come AuthorizationServiceClient parametro . L'argomento deve essere archiviato in un campo ed eliminato nel metodo del Dispose() servizio.

class Calculator : ICalculator, IDisposable
{
    private readonly AuthorizationServiceClient authorizationService;

    internal Calculator(AuthorizationServiceClient authorizationService)
    {
        this.authorizationService = authorizationService;
    }

    public void Dispose()
    {
        this.authorizationService.Dispose();
    }
}

La service factory di cui si esegue il proffer cambia leggermente per supportare questo nuovo parametro. Anziché fornire un oggetto BrokeredServiceFactory al IBrokeredServiceContainer.Proffer metodo , fornire un AuthorizingBrokeredServiceFactory delegato. Questo delegato riceve l'oggetto AuthorizationServiceClient che sarà necessario passare al servizio negoziato.

Questa modifica al codice proffer potrebbe essere simile alla seguente:

 container.Proffer(
     CalculatorService,
-    (moniker, options, serviceBroker, cancellationToken) => new ValueTask<object?>(new CalculatorService()));
+    (moniker, options, serviceBroker, authorizationService, cancellationToken) => new ValueTask<object?>(new CalculatorService(authorizationService)));

Uso del servizio di autorizzazione

Qualsiasi operazione che può divulgare informazioni riservate o modificare lo stato dell'utente deve essere verificata con il servizio di autorizzazione usando AuthorizationServiceClient.AuthorizeOrThrowAsync.

Per affermare che il chiamante è il proprietario del codice (la stessa identità dell'operatore dell'host di Live Share), è possibile usare questo codice:

private static readonly ProtectedOperation ClientIsOwner = WellKnownProtectedOperations.CreateClientIsOwner();

public ValueTask ResetOperationCounterAsync(CancellationToken cancellationToken)
{
    // Resetting the counter should only be allowed if the user is the owner.
    await this.authorizationService.AuthorizeOrThrowAsync(ClientIsOwner, cancellationToken);

    // Proceed with the operation.
    this.operationCounter = 0;
}

Nella classe sono definiti WellKnownProtectedOperations vari altri livelli di autorizzazione.

Tutti i controlli di autorizzazione vengono sempre approvati quando il client del servizio è in esecuzione nello stesso computer e nello stesso account utente. Vengono inoltre approvati per un guest di Live Share che opera con lo stesso account Microsoft dell'host.

Quando l'operazione richiesta non è autorizzata, AuthorizeOrThrowAsync genererà un'eccezione UnauthorizedAccessException. L'host live share può notificare al proprietario il tentativo non riuscito, dando all'host la possibilità di concedere l'autorizzazione necessaria per completare l'operazione se ProtectedOperation viene riconosciuto in modo che un tentativo successivo sul client abbia esito positivo.

Memorizza AuthorizationServiceClient nella cache tutti i controlli di autorizzazione in locale in modo che i controlli di autorizzazione ripetuti saranno veloci. Nel caso in cui il set di autorizzazioni di un utente cambi (ad esempio, l'host di Live Share modifica le autorizzazioni per il guest), la cache locale viene scaricata automaticamente.

Utilizzo di altri servizi negoziati

Quando un servizio negoziato richiede l'accesso a un altro servizio negoziato, deve usare l'oggetto IServiceBroker fornito alla relativa factory di servizio. Non deve usare service broker globale, in quanto non è a conoscenza del contesto di questa particolare istanza del servizio negoziata e l'autorizzazione che il client deve attivare e richiamare altri comportamenti.

Se il servizio calcolatrice aveva bisogno di altri servizi negoziati per implementarne il comportamento, il costruttore verrebbe modificato in modo da accettare un oggetto IServiceBroker:

internal class Calculator : ICalculator
{
    private readonly IServiceBroker serviceBroker;
    private readonly AuthorizationServiceClient authorizationService;

    internal class Calculator(IServiceBroker serviceBroker, AuthorizationServiceClient authorizationService)
    {
        this.serviceBroker = serviceBroker;
        this.authorizationService = authorizationService;
    }
}

Questo parametro aggiuntivo influirà sul codice di ffering di Service Factory:

 container.Proffer(
     CalculatorService,
     (moniker, options, serviceBroker, authorizationService, cancellationToken)
-        => new ValueTask<object?>(new CalculatorService(authorizationService)));
+        => new ValueTask<object?>(new CalculatorService(serviceBroker, authorizationService)));

Disponibilità limitata del servizio negoziato

Quando il client del servizio negoziato è un guest di Live Share (con un account diverso dal proprietario dell'host), il service broker contestuale attiverà solo altri servizi negoziati che hanno impostato il AllowTransitiveGuestClients flag anche come precauzione di sicurezza. I tentativi di attivare un servizio broker non qualificato genereranno un'eccezione UnauthorizedAccessException.

Se il servizio negoziato richiede un altro servizio negoziato che non dispone del AllowTransitiveGuestClients flag , è possibile usare il service broker globale per ottenerlo, ma deve considerare che i servizi negoziati ottenuti da esso non hanno idea che un guest non attendibile sia il client finale. È consigliabile seguire tutte le stesse precauzioni indicate nella sezione successiva sulla chiamata di altri servizi di Visual Studio o altre API.

Altre informazioni sull'utilizzo dei servizi negoziati.

Utilizzo di altri servizi di Visual Studio o di altre API

La chiamata di servizi standard di Visual Studio, librerie di terze parti o API .NET standard è consentita nei servizi negoziati esposti agli utenti guest di Live Share, ma tali chiamate devono essere scritte attentamente e tutti gli input convalidati per primi.

I percorsi o gli URL dei file devono essere controllati attentamente per assicurarsi che siano validi e rientrano nei percorsi secondari previsti a cui l'utente guest ha l'autorizzazione per l'accesso. Ad esempio, se il servizio negoziato consente la lettura o la scrittura in file in base a un percorso, il percorso deve essere controllato per rientrare nella soluzione aperta e che il guest abbia effettivamente le autorizzazioni di scrittura, se applicabile. La convalida dei percorsi di file correttamente può essere difficile da considerare .. e altri mezzi per renderlo simile a un percorso inizia con il prefisso corretto, ma quindi eseguire l'escape della directory della soluzione consentita.

Usare l'oggetto AuthorizationServiceClient descritto nella sezione precedente come appropriato per affermare che il client dispone dell'autorizzazione prima di chiamare un'API che non dispone dei propri controlli di autorizzazione predefiniti. Si presuppone che solo i servizi negoziati incorporati in Visual Studio contengano i propri controlli di autorizzazione e ciò si basa sull'acquisizione di questi servizi negoziati usando il service broker contestuale, come descritto nella sezione precedente.

Tutte le altre API, inclusi i servizi di Visual Studio non negoziati o i servizi negoziati ottenuti con il Service Broker globale, possono essere eseguite in base al livello di autorizzazione del guest di Live Share, rendendo il proprio controllo di autorizzazione critico per proteggere la sicurezza dell'host Live Share.

Evitare di esporre funzionalità dal servizio negoziato già esposto da un altro servizio negoziato di Visual Studio man mano che aumenta la superficie di attacco.

Condivisione dello stato tra istanze del servizio negoziato

Quando il servizio negoziato richiede la condivisione dello stato tra più istanze del servizio, questi dati vengono esposti potenzialmente a più utenti con set di autorizzazioni diversi. Diventa fondamentale per il servizio negoziato proteggere questi dati tra questi utenti. Usare il modello STRIDE per identificare, classificare e ridurre le minacce.

È possibile decidere di considerare lo stato condiviso come attendibile e quindi concedere l'autorizzazione per eseguire qualsiasi operazione necessaria internamente( ad esempio, accedere ai servizi di Visual Studio o usare il Service Broker globale). In tal caso, diventa responsabilità di un'istanza del servizio negoziata di proteggere le chiamate effettuate nello stato condiviso per garantire che tutti gli input siano appropriati in base alle autorizzazioni dell'utente usando il servizio di autorizzazione.

Microsoft Threat Modeling Tool può essere uno strumento utile per proteggere lo stato condiviso e gli utenti.