Jump to content
KyotoUK

Create Local Admin if not present

Recommended Posts

Hi all,

I am trying to work out how to create a local admin account if one with a particular name doesnt exist. I'm sure like my previous question is obvious but I cant see for looking.

The account name I plan to use is supportadmin

Thanks again

R

Share this post


Link to post
Share on other sites

If the machine already has CWA installed on it you can open the Agent, open Windows System tile, select users.

From there you can add a user and then promote it to administrator

 

Share this post


Link to post
Share on other sites

Hi Kyoto,

 

If you go through the system and create user you can turn into a script by going into commands>right click on the commands and turn into script.

You can go ahead and deploy this script on 200 machines.

Share this post


Link to post
Share on other sites

Hello, @KyotoUK, hopefully what we've done may be of some use. Here's the rough breakdown of the script we use. (And we're using an EDF to track if we have or haven't added/updated the admin account.)

  1. Shell 'net user [username]', IF %shellresult% contains [username] then jump to part of script where we just use a batch file to update the password.
  2. IF %shellresult% doesn't, we need to create a new account.
  3. New account - Use the 'add user' script step, then a shell command for 'net localgroup Administrators [username] /add', and to make the password not expire we run a 'WMIC USERACCOUNT WHERE (Name='[username]' and Domain='%computername%') SET PasswordExpires=FALSE', set the tracking EDF to 1, then exit the script.
  4. Update password instead - Download batch file which basically just runs 'net user' to set the password. We use that WMIC command again just to reinforce the 'no expire' part. Then delete the batch file and set the tracking EDF to 1.

Why the batch file? Because a 'net user' command and its results show up in the Commands list on a given machine, so folks who have access to Commands logs but shouldn't know the special password will get to see it. (Oh yes, use ECHO OFF in that batch file.)

The EDF is just a toggle to say "yes, the special admin account has been taken care of." Then you can use its 0 or 1 status to do a search that populates a group. That group can be set to run the add-or-update-admin-user script every couple of hours. Once the script runs, the EDF/search will take care of removing the endpoint from the group.

  • Like 2

Share this post


Link to post
Share on other sites

Adding to @KKerezman post:  You can also add some additional items like the line below to formalize the account:

net user supportadmin /comment:"123Company Support Account" /fullname:"123Company Support" /expires:never  /active:yes

