CHANGER PERIODIQUEMENT LE MOT DE PASSE DU COMPTE ADMINISTRATEUR PRE-INTEGRE (BUILTIN) DE LA BASE SAM :

salut à tous

J’ai récemment travaillé sur une solution pour changer périodiquement le compte administrateur pré-défini sur des stations de travail Windows XP Pro / Windows Seven.
Le cachier des charges précisait :
– Que le mot de passe du compte administrateur pré-défini devait changer tous les 90 jours.
– Que le mot de passe devait être stocké sur un partage non accessible en lecture aux utilisateurs.
– Que le mot de passe devait respecter certaines contraintes en terme de tailles, nombre de familles de caractères (majuscules, minuscules, chiffres, caractères spéciaux).
– Prendre en charge le fait que le compte administrateur intégré changerait de nom selon la langue de l’OS ou pouvait avoir été renommé (“administrator” pour une version Windows anglaise, “administrateur” pour une version française).
La solution proposée ci dessous est basée sur deux scripts.
– ADMINISTRATORPASSWORD.CSV
– GENERATECSV.VBS

1 LE SCRIPT ADMINISTRATORPASSWORD.vbs :
1.1 PRESENTATION GENERALE :

Ce script permet de
– Générer le mot de passe selon les contraintes (nombre de majuscules, minuscules, caractères spéciaux…)
– Déterminer si cela fait plus de 90 jours que le mot de passe a été changé.
– Modifier le mot de passe sur la station de travail.
– Ecrire un fichier texte contenant le nom de la machine, le nom du compte administrateur pré-intégré et le mot de passe.

1.2 CONTRAINTES ET PROBLEMATIQUES DE LA SOLUTION :
– Tous les stations de travail doivent pouvoir accéder aux partages de fichiers de ces deux serveurs.
– Toutes les stations de travail doivent être membres d’un domaine Active Directory.
– Chaque station de travail doit pouvoir écrire le fichier texte contenant le mot de passe sans permettre aux utilisateurs d’accéder à tous les fichiers texte stockés sur le partage.
-La solution exige deux serveurs : un serveur hébergeant le partage où sont stockés les fichiers texte contenant le mot de passe et un serveur hébergeant les fichiers de logs d’erreurs en cas de problème lors de l’exécution du script.

1.3 SECURISATION DU REPERTOIRE CONTENANT LES FICHIERS AVEC MOTS DE PASSE :
Le script ADMINISTRATORPASSWORD.CSV s’exécute via un script de démarrage (GPO de type “Configuration Ordinateur”). Il s’exécute donc dans le contexte du compte SYSTEM (droit administrateur sur la station de travail).
La première étape consiste à créer le répertoire E:\logs et le partager en tant que logs$. Définir « Control Total » pour « Tout le monde » au niveau des permissions de partage.
Au niveau des permissions NTFS, supprimer l’héritage des permissions (dans les permissions NTFS avancées). Donner les droits “Contrôl Tôtal” à Administrators, SYSTEM, GRP_PASSWORD Viewer (groupe contenant les utilisateurs qui peuvent voir les fichiers avec les mots de passe).
Il faut ensuite ajouter des permissions spéciales pour le groupe “Authenticated users”
Créer une permissions NTFS personnalisée pour le groupe “Authenticated users”. Aller dans les permissions NTFS avancées. Sélectionner “Apply to this folder and subfolders”. Sélectionner le permissions suivantes :
– Traverse folder / execute file
– List folder / Read data
– Read attributes
– Read extended attributes
– Create files / write data
– Read permissions
Créer une seconde entrée au niveau des permissions NTFS avancées. Sélectionner “Apply to Files only“. Sélectionner le permissions suivantes :
– Read attributes
– Read extented attributes
– Create files / write data
– Create folders / append data
– Write attributes
– write extended attributes
– Delete
– Read permissions

Ne surtout pas cocher la case “List Folder / read data“.
Tester l’accès avec un compte utilisateur.
Ce dernier peut copier un fichier existant, le renommer, le supprimer mais ne peut pas le lire ou le copier depuis le serveur vers sa station de travail.
On est obligé de donner le droit de supprimer dans le cas où le compte ordinateur est supprimé. C’est en effet le compte ordinateur qui est propriétaire du fichier.

