Come gestisci la sicurezza del database da un'applicazione desktop?

12

Per circa 10 anni ho lavorato su varie applicazioni client desktop interne con archivi dati di SQL Server. Raramente ho avviato questi progetti - la maggior parte sono lavori di acquisizione.

Una cosa che sembrava costante ovunque era che c'era un unico account utente globale di SQL Server che questa applicazione usava che gli concedeva l'autorizzazione per il database comune, e sì in alcune situazioni ingenue usava l'account utente sa , che io in genere ho cercato di correggere quando possibile.

Non è possibile nascondere in modo efficace questo nome utente e password utilizzati dall'applicazione per accedere al database. Solitamente sono memorizzati in un file ini o config , o eventualmente inseriti nell'eseguibile stesso. In tutti i casi, sono visibili all'utente se fanno un po 'di scavo. In un caso abbiamo effettivamente utilizzato un file config ma lo abbiamo crittografato, ma ovviamente la chiave di crittografia doveva essere archiviata nell'eseguibile (non eravamo ingenui con le limitazioni di questo, ma effettivamente ha impedito alle persone di frugare chi sono stati abbastanza esperti da cercare in config file).

Tutti questi sistemi avevano un sistema di autenticazione utente integrato nell'applicazione, ma naturalmente erano tutti gestiti attraverso l'applicazione stessa, il che significa che le informazioni dell'utente erano memorizzate nel database. L'applicazione ha limitato le cose che potresti fare in base al tuo livello di accesso, ma è tutto di tipo moot se puoi semplicemente collegarti al database ed eseguire query ad-hoc.

Sono interessato a sapere quali altri sistemi fanno per aggirare questo problema. Ecco le opzioni che conosco:

  1. Utilizza il meccanismo di sicurezza di SQL Server per mantenere un elenco di utenti e ruoli e fare in modo che l'applicazione desktop aggiunga e rimuovi utenti tramite query T-SQL.
  2. Invece di connettersi direttamente al database, creare una sorta di servizio Web che gira sul server e inserire la logica di autenticazione. Fai in modo che ogni richiesta esegua la convalida della sicurezza.

Le prime opzioni sono un po 'brutte perché stai separando gli utenti dal database in modo che gli utenti non siano più entità di prima classe e non puoi farvi riferimento con le relazioni con le chiavi esterne, ecc.

Il secondo sembra solo un grosso problema di prestazioni e molto lavoro extra, inoltre non è possibile utilizzare facilmente mapper ORM come NHibernate (credo).

Qualcuno ha esperienza con questo? Best practice?

Modifica

Pensando un po 'di più, l'autenticazione di SQL Server può realmente risolvere questo problema? Ad esempio, se l'utente deve essere in grado di inserire e aggiornare i record della scheda attività in modo da poter modificare la scheda attività, non è possibile che SQL Server impedisca l'accesso ad altre righe nella tabella dei dettagli della scheda attività, il che significa che è possibile leggere e scrivere altro timesheets delle persone.

    
posta Scott Whitlock 28.05.2012 - 19:37
fonte

7 risposte

9

Temo che l'aggiunta di un livello di servizio Web sia probabilmente la soluzione corretta al tuo problema.

Separare il client dall'implementazione del database sottostante probabilmente ti aiuterà anche a lungo termine.

L'aggiunta di un livello di servizio Web non deve necessariamente danneggiare le prestazioni ...

Infatti, con un'API appropriata, un servizio Web può effettivamente migliorare le prestazioni, raggruppando più query di database all'interno della LAN del data center, piuttosto che richiedere più round trip sulla WAN.

Ovviamente un livello di servizio Web può spesso essere ridimensionato orizzontalmente e aggiungere una cache appropriata alle query del database, forse persino un meccanismo di notifica delle modifiche.

