Sécurité et comptes génériques
Le titre de ce post peut paraître contradictoire, en effet l’utilisation des comptes génériques dans votre domaine doit être limitée au strict minimum. L’accès aux ressources devant être nominatif l’utilisation de ce genre de comptes est à éviter. Cependant pour des raisons politiques et/ou historiques un service de votre entreprise peut être amené à utiliser ce type de compte pour l’accès à une application ou à certaines machines. Ce compte étant utilisé par plusieurs personnes, le mot de passe de ce compte devient très rapidement connu au sein des différents services et peut vite servir à autre chose que son but initial. Si l’on impose une stratégie de changement de mot de passe classique sur ce compte, alors le jour de l’expiration du mot de passe, une personne effectuera la modification et ne pensera pas forcément à prévenir toutes les personnes en droit de se servir de ce compte. La plupart du temps ce genre de compte est donc configuré avec le flag “mot de passe n’expire jamais”, ce qui est une faille de sécurité évidente. Nous allons donc montrer dans cet article comment mettre en place un système automatique de changement de mot de passe pour ces comptes génériques et comment avertir les utilisateurs de ce changement de mot de passe.
Nous allons donc mettre en place une tache planifiée, lancée avec un compte de service ayant les droits de modifier le mot de passe du compte, qui effectuera le renouvellement de password et avertira les utilisateurs par un moyen que nous définirons plus tard. Cette tâche sera lancée mensuellement, si nous désirons changer le mot de passe du compte tous les mois.
Nous devons tout d’abord effectuer quelques modifications sur le compte générique à traiter:
- Laisser le flag “passsword n’expire jamais”: le mot de passe sera changé via notre tâche planifiée et non via le changement de mot de passe classique imposé par notre stratégie de mot de passe du domaine sous Windows 2003 ou éventuellement vos “Fine Grained Password Policies” sous Windows 2008.
- Mettre le flag “L’utilisateur de ne peut pas changer de mot de passe”: De cette manière le mot de passe ne sera changé que par le compte de service lançant la tâche planifié et les administrateurs AD.
- Permettre à votre compte de service de changer le mot de passe du compte générique, si celui-ci ne possède pas déjà les droits par défaut. Inutile si par exemple le compte de service est administrateur du domaine, cependant cela est à éviter si possible.
Voir les captures d’écran suivantes, s-pwd-supervision est le compte de service qui effectue le changement de mot de passe et g-generic notre compte générique.
Il nous faut ensuite créer notre tache planifiée: Le script changepass.vbs sera lancé tous les premier du mois à 5h00 avec le compte de service s-pwd-supervision:
Nous allons détailler ce que nous mettons dans notre script changepass.vbs, tout d’abord il faut générer un mot de passe aléatoire et attribuer le mot de passe à notre compte g-generic. La fonction de génération de mot de passe aléatoire a été prise sur cette page,l’auteur est Mark D. MacLachlan, vous pouvez en trouver d’autres sur la toile. Adaptez ce script à vos besoins en changeant la valeur de DNg-generic qui est le Distinguished Name de votre compte générique. La fonction generatePassword est paramétrée pour générer un mot de passe de 8 caractères, vous pouvez changer ce paramètre, du moment qu’il respecte la stratégie de mot de passe mise en place.
DNg-generic = "CN=g-generic,OU=users,DC=ldap389,DC=info" pwd = generatePassword(8) Set objUser = GetObject("LDAP://"&DNg-generic) objUser.SetPassword pwd Function generatePassword(PASSWORD_LENGTH) ' COPY OF RandomPasswordGenerator.vbs ' ' AUTHOR: Mark D. MacLachlan , The Spider's Parlor ' URL: http://www.thespidersparlor.com Dim NUMLOWER, NUMUPPER, LOWERBOUND, UPPERBOUND, LOWERBOUND1, UPPERBOUND1, SYMLOWER, SYMUPPER Dim newPassword, count, pwd Dim pCheckComplex, pCheckComplexUp, pCheckComplexLow, pCheckComplexNum, pCheckComplexSym, pCheckAnswer NUMLOWER = 48 ' 48 = 0 NUMUPPER = 57 ' 57 = 9 LOWERBOUND = 65 ' 65 = A UPPERBOUND = 90 ' 90 = Z LOWERBOUND1 = 97 ' 97 = a UPPERBOUND1 = 122 ' 122 = z SYMLOWER = 33 ' 33 = !a SYMUPPER = 46 ' 46 = . pCheckComplexUp = 0 ' used later to check number of character types in password pCheckComplexLow = 0 ' used later to check number of character types in password pCheckComplexNum = 0 ' used later to check number of character types in password pCheckComplexSym = 0 ' used later to check number of character types in password ' initialize the random number generator Randomize() newPassword = "" count = 0 DO UNTIL count = PASSWORD_LENGTH ' generate a num between 2 and 10 ' if num <= 2 create a symbol If Int( ( 10 - 2 + 1 ) * Rnd + 2 ) <= 2 Then pwd = Int( ( SYMUPPER - SYMLOWER + 1 ) * Rnd + SYMLOWER ) ' if num is between 3 and 5 create a lowercase Elseif Int( ( 10 - 2 + 1 ) * Rnd + 2 ) > 2 And Int( ( 10 - 2 + 1 ) * Rnd + 2 ) <= 5 Then pwd = Int( ( UPPERBOUND1 - LOWERBOUND1 + 1 ) * Rnd + LOWERBOUND1 ) ' if num is 6 or 7 generate an uppercase Elseif Int( ( 10 - 2 + 1 ) * Rnd + 2 ) > 5 And Int( ( 10 - 2 + 1 ) * Rnd + 2 ) <= 7 Then pwd = Int( ( UPPERBOUND - LOWERBOUND + 1 ) * Rnd + LOWERBOUND ) Else pwd = Int( ( NUMUPPER - NUMLOWER + 1 ) * Rnd + NUMLOWER ) End If newPassword = newPassword + Chr( pwd ) count = count + 1 'Check to make sure that a proper mix of characters has been created. If not discard the password. If count = (PASSWORD_LENGTH) Then For pCheckComplex = 1 To PASSWORD_LENGTH 'Check for uppercase If Asc(Mid(newPassword,pCheckComplex,1)) >64 And Asc(Mid(newPassword,pCheckComplex,1))< 90 Then pCheckComplexUp = 1 'Check for lowercase ElseIf Asc(Mid(newPassword,pCheckComplex,1)) >96 And Asc(Mid(newPassword,pCheckComplex,1))< 123 Then pCheckComplexLow = 1 'Check for numbers ElseIf Asc(Mid(newPassword,pCheckComplex,1)) >47 And Asc(Mid(newPassword,pCheckComplex,1))< 58 Then pCheckComplexNum = 1 'Check for symbols ElseIf Asc(Mid(newPassword,pCheckComplex,1)) >32 And Asc(Mid(newPassword,pCheckComplex,1))< 47 Then pCheckComplexSym = 1 End If Next 'Add up the number of character sets. We require 3 or 4 for a complex password. pCheckAnswer = pCheckComplexUp+pCheckComplexLow+pCheckComplexNum+pCheckComplexSym If pCheckAnswer < 3 Then newPassword = "" count = 0 End If End If Loop 'The password is good so return it generatePassword = newPassword End Function |
Maintenant il faut que notre script prévienne les utilisateurs concernés d’une manière ou d’une autre. Nous allons présenter deux méthodes:
La première est de prévenir les utilisateurs concernés par Email, pour cela il vous suffit d’utiliser Blat, Bmail ou bien directement d’appeler l’objet CDO dans votre script. Il vous suffit d’indiquer votre serveur SMTP, les destinataires et de mettre dans le corps du message le nouveau mot de passe.
La seconde est de mettre ce mot de passe à disposition sur une page Web sur un serveur IIS de votre entreprise. Une fois le password généré il sera copié dans une page Web qui se trouvera sur un répertoire de votre serveur IIS. Nous devons établir une politique de sécurité d’accès à ce répertoire, donc à cette page, en paramétrant les droits NTFS de ce dossier:
- Le compte de service pourra écrire dans ce dossier.
- Seuls les comptes utilisateurs habilités pourrons lire cette page, nous donnerons donc les droits en lecture à un groupe de comptes utilisateurs devant être au courant du changement de mot de passe. Si une personne non autorisée essaye d’accéder à la page elle aura le message d’erreur suivant:
Nous pouvons ajouter une sécurité supplémentaire sur cette page: Quand les personnes autorisées y accèdent rien ne s’affiche, l’utilisateur doit placer son curseur de souris sur un endroit particulier de la page pour que le mot de passe s’affiche, ceci grâce a la fonction Javascript OnMouseOver. Une fois votre mot de passe “pwd” généré par le script il vous suffit d’ajouter les lignes suivantes à votre code:
'PathIISHTML is the path of your HTML file on your IIS Server PathIISHTML = "IISserverShareNameFile.html" Const ForWriting = 2 Set FSO = CreateObject("Scripting.FileSystemObject") Set f3 = fso.OpenTextFile(PathIISHTML,ForWriting,1) f3.writeline("<div id='myText' style='visibility: hidden'>"&pwd&"</div>") f3.writeline("<p onMouseOver="&chr(34)&"myText.style.visibility = 'visible'"&chr(34)) f3.writeline("onMouseOut="&chr(34)&"myText.style.visibility = 'hidden'"&chr(34)&">") f3.writeline("<BR>") f3.writeline("</p>") f3.close |
Pour télécharger le script complet c’est ici:
Vous voyez qu’avec ce type de code il est très simple de générer une page HTML, cela peut vous servir dans d’autres scripts pour la présentation de rapports sous une forme un peu plus claire qu’un simple fichier texte à plat.
Une dernière remarque: Avant de mettre en place un changement de mot de passe pour un compte générique assurez vous que celui ci ne sert pas à une tâche planifiée, à un poste en autologon ou bien à un service.
This post is also available in: Anglais