Prolongement de l'emprunt d'identité au niveau de la base de données à l'aide de EXECUTE AS
SQL Server permet d'emprunter l'identité d'une autre entité de sécurité, soit explicitement en utilisant l'instruction EXECUTE AS autonome, soit implicitement en utilisant la clause EXECUTE AS sur des modules. L'instruction EXECUTE AS autonome peut être utilisée pour emprunter l'identité d'entités de sécurité, ou de noms de connexion, au niveau du serveur, en utilisant l'instruction EXECUTE AS LOGIN. L'instruction EXECUTE AS autonome peut aussi être utilisée pour emprunter l'identité d'entités de sécurité au niveau de la base de données, ou des utilisateurs, en utilisant l'instruction EXECUTE AS USER.
Les emprunts d'identité implicites qui sont effectués par le biais de la clause EXECUTE AS sur des modules permettent de se faire passer pour l'utilisateur ou le nom de connexion spécifiés au niveau du serveur ou de la base de données. Cet emprunt d'identité varie selon que le module se situe au niveau de la base de données, par exemple une procédure stockée ou une fonction, ou au niveau du serveur, par exemple un déclencheur de niveau serveur.
Présentation de l'étendue d'un emprunt d'identité
Lors de l'emprunt d'identité d'une entité de sécurité à l'aide de l'instruction EXECUTE AS LOGIN, ou au sein d'un module au niveau d'un serveur à l'aide de la clause EXECUTE AS, cet emprunt d'identité concerne l'ensemble du serveur. Autrement dit, suite au changement de contexte, toute ressource située dans le serveur pour lequel le nom de connexion emprunté a des autorisations devient accessible.
Toutefois, lors de l'emprunt d'identité d'une entité de sécurité à l'aide de l'instruction EXECUTE AS USER, ou au sein d'un module dont l'étendue concerne la base de données à l'aide de la clause EXECUTE AS, cet emprunt d'identité se limite par défaut à la base de données. Cela signifie que les références à des objets situés au-delà de la portée de la base de données retourneront une erreur. Pour vous aider à comprendre le mécanisme de ce comportement par défaut, étudiez le scénario suivant.
Il se peut que le propriétaire d'une base de données, bien qu'ayant les autorisations complètes au sein de cette base de données, n'en ait aucune en dehors de ladite base de données. Par conséquent, SQL Server n'autorise pas le propriétaire de la base de données à emprunter l'identité, ni à accorder ce droit à un tiers, d'un autre utilisateur afin d'accéder aux ressources situées au-delà de la portée de ses autorisations actuelles.
Prenons par exemple deux bases de données dans un environnement d'hébergement, chacune appartenant à un propriétaire différent. Database1 est la propriété de Bob et Database2 celle de Fred. Ni Bob ni Fred ne souhaite que l'autre accède aux ressources de sa base de données. En tant que propriétaire de Database1, Bob peut créer un utilisateur pour Fred dans cette base de données, et comme il dispose de toutes les autorisations dans Database 1, Bob peut également prendre l'identité de l'utilisateur Fred. Toutefois, en raison des restrictions de sécurité imposées par SQL Server, Bob ne peut pas accéder à la base de données de Fred dans le contexte d'emprunt d'identité. Sans ces restrictions par défaut, Bob pourrait accéder aux données de Fred à son insu. C'est pour cette raison que la portée des emprunts d'identité au niveau de la base de données se limite par défaut à la base de données.
Toutefois, dans certains scénarios il peut être utile d'étendre sélectivement l'étendue de l'emprunt d'identité au-delà de la base de données. Cela peut être le cas par exemple pour une application qui utilise deux bases de données et qui a besoin d'accéder à l'une d'elle à partir de l'autre.
Pensez à la situation dans laquelle une application de marketing appelle une procédure stockée appelée GetSalesProjections dans la base de données Marketing, alors que cette procédure stockée contient une définition de changement de contexte d'exécution. La procédure stockée lance des appels dans la base de données Sales pour récupérer des informations de vente à partir de la table SalesStats. Par défaut, ce scénario ne fonctionnera pas, parce qu'un contexte d'exécution établi à l'intérieur d'une base de données n'est pas valide en dehors de cette base de données. Toutefois, les développeurs de l'application de marketing ne veulent pas que les utilisateurs de cette application aient un accès direct à la base de données Sales ou disposent d'autorisations sur des objets de cette base. La solution idéale serait d'utiliser la clause EXECUTE AS dans la procédure stockée pour emprunter l'identité d'un utilisateur qui dispose des autorisations nécessaires dans la base de données Sales. Toutefois, les restrictions par défaut actuellement en place l'interdisent. Aussi, la question est de savoir comment les développeurs peuvent résoudre ce problème.
Dans SQL Server, vous pouvez étendre sélectivement l'étendue de l'emprunt d'identité dans une base de données en établissant un modèle d'approbation entre les deux bases de données. Cependant, avant de décrire ce modèle d'approbation et d'indiquer comment la portée de l'emprunt d'identité peut être étendue de manière sélective, vous devez avoir compris les principes de l'authentification et le rôle des authentificateurs dans SQL Server.
Présentation des authentificateurs
L'authentification est le procédé selon lequel une entité de sécurité particulière établit et prouve son identité à un système. Un authentificateur est une entité qui authentifie, ou répond de, l'authenticité d'une entité de sécurité particulière. Par exemple, lorsqu'une connexion est établie à SQL Server, le nom de connexion établi est authentifié par l'instance de SQL Server.
Prenons le cas d'un utilisateur qui change explicitement de contexte au niveau du serveur à l'aide de l'instruction EXECUTE AS LOGIN. Cela nécessite des autorisations d'emprunt d'identité au niveau du serveur. Ces autorisations permettent à leur bénéficiaire, l'appelant de l'instruction EXECUTE AS LOGIN, de prendre l'identité du nom de connexion spécifié n'importe où dans l'instance de SQL Server. En effet, l'instruction permet à l'appelant de simuler l'acte d'ouverture de session sous le nom de connexion emprunté. Le propriétaire des autorisations au niveau du serveur est le sysadmin qui possède l'instance de SQL Server. En cas d'emprunt d'identité au niveau du serveur, l'authentificateur est le sysadmin ou l'instance de SQL Server.
Il faut toutefois envisager les cas où le contexte est établi à cause d'une instruction EXECUTE AS USER ou d'une clause EXECUTE AS sur un module dont la portée se limite à la base de données. La plupart du temps, les autorisations d'emprunt d'identité au sein de la base de données sont vérifiées. Par défaut, les autorisations IMPERSONATE concernent les utilisateurs de la base de données elle-même, dont le propriétaire est dbo. Par ailleurs, l'authentificateur de ces emprunts d'identité est le propriétaire de la base de données. De plus, c'est le propriétaire de la base de données qui, dans les faits, établit l'identité de l'utilisateur dont l'identité a été empruntée et répond de son authenticité. Comme le propriétaire de la base de données la possède intégralement, le contexte représenté est considéré comme étant authentique n'importe où au sein de cette base de données spécifique. Toutefois, en dehors de cette base de données le contexte représenté n'est pas valide.
Utilisation des authentificateurs
Les authentificateurs permettent de déterminer si un contexte établi est valide dans une étendue particulière. L'authentificateur est souvent l'administrateur système (SA) ou l'instance de SQL Server, ou avec les bases de données, le dbo. Concrètement il est le propriétaire de l'étendue dans laquelle le contexte d'un utilisateur ou d'un nom de connexion particulier est établi. Ces informations sur l'authentificateur sont capturées dans les informations de jeton gérées pour le nom de connexion et l'utilisateur ; elles sont accessibles par les vues sys.user_token et sys.login_token. Pour plus d'informations, consultez Présentation du contexte d'exécution.
Notes
Si aucune information sur l'authentificateur n'est retournée dans la vue du jeton, l'authentificateur est l'instance de SQL Server. Cela est vrai s'il n'y a pas de changement de contexte ou si l'emprunt d'identité s'effectue au niveau du serveur.
Un contexte d'exécution qui a comme authentificateur le propriétaire d'une étendue est valide dans toute cette étendue. En effet, le propriétaire d'une étendue, par exemple une base de données, est implicitement approuvé par toutes les entités figurant dans cette étendue. Le contexte est également valide dans toutes les autres étendues, par exemple d'autres bases de données ou l'instance de SQL Server, où l'authentificateur est approuvé. Par conséquent, la validité du contexte de l'utilisateur représenté en dehors de l'étendue de la base de données varie selon que l'authentificateur de ce contexte est approuvé ou non dans l'étendue cible. Cette approbation est établie en accordant à l'authentificateur l'autorisation AUTHENTICATE si l'étendue cible est une autre base de données ou l'autorisation AUTHENTICATE SERVER si l'étendue cible est une instance de SQL Server.
Prolongement de l'étendue de l'emprunt d'identité
Pour étendre la portée d'un emprunt d'identité d'une base de données à une étendue cible, par exemple une autre base de données ou l'instance de SQL Server, les conditions suivantes doivent être respectées.
L'authentificateur doit être approuvé dans l'étendue cible.
La base de données source doit être identifiée comme étant digne de confiance.
Approbation de l'authentificateur
L'illustration suivante, qui utilise les exemples de bases de données Sales et Marketing précédentes, montre la procédure stockée GetSalesProjections dans la base de données Marketing accédant aux données de la table SalesStats dans la base de données Sales. La procédure stockée contient la clause EXECUTE AS USER MarketingExec. Le propriétaire de la base de données Sales est SalesDBO et celui de la base de données Marketing est MarketingDBO.
Lorsqu'un utilisateur appelle la procédure stockée GetSalesProjections, la clause EXECUTE AS change implicitement le contexte d'exécution de cette procédure pour passer de l'utilisateur appelant à l'utilisateur MarketingExec. L'authentificateur de ce contexte est MarketingDBO, le propriétaire de la base de données Marketing. Par défaut, cette procédure peut accéder à toutes les ressources de la base de données Marketing auxquelles l'utilisateur MarketingExec a le droit d'accéder. Toutefois, pour accéder à une table de la base de données Sales, la base de données Sales doit approuver l'authentificateur MarketingDBO.
Vous pouvez pour cela créer dans la base de données Sales un utilisateur appelé MarketingDBO, mappé au nom de connexion MarketingDBO, puis accorder à cet utilisateur l'autorisation AUTHENTICATE sur la base de données Sales. Il en résulte que tout contexte d'exécution dont l'authentificateur bénéficie de cette autorisation est valide dans la base de données. Comme l'authentificateur MarketingDBO a l'autorisation AUTHENTICATE dans la base de données Sales, le contexte de l'utilisateur MarketingExec établi par la clause EXECUTE AS dans la procédure stockée GetSalesProjections de la base de données Marketing est approuvé dans la base de données Sales.
Cet exemple illustre le prolongement de l'étendue de l'emprunt d'identité pour permettre d'accéder à un objet d'une base de données externe, mais il est possible également de prolonger l'étendue de l'emprunt d'identité à l'instance de SQL Server. Par exemple, si la procédure consistait à créer un nom de connexion, ce qui relève d'une opération au niveau du serveur nécessitant une autorisation à cette échelle, l'autorisation AUTHENTICATE SERVER devrait être accordée à l'authentificateur du contexte. Cela signifie que tout contexte bénéficiant de l'autorisation AUTHENTICATE SERVER en tant qu'authentificateur est approuvé dans toute l'instance de SQL Server**,** comme si le contexte était connecté directement à l'instance de SQL Server.
Approbation de la base de données
Dans SQL Server, le modèle d'approbation va encore plus loin afin de renforcer la sécurité et la granularité lors du prolongement de l'étendue de l'emprunt d'identité au niveau de la base de données. Vous pouvez utiliser l'autorisation AUTHENTICATE pour permettre à l'étendue cible d'approuver l'authentificateur d'un contexte, mais vous pouvez aussi déterminer si l'instance de SQL Server approuve la base de données source et son contenu.
Pour illustrer ceci, supposons que l'entité de sécurité MarketingDBO possède une autre base de données, appelée Conference. Supposons également que MarketingDBO veuille que les contextes d'exécution qui sont spécifiés dans la base de données Marketing aient accès aux ressources de la base de données Sales. Toutefois, il ne souhaite pas que les contextes qui sont établis dans la base de données Conference aient accès à la base de données Sales.
Pour cela, la base de données qui contient le module où est utilisé un contexte d'emprunt d'identité pour accéder aux ressources situées en dehors de la base de données doit être identifiée comme étant digne de confiance. La propriété TRUSTWORTHY indique si l'instance de SQL Server approuve la base de données et son contenu. La propriété TRUSTWORTHY a deux fonctions :
Elle réduit les risques induits par les bases de données qui sont attachées à l'instance de SQL Server et qui sont susceptibles de contenir des modules malveillants définis pour s'exécuter dans le contexte d'un utilisateur bénéficiant d'un niveau de privilège élevé.
Il faut à cet effet s'assurer que les bases de données attachées ne sont pas identifiées par défaut comme étant dignes de confiance. Il faut également vérifier que l'accès aux ressources en dehors de la base de données par le biais de modules potentiellement malveillants nécessite que la base de données soit identifiée comme étant signe de confiance. La définition de la propriété TRUSTWORTHY sur une base de données ne peut être effectuée que par les membres du rôle serveur fixe sysadmin.
Elle permet à l'administrateur de l'instance de SQL Server de déterminer parmi les bases de données lesquelles doivent être autorisées à accéder à des ressources externes et lesquelles ne le peuvent pas, lorsqu'elles ont le même propriétaire et que celui-ci est approuvé en tant qu'authentificateur dans une certaine étendue.
La propriété TRUSTWORTHY permet de définir précisément ce comportement. Prenons par exemple un cas où les contextes représentés depuis une base de données, Database 1, doivent être approuvés alors que les contextes d'une autre base de données, Database 2, ne doivent pas être approuvés, alors qu'elles ont toutes les deux le même propriétaire qui est approuvé en tant qu'authentificateur dans l'étendue cible. La propriété TRUSTWORTHY peut être activée (ON) pour database1 et désactivée (OFF) pour database2 ; de cette façon, les modules de Database 2 ne peuvent pas accéder aux ressources qui se trouvent en dehors de cette base de données.
L'illustration suivante présente l'utilisation de la propriété de base de données TRUSTWORTHY pour contrôler l'accès aux ressources situées en dehors de l'étendue de la base de données source. MarketingDBO bénéficie des autorisations AUTHENTICATE dans la base de données Sales et il est le propriétaire des bases de données Marketing et Conference. La procédure stockée GetSalesProjections de la base de données Marketing peut accéder sans problème à la base de données Sales car elle répond aux deux critères de sécurité : l'authentificateur, MarketingDBO, est approuvé dans l'étendue cible et la base de données source, Marketing, est digne de confiance. Les tentatives d'accès à la base de données Sales à partir de la base de données Conference sont refusées, parce qu'une seule condition est respectée : l'authentificateur, MarketingDBO, est approuvé dans l'étendue cible.
À chaque tentative d'accès à une ressource située en dehors de l'étendue de la base de données par le biais d'un contexte représenté, l'instance de SQL Server vérifie que la base de données d'où provient la demande est digne de confiance et que l'authentificateur est approuvé.
Certificats et clés asymétriques comme authentificateurs
Un contexte d'emprunt d'identité établi au sein d'une base de données peut être prolongé pour permettre l'accès à des ressources en dehors de l'étendue de la base de données, en utilisant le propriétaire de la base de données comme authentificateur. Pour cela, le propriétaire de la base de données doit être approuvé par la ressource externe et la base de données elle-même doit par ailleurs être digne de confiance. Toutefois, cette approche implique que quand un propriétaire de base de données approuvé bénéficie des autorisations AUTHENTICATE ou AUTHENTICATE SERVER dans l'étendue cible et que la base de données appelante est digne de confiance, tout contexte représenté établi dans cette base de données est valide dans l'étendue cible qui approuve le propriétaire de la base de données.
Un niveau d'approbation plus granulaire peut être nécessaire. Supposons que les besoins de l'entreprise dictent l'approbation de quelques modules seulement dans la base de données source en utilisant la clause EXECUTE AS pour accéder à la ressource cible, mais pas l'approbation de la base de données source complète. Supposons par exemple que SalesDBO souhaite garantir que seule la procédure stockée GetSalesProjections puisse accéder à la table SalesStats en tant qu'utilisateur MarketingExec, mais qu'il ne souhaite pas que tout le monde dans la base de données Marketing bénéficiant d'autorisations d'emprunt d'identité sur MarketingExec puisse accéder aux ressources de la base de données Sales. L'approbation de MarketingDBO et la définition de la base de données Marketing comme étant digne de confiance ne remplissent pas cette tâche. Pour procurer un plus haut niveau de granularité pour remplir cette condition, le modèle d'approbation permet d'utiliser des certificats ou des clés asymétriques comme authentificateurs. Cela tire parti d'une technique dite de signature. Pour plus d'informations sur les signatures, consultez ADD SIGNATURE (Transact-SQL).
Utilisation des signatures
Les signatures sur un module vérifient que le code à l'intérieur d'un module ne peut être modifié que par une personne ayant accès à la clé privée qui a été utilisée pour signer ledit module. Selon les garanties des signatures, vous pouvez approuver le certificat ou la clé asymétrique spécifiés dans la signature. Plus précisément, vous pouvez approuver le propriétaire du certificat ou de la clé asymétrique, plutôt que juste le propriétaire de la base de données.
L'approbation du module signé s'effectue en accordant l'autorisation AUTHENTICATE ou AUTHENTICATE SERVER à l'utilisateur de l'étendue cible qui correspond au certificat ou à la clé asymétrique.
Avec cette approche, un contexte d'exécution établi dans un module signé avec un certificat approuvé est valide dans l'étendue cible dans laquelle le certificat est approuvé.
Supposons par exemple que la procédure GetSalesProjections soit signée à l'aide d'un certificat appelé C1. Ce certificat C1 doit être présent dans la base de données Sales et un utilisateur, par exemple CertUser1, doit être mappé au certificat C1. CertUser1 reçoit ensuite les autorisations AUTHENTICATE dans la base de données Sales.
Lors de l'appel de la procédure, sa signature est vérifiée pour s'assurer qu'elle n'a pas été falsifiée. Si la signature est vérifiée, le contexte établi par la clause EXECUTE AS dans le module a le certificat C1 comme authentificateur. Si elle n'est pas vérifiée, l'authentificateur n'est pas ajouté au jeton et la tentative d'accès à la ressource externe échoue.
L'illustration suivante présente l'utilisation d'un module signé pour contrôler l'accès aux ressources situées en dehors de l'étendue de la base de données source. La procédure GetSalesProjections de la base de données Marketing est signée à l'aide d'un certificat appelé C1. Ce certificat C1 est présent dans la base de données Sales et l'utilisateur CertUser est mappé au certificat. CertUser1 reçoit les autorisations AUTHENTICATE dans la base de données Sales.
L'approbation sur cet authentificateur est vérifiée de la même façon que l'approbation est vérifiée lorsque le propriétaire de la base de données est l'authentificateur. C'est-à-dire qu'elle est vérifiée par le biais du contrôle de l'autorisation AUTHENTICATE SERVER ou AUTHENTICATE. Cependant, étant donné que l'approbation est établie à un niveau de granularité et que le module ne peut pas être modifié sans modifier la signature, il n'est pas nécessaire de vérifier la propriété TRUSTWORTHY sur la base de données.
Cela réduit les risques induits par les bases de données attachées contenant du code malveillant. Il faudrait que le pirate signe le module avec la clé privée qui correspond au certificat déjà approuvé. Mais le pirate n'a pas accès à cette clé. De plus, si un module approuvé existant est modifié ou si un nouveau est créé, ce module n'aura pas de signature approuvée valide.
Pour plus d'informations, consultez Signature de module (moteur de base de données).
Règles de prolongement de l'étendue de l'emprunt d'identité au niveau de la base de données
Pour résumer, l'étendue de l'emprunt d'identité d'un contexte établi dans une base de données peut être prolongée à d'autres étendues si et seulement si la condition suivante est remplie :
L'authentificateur, que ce soit le propriétaire de la base de données, ou un certificat ou une clé asymétrique utilisés pour signer le module, doit être approuvé dans l'étendue cible. Pour cela, vous pouvez accorder l'autorisation AUTHENTICATE ou AUTHENTICATE SERVER à l'entité de sécurité qui correspond au propriétaire de la base de données, au certificat ou à la clé asymétrique.
Si l'authentificateur est le propriétaire de la base de données, la base de données source doit être identifiée comme étant digne de confiance. Pour cela, vous pouvez affecter à la propriété TRUSTWORTHY la valeur ON pour la base de données.
Sélection du mécanisme d'approbation selon vos besoins
Chaque approche, propriétaire de la base de données ou signature, présente des avantages et des inconvénients. Le mécanisme le mieux adapté à vos besoins dépend de vos exigences professionnelles et de votre environnement de travail.
Propriétaire de base de données
Cette approche d'établissement de l'approbation présente les avantages et les inconvénients suivants :
Il n'est pas nécessaire de connaître les concepts de la cryptographie, dont les certificats ou les signatures.
La granularité est moins importante qu'avec l'approche utilisant la signature.
L'attachement d'une base de données à une instance de SQL Server définit la propriété TRUSTWORTHY de la base de données comme étant OFF. Les modules approuvés par le propriétaire de la base de données ne seront valides que lorsque l'administrateur système aura défini explicitement la propriété TRUSTWORTHY comme étant ON. Cela implique que l'administrateur risque de devoir intervenir, avant que la base de données attachée puisse fonctionner comme vous le souhaitez et accéder à d'autres bases de données.
Signature
Cette approche d'établissement de l'approbation présente les avantages et les inconvénients suivants :
Elle peut fournir un niveau d'approbation granulaire, mais elle ne s'applique qu'aux changements de contexte effectués au sein de modules signés.
La signature ne peut pas être appliquée à des changements de contexte qui sont établis par le biais d'instructions autonomes EXECUTE AS USER et EXECUTE AS LOGIN. Ces instructions nécessitent l'approche du propriétaire de la base de données pour prolonger l'étendue de l'approbation.
Le fournisseur ou le développeur de l'application peut signer le module avec une clé privée, mais il doit la supprimer avant de livrer les modules ou la base de données. Cette solution est possible parce que les clés privées ne sont utilisées que pour signer les modules. Pour la vérification de la signature, les clés publiques associées au module suffisent.
L'attachement d'une base de données n'a aucun effet sur les modules qui sont approuvés en raison de leurs signatures. Il n'y a pas d'autres conditions requises.
Voir aussi