Un livello server aggiunge sicurezza che non è possibile garantire con app in esecuzione su un client remoto. Tutto ciò che viene eseguito su un client può essere "hackerato" e non dovrebbe essere considerato in alcun modo attendibile. Dovresti solo inserire la logica di presentazione nel client e ospitare qualsiasi cosa importante sull'hardware di cui hai il completo controllo.

Non conosco le tue app, ma le mie app web sono naturalmente suddivise in più livelli, con il codice di presentazione separato dal livello di persistenza da almeno un livello di business logic che tiene separati i due. Trovo che questo renda molto più facile ragionare sulla mia app e molto più veloce nell'aggiungere o modificare funzionalità. Se i livelli sono separati, è relativamente facile mantenere il livello di presentazione nel client e il resto su un server sotto il mio controllo.

Quindi, mentre puoi risolvere i tuoi problemi senza introdurre un livello di "servizio web", nel momento in cui hai scritto tutte le stored procedure (o equivalenti) necessarie per riempire i buchi nell'implementazione standard della sicurezza del database, probabilmente sarai meglio scrivere su un'applicazione lato server per cui è possibile scrivere i test di unità appropriati.

    
risposta data 28.05.2012 - 20:10
fonte
5

Come per la risposta di jmoreno, puoi negare a un utente l'accesso a tutto tranne le autorizzazioni EXECUTE sulle stored procedure, quindi sfruttare il concatenamento della proprietà per fare in modo che la stored procedure esegua le operazioni richieste sulle tabelle.

Vedi qui per i dettagli link

Quando l'utente inserisce il suo nome utente / password lato client, li memorizzo e inviano come parametri ad ogni chiamata di procedura memorizzata. È quindi possibile verificarli rispetto ai valori memorizzati in una tabella prima di eseguire l'operazione desiderata.

Sicuramente non è l'ultima parola in sicurezza, ma potrebbe essere necessaria se i PC hanno accessi generici, limitando la possibilità di utilizzare i gruppi di annunci per autorizzazioni o se si dispone di un accesso limitato alla stessa.

    
risposta data 20.02.2015 - 10:28
fonte
2

Un approccio consiste nell'utilizzare i gruppi di annunci e le procedure memorizzate per limitare ciò che l'utente può fare, ad esempio il DB del time sheet, potrebbe consentire l'inserimento, l'aggiornamento e l'eliminazione delle ore degli utenti, ma non consentire l'aggiornamento delle ore degli altri. L'ID dell'utente verrebbe fornito dal motore DB, l'utente non avrebbe accesso diretto alle tabelle DB, solo a SP che eseguiva le query in base all'ID di accesso.

Naturalmente questo non è sempre fattibile, ma può esserlo. L'approccio migliore dipenderà dalle tue esigenze e risorse.

    
risposta data 28.05.2012 - 22:32
fonte
1