1.4 CODE  DU SCRIPT ADMINISTRATORPASSWORD.CSV :
‘ More informations about RND function : http://www.w3schools.com/vbscript/func_rnd.asp
‘ More informations about ACSII code : http://www.commentcamarche.net/contents/base/ascii.php3
‘ More informations about error management : http://technet.microsoft.com/en-us/library/ee176982.aspx and http://technet.microsoft.com/en-us/library/ee692852.aspx
‘ More informations about the date : http://www.commentcamarche.net/contents/vbscript/vbs-fonctions-date.php3
‘ More information about permission NTFS : http://support.microsoft.com/kb/308419/en-us

On error resume next
strComputer = “.”
Dim text,action,digits
text = “”

‘VARIABLES TO DEFINE

serverpasswordname = “nom_serveur.domaine.dns”  ‘ Server which store password files. Exemple : srv1.msreport.free.fr
serverlogname = “nom_serveur.domaine.dns”  ‘ Server whuch store errors log files. Exemple : srv1.msreport.free.fr
periodTime = “7776000”     ‘ Time before password expiration in seconds (7776000 = 90 days)
digits = 9      ‘ Lengh of the password

‘ MAIN

‘ Verify if the password must change on the computer
action = NeedChange()
if action = 1 then
 ‘ Determin the name of the administrator account (administrateur in french).
 accounttomodify = AdministratorName()
 ‘ Generate the password
 password = GeneratePassword(digits)
 ‘ Define the new password on the computer.
 Set objUser = getobject(“WinNT://” & strComputer & “/” & accounttomodify & “,User”)
 If Err <> 0 Then
  WriteError(“N.A.;N.A.;No administrator account.”)
  Err.Clear
 else
  objUser.SetPassword password
  objUser.SetInfo
  if Err <> 0 Then
   WriteError(“N.A.;N.A.;Update of administrator fail.”)
   Err.Clear
  else
   ‘ Write the password on a file on server and write the witness file on the computer
   text = accounttomodify + “;” + password
   Writepasswordfile(text)
   if Err = 0 then
    Writewitness(now)
   else
    WriteError(“Unable to connect to the server !”)
   
   End if
  End if
 End If
else
 ‘ if the password has been changed since lower than 30 days, the script takes no actions.
 wscript.quit
End If

Function NeedChange()
On error resume next
‘ Script change password once every periodtime (variable). The script write a log on the computer in C:\Windows\passwordchange.txt that contains the day of the last change of the password

‘ Verify if the file exist on the station
Set objFSO = CreateObject(“Scripting.FileSystemObject”)

‘ if the file exists, we need to read it and verify the date.
If objFSO.FileExists (“C:\Windows\passwordchange.txt”) then
 ‘ Read the date on file C:\Windows\passwordchange.txt 
    dim sFileContents
 dim lastchangetime
 Set oTextStream = objFSO.OpenTextFile(“C:\Windows\passwordchange.txt”,1)
 lastchangetime = cdate(oTextStream.ReadAll)
 oTextStream.Close

 ‘wscript.echo “PeriodTime : ” & periodtime
 ‘wscript.echo ” Date du fichier : ” & lastchangetime
 ‘wscript.echo “Date actuelle : ” & now
 ‘wscript.echo “Différence de temps : ” & DateDiff(“s”,lastchangetime,now)

 ‘ If the file is corrupted, password must be changed.
 if err <> 0 then
  NeedChange = 1
  Err.Clear
       
 ‘if the diffrence between the two date is greater than periodTime, we need to change the password.
 elseif  CDbl(DateDiff(“s”,lastchangetime,now)) > CDbl(periodTime) then
  NeedChange = 1
  ‘wscript.echo “NeedChange : ” & NeedChange
 ‘ Other case, do nothing.
 elseif CDbl(DateDiff(“s”,lastchangetime,now)) < 0 then
  NeedChange = 1
 else
  NeedChange = 0
  ‘wscript.echo “NeedChange : ” & NeedChange
 End If
‘ if the file doesn’t exist, change the password
else
 NeedChange = 1
End if

End Function

‘ Function to generate password

Function GeneratePassword(digits)
Dim passwordtemp
passwordtemp = “”
Dim w
Dim i
Dim digit1, digit2, digit3

‘ Code to generate password with uppercases (A…Z), lowercases (a…z) and numbers (2…9) without 0, O,o I, l

For i = 1 To Digits
 ‘ The function randomize permit to change the result of the RND function
 ‘ The first caracters is an uppercase
 digit1 = “”
 digit2 = “”
 digit3 = “”
 if i = 1 then
         Randomize
  digit1 = chr(65 + INT(RND * 25))
  ‘ The ACSII value 79 is O and the ACSII code 73 is I
  if (digit1 = chr(79)) OR (digit1 = chr(73)) then
   digit1 = chr(80 + INT(RND * 10))
  End if
  passwordtemp = passwordtemp + digit1
 
 elseif i = 2 then
  Randomize
  digit2 = chr(97 + INT(RND * 25))
  ‘ The ACSII value 108 is l
  if (digit2 = chr(108)) OR (digit2 = chr(111)) then
   digit2 = chr(112 + INT(RND * 10))
  End if
                passwordtemp = passwordtemp + digit2
 
 elseif i = digits then
  Randomize
  ‘ The ACSII value 48 is 0 and isn’t in the range.
  passwordtemp = passwordtemp + chr(50 + INT(RND * 7))
 
 else
  Randomize
         w = 1 + INT(RND * 4)
  ‘wscript.echo “value w : ” & w
         If W = 1 Then
                 Randomize
   digit1 = chr(65 + INT(RND * 25))
   ‘ The ACSII value 79 is O and the ACSII code 73 is I
   if (digit1 = chr(79)) OR (digit1 = chr(73)) then
    digit1 = chr(80 + INT(RND * 10))
   End if
   passwordtemp = passwordtemp + digit1 
         ElseIf W = 2 Then
   Randomize
   digit2 = chr(97 + INT(RND * 25))
   ‘ The ACSII value 108 is l
   if (digit2 = chr(108)) OR (digit2 = chr(111)) then
    digit2 = chr(112 + INT(RND * 10))
   End if
                 passwordtemp = passwordtemp + digit2
  Elseif w = 3 Then
   Randomize
   choice = INT(RND * 5)
   ‘wscript.echo “Choice : ” & choice
   ‘ Value ACSII : # = 35  $ = 36 * = 42 + = 43 @ = 64
   if choice = 0 then
    digit3 = chr(35)
   elseif choice = 1 then
    digit3 = chr(36)
   elseif choice = 2 then
    digit3 = chr(42)
   elseif choice = 3 then
    digit3 = chr(43)
   else
    digit3 = chr(64)
   End if
   passwordtemp = passwordtemp + digit3
         Else
                 Randomize
   ‘ The ACSII value 48 is 0, 49 is 1 and isn’t in the range.
   passwordtemp = passwordtemp + chr(50 + INT(RND * 7))
         End If
 End if
‘wscript.echo “Valeur de I : ” & i
Next
GeneratePassword = passwordtemp
End Function

‘ Function to create file with password on the share

Function Writepasswordfile(text)
        ‘Find the name of the workstation and create file result on server
        Set WshNetwork = WScript.CreateObject(“WScript.Network”)
        StationName = WshNetwork.ComputerName
 resufile = “\\” & serverpasswordname & “\logs$\” & StationName & “.txt”
        ‘wscript.echo “Fichier mot de passe : ” & resufile
 Dim objFSO,objFile
        Set objFSO = CreateObject(“Scripting.FileSystemObject”)
        Set objFile = objFSO.CreateTextFile(resufile)
 ‘ Write the date in french format.
        objFile.WriteLine StationName & “;” & text & “;” & Day(now) & “/” & Month(now) & “/” & Year(now)
        objFile.Close        
End Function

Function WriteError(text)
        ‘Find the name of the workstation and create file result on server
        Set WshNetwork = WScript.CreateObject(“WScript.Network”)
        StationName = WshNetwork.ComputerName
 resufile = “\\” & serverlogname & “\logs$\Error-” & StationName & “.txt”
        ‘wscript.echo “Fichier mot de passe : ” & resufile
 Dim objFSO,objFile
        Set objFSO = CreateObject(“Scripting.FileSystemObject”)
        Set objFile = objFSO.CreateTextFile(resufile)
        objFile.WriteLine StationName & “;” & text
        objFile.Close        
End Function
 

Function Writewitness(dateofchangepassword)
 resufile = “C:\Windows\passwordchange.txt”
        Dim objFSO,objFile
        Set objFSO = CreateObject(“Scripting.FileSystemObject”)
        Set objFile = objFSO.CreateTextFile(resufile)
        objFile.WriteLine dateofchangepassword
        objFile.Close        
End Function

Function AdministratorName()
‘ Permit to find the name of the BUILTIN administrator account on the computer. This account have a sid which begin by the following strings S-1-5- and which finish by the following strings “-500”.
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
Set colAccounts = objWMIService.ExecQuery _
    (“Select * From Win32_UserAccount Where LocalAccount = TRUE”)
For Each objAccount in colAccounts
    If Left (objAccount.SID, 6) = “S-1-5-” and Right(objAccount.SID, 4) = “-500” Then
        AdministratorName = objAccount.Name
    End If
Next

End Function

2. LE SCRIPT GENERATECSV.VBS :
2.1 PRESENTATION GENERALE :

Ce script permet de générer un fichier CSV à partir de tous les fichiers textes contenant les mots de passe.
On ne peut pas écrire directement dans le fichier CSV depuis les stations de travail du fait du risque de corruption de données si deux machines changent de mots de passe en même temps. Il faudrait une base de données.

2.2 MISE EN OEUVRE :
Configurer une tâche planifiée sur le serveur où sont stockés les fichiers avec les mots de passe pour créer le fichier CSV contenant tous mots de passe toutes les 10 minutes.

2.3 CODE DU SCRIPT GENERATECSV.VBS :
‘ More information at http://www.computerperformance.co.uk/vbscript/vbscript_file_opentextfile.htm
‘ More information at http://www.devguru.com/technologies/vbscript/quickref/textstream_readall.html

on error resume next

‘ VARIABLES TO DEFINE :
Dim passwordfileshare
Dim targetcsvfile
passwordfileshare = “
\\nom_serveurs_partage_password_files\logs$\
targetcsvfile = “
\\nom_serveurs_partage_password_files\logs$\csv\
csvfile = “
\\nom_serveurs_partage_password_files\logs$\csv\resultats\userspassword.csv
resultfolder = “
\\nom_serveurs_partage_password_files\logs$\csv\resultats\

‘ MAIN
‘ Copy all file from passwordfileshare to targetcsvfile
copypasswordfiles()

‘ Generate the CSV file
GenerateCSV()

Function copypasswordfiles()
Dim FSO
Dim FileExt
FileExt = “*.txt”
Set FSO = CreateObject(“scripting.filesystemobject”)

‘ ADD “\” if the folder name doesn’t finish by this caracters.
If Right(passwordfileshare, 1) <> “\” Then
 passwordfileshare = passwordfileshare & “\”
End If

‘ Verify if the folder to result exist
If FSO.FolderExists(passwordfileshare) = False Then   
 wscript.quit(1)
End if

if FSO.folderExists(targetcsvfile) = False Then
 FSO.CreateFolder(targetcsvfile)
     FSO.CopyFile passwordfileshare & FileExt, targetcsvfile
else
    FSO.CopyFile passwordfileshare & FileExt, targetcsvfile
End if
End function

Function GenerateCSV()

Dim fso, folder, files, NewsFile
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ Verify if the result folder exist and create it if not exist.
if FSO.folderExists(resultfolder) = False Then
 FSO.CreateFolder(resultfolder)
End if

‘ List each file in targetcsvfile, copy the content of each file in csvfile
‘ Create the result file
Set NewFile = fso.CreateTextFile(csvfile, True)
‘ List the file
Set folder = fso.GetFolder(targetcsvfile)
Set files = folder.Files
‘ Write the first line of the result CSV file
NewFile.WriteLine (“Computer;Login;Password;TimeLastChange”)

For each folderIdx In files
 ‘ Read the fisrt line of each txt file
 Set TextFile = fso.opentextfile(targetcsvfile & folderIdx.Name,1)
 ‘ Write a new line in csvfile
 NewFile.WriteLine(TextFile.ReadLine) 
Next
NewFile.Close
End function

a+
Guillaume MATHIEU
http://msreport.free.fr
PROSERVIA
Le bonheur c’est le partage.

 

A propos Guillaume Mathieu

Directeur Technique chez Flexsi
Ce contenu a été publié dans Active Directory, GPO, Outils, Sécurité, Scripts, Système, Windows Seven, Windows Vista, Windows XP. Vous pouvez le mettre en favoris avec ce permalien.

Laisser un commentaire