Note(s): The /expires: never is for the account not the password (That was specified in @KKerezman line #3)

                The /active:yes is an unlock of the account.  (Most likely not needed for this portion but a nice-to-know if you are a command line person)

Edited by tvarvais
update
  • Like 1

Share this post


Link to post
Share on other sites

@KKerezman  Thanks for this - I've had a semi-formed script I'd been working on for a while, but was stuck at the concept of a client-specific password.   I guess in Step 4 I'm a little concerned that there's a batch file out there with a local admin password in it.  I know we're deleting it from the machine, but it still exists in the share.  

Anyone have any ideas for setting that password per client without using a batch file?  With all the MSPs being targeted, I don't want to leave anything to chance.

Share this post


Link to post
Share on other sites

CWA scripting actually has a generate password function. I use that function to generate the password, then use commands to set it and write it to a machine level EDF. That way every single machine has a unique admin password. That's important because if you use the same password for every computer in a client, if one machine is compromised it's pretty easy to brute force even complex passwords on Windows user accounts. Which means compromising one computer could be a very easy gateway to compromising all computers in a network automatically and invisible to the user.

Share this post


Link to post
Share on other sites

We also rerun the script daily, meaning that the admin password for each computer rotates daily as well. This gives us the advantage of, in a pinch, being able to give the client the password knowing it wont be any good tomorrow, even if they write it on a sticky note and tape it to their screen. If you do that, just make sure you verify it has been changed before updating the EDF.

Share this post


Link to post
Share on other sites

My script isn't safe for public consumption, but most of the heavy lifting is done by Powershell. Here are the two important parts of it.

Part One, creating or updating the user.

$Password = ConvertTo-SecureString -string '@Password@' -AsPlainText -Force
$Username = '@Username@'
Try{$User = Get-LocalUser -Name $Username -ErrorAction Stop; write-host "User exists"}
Catch {write-host "User does not exist"}
if(!$User) {
    Try{$UserCreation = New-LocalUser -Name $Username -Description "MSP Local Administrator Account" -Password $password -ErrorAction Stop; $User = Get-LocalUser -Name $Username -ErrorAction Stop}
    Catch {write-host "User Creation Failed: $_.Exception.Message"}
}
if($User) {
    Try{$GroupAddResults = Add-LocalGroupMember -name Administrators -Member $User -ErrorAction Stop; Write-Host "User added to group"} 
    Catch {Write-Host "User Already in Admin Group"}
    Set-LocalUser $User -PasswordNeverExpires $true
    Add-Type -assemblyname system.DirectoryServices.accountmanagement 
    $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
    if($DS.ValidateCredentials($Username, '@Password@')) {
        Write-Host "Credentials do not need to be updated"
    } else {
        Try {$UserUpdate = Set-LocalUser $User -Password $Password -ErrorAction Stop; Write-Host "Credentials Updated"}
        Catch {Write-Host "Updating of credentials failed"}
    }
}

Part Two, verifying the credentials are correct.


Add-Type -assemblyname system.DirectoryServices.accountmanagement
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
if($DS.ValidateCredentials('@Username@', '@Password@')) {
    Write-Host "Credentials Correct"
} else {
    Write-Host "Credentials Incorrect"
}

I use machine level EDFs to store the password after I've verified it to be correct. The first script also verifies the credentials, but for safety I verify a second time with a new powershell session so I can be 100% sure the password was updated. At the beginning of the script I check to make sure the role of AD Domain Controller isn't present, so that we don't accidentally end up creating the domain user, and then changing the password for every domain controller on a network.

Edited by danialbulloch
  • Like 2

Share this post


Link to post
Share on other sites

R,

We use a search for this.  The "legacy" searches can use raw SQL if you use a * character.  So:

client = name
last contact date not= *'x' AND (computers.useraccounts NOT LIKE '%supportadmin%')
os notlike %server%

...or whatever conditions you need.  The "last contact date" is irrelevant...we really want the "and" part...but including it does display that column.  It doesn't know to display the column in the extra text.

Computers.useraccounts is a database field, I want to say it is one user per line or something, might be comma delimited...it's been several years.

Then just schedule your user creation script to run on PCs in that group, with the search as the autojoin.

 

To create the user we just use:

net user /add [username] [password]
net localgroup administrators [username] /add
wmic useraccount WHERE "Name='[username]'" set PasswordExpires=false

(without the brackets of course)

Edited by SteveYates
user creation info

Share this post


Link to post
Share on other sites
On 12/17/2019 at 3:11 PM, danialbulloch said:

My script isn't safe for public consumption, but most of the heavy lifting is done by Powershell. Here are the two important parts of it.

Part One, creating or updating the user.


$Password = ConvertTo-SecureString -string '@Password@' -AsPlainText -Force
$Username = '@Username@'
Try{$User = Get-LocalUser -Name $Username -ErrorAction Stop; write-host "User exists"}
Catch {write-host "User does not exist"}
if(!$User) {
    Try{$UserCreation = New-LocalUser -Name $Username -Description "MSP Local Administrator Account" -Password $password -ErrorAction Stop; $User = Get-LocalUser -Name $Username -ErrorAction Stop}
    Catch {write-host "User Creation Failed: $_.Exception.Message"}
}
if($User) {
    Try{$GroupAddResults = Add-LocalGroupMember -name Administrators -Member $User -ErrorAction Stop; Write-Host "User added to group"} 
    Catch {Write-Host "User Already in Admin Group"}
    Set-LocalUser $User -PasswordNeverExpires $true
    Add-Type -assemblyname system.DirectoryServices.accountmanagement 
    $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
    if($DS.ValidateCredentials($Username, '@Password@')) {
        Write-Host "Credentials do not need to be updated"
    } else {
        Try {$UserUpdate = Set-LocalUser $User -Password $Password -ErrorAction Stop; Write-Host "Credentials Updated"}
        Catch {Write-Host "Updating of credentials failed"}
    }
}

Part Two, verifying the credentials are correct.


Add-Type -assemblyname system.DirectoryServices.accountmanagement
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)
if($DS.ValidateCredentials('@Username@', '@Password@')) {
    Write-Host "Credentials Correct"
} else {
    Write-Host "Credentials Incorrect"
}

I use machine level EDFs to store the password after I've verified it to be correct. The first script also verifies the credentials, but for safety I verify a second time with a new powershell session so I can be 100% sure the password was updated. At the beginning of the script I check to make sure the role of AD Domain Controller isn't present, so that we don't accidentally end up creating the domain user, and then changing the password for every domain controller on a network.

Hi Daniel & all.

I love the idea of this script running on a daily basis with random system generated passwords for the local admin accounts.


A couple of questions though sorry:
1. Do you have a complete script available so it can be installed or a set of instructions for those of us that are new to Automate can set this up?
2. Is a tech able to see the password so it can be entered manually if needed? ie a control session or to manually install a piece of software on an endpoint?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...