Ciò a cui fai riferimento come "servizio web" si chiama architettura a più livelli . Generalmente è la strada da percorrere nei casi in cui sono probabili problemi di sicurezza o di configurazione (ad esempio, la distribuzione di un'applicazione in molti uffici). Tuttavia, non deve essere "basato sul web". Molti lavorano con altri protocolli.

Si crea un server applicazioni che funge da intermediario tra il client e il database (e altre risorse). Il server delle applicazioni gestisce l'autenticazione basata sull'applicazione ed esegue azioni per conto del cliente. In effetti, idealmente non staresti facendo alcun SQL nel tuo client - piuttosto chiami metodi sul server dell'app. Il server delle applicazioni gestirà tutta la manipolazione dei dati.

C'è un certo numero di vantaggi nell'approccio. Non è necessario configurare connessioni e driver del database sui client. Non memorizzi utenti di database, password, & server. La configurazione dei client non è nemmeno necessaria, basta indicarli nel codice all'URL o all'indirizzo corretto. Inoltre, con la 'logica' nel server delle applicazioni, non devi ripeterti quando sviluppi altre applicazioni: lo stesso server delle app può essere riutilizzato da diversi tipi di client.

    
risposta data 28.05.2012 - 22:29
fonte
1

La tecnologia è cambiata un po '. Se si autentica ciascun utente nel database stesso e si utilizzano i ruoli del database, è ora possibile utilizzare la cosiddetta vista aggiornabile per risolvere questo problema, almeno in SQL Server.

Ecco come potrebbe apparire una visualizzazione aggiornabile per una tabella denominata SomeTable in cui ogni riga in quella tabella è collegata a un dipendente. Il dipendente dovrebbe essere in grado di vedere le righe collegate a loro, e i membri del ruolo HR dovrebbero essere in grado di vedere tutte le righe, ad esempio:

CREATE VIEW [dbo].[vwSomeTable]
AS
    SELECT SomeTable.*
    FROM SomeTable
        INNER JOIN Employee ON SomeTable.Employee_ID = Employee.Employee_ID
    WHERE Employee.Username = USER_NAME() OR IS_MEMBER('HR_Role')=1

GO

Quindi quello che fai è dare permessi di lettura (e possibilmente scrivere) nella vista ( vwSomeTable ) a tutti gli utenti, e non dare permessi sulla tabella ( SomeTable ).

Puoi testarlo in questo modo:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... che dovrebbe solo restituire la / e loro / e riga / e. Oppure:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... che restituirà tutte le righe. Tieni presente che avrai bisogno delle autorizzazioni di esecuzione come (impersonificazione) per eseguire questo test.

Le viste sono aggiornabili, quindi anche l'utente normale può farlo, purché la riga sia collegata alla loro Employee riga:

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'
    
risposta data 24.05.2018 - 19:13
fonte
0

L'utilizzo dell'autenticazione basata su certificato è il modo "corretto" per implementare un account sql condiviso. L'obiettivo è eliminare l'uso della password per questo tipo di cose.

Aggiornamento:

Suppongo che abbia frainteso la domanda. Ho pensato che avesse a che fare con il tentativo di trovare un'alternativa a mettere un nome utente e una password db sia in una configurazione dell'applicazione, sia nel backup dell'applicazione stessa.

È possibile eliminare il problema della gestione delle password nelle applicazioni utilizzando invece i certificati lato client. Il certificato stesso non è abbastanza, devi avere un sistema di distribuzione e gestione capace di operazioni come la revoca di certificati.

Riferimento: link

    
risposta data 28.05.2012 - 22:25
fonte
0

Creando una nuova soluzione per la sicurezza del desktop, abbiamo optato per la soluzione del servizio web che tenterò di descrivere qui sotto.

Compiliamo gli eseguibili dell'applicazione desktop in un ambiente separato dagli sviluppatori. E calcolare un HASH da quell'eseguibile che è registrato nel database.

Un servizio Web che fornisce tutte le informazioni necessarie per l'esecuzione dell'applicazione, la password del DB, le informazioni sulla stringa di connessione, le autorizzazioni dell'utente, ecc ...

utilizziamo un singolo accesso DB per applicazione e registriamo i dettagli dell'utente nel database nelle variabili di sessione per poter controllare i record.

Una DLL gestisce tutte le comunicazioni dall'applicazione desktop al servizio web, che è accessibile solo con una build di token nella DLL.

Per poter ottenere la password del DB dell'applicazione dal servizio Web, la DLL calcola i chiamanti DLL HASH in runtime e passa come parametro al servizio Web che convalida il token DLL e il runtime eseguibile ha calcolato HASH su quello registrato quando è stato distribuito (l'applicazione è disponibile solo in una singola installazione condivisa in rete).

In questo modo siamo caduti, è una buona soluzione per il problema di sicurezza in cui siamo più interessati e siamo ben consapevoli di alcuni difetti di progettazione. Stiamo quasi finendo questa implementazione e finora siamo soddisfatti dei risultati.

Modifica: È possibile sostituire l'idea di hash utilizzando le firme digitali e i certificati X.509.

    
risposta data 15.02.2014 - 19:21
fonte

Leggi altre domande sui tag