27

I use Windows Server 2012.

I can do this:

In Administrative Tools folder, double click the Local Security Policy icon, expand Account Policies and click Password Policy.

In the right pane double click Password must meet complexity requirements and set it to Disabled. Click OK to save your policy change.

How can I do it programmatically using Powershell?

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
  • i dont know how to do it using PS, but you can still use secedit.exe see http://technet.microsoft.com/en-us/library/hh875511.aspx – Loïc MICHEL Apr 24 '14 at 07:42

3 Answers3

37

There is no pure powershell way of doing it as per @Kayasax's answer, you have to wrap secedit into Powershell.

secedit /export /cfg c:\secpol.cfg
(gc C:\secpol.cfg).replace("PasswordComplexity = 1", "PasswordComplexity = 0") | Out-File C:\secpol.cfg
secedit /configure /db c:\windows\security\local.sdb /cfg c:\secpol.cfg /areas SECURITYPOLICY
rm -force c:\secpol.cfg -confirm:$false
Raf
  • 9,681
  • 1
  • 29
  • 41
  • 1
    Added useful sample http://vlasenko.org/2011/04/27/removing-password-complexity-requirements-from-windows-server-2008-core/ – Kiquenet Jul 24 '14 at 06:03
  • 3
    The one thing to note is that exporting the policy violates the system security, since it exposes it and placing the file in the root of the boot volume c:\secpol.cfg makes this easy to abuse security wise. So I'd not use this verbatim in a production environment - rather use the $env:userdata location to store the temporary file and resolve the filename for the commandline utility "${env:appdata}\secpol.cfg" –  Jun 23 '15 at 10:40
  • crazy, ugly but it works. Looks like the only easy way to interact with Group Policy. GPOs APIs are written in C++ – Nick Kavadias Dec 24 '15 at 05:55
  • 1
    Be warned. this changed other security settings which hadnt initally been set by GPO , e.g. powershell execution policy. – Nick Kavadias Dec 24 '15 at 06:12
  • Getting "The parameter is incorrect." on this line "secedit /configure /db c:\windows\security\local.sdb /cfg c:\secpol.cfg /areas SECURITYPOLICY" – Emperor Eto Jun 24 '20 at 13:31
  • @PeterMoore please create a new question - rather than a comment - with appropriate description: PS and OS version + other relevant bits. A lot could have changed in the last 6 years since this question was answered. – Raf Jun 24 '20 at 14:29
13

I decided to write a couple functions to make this process easier.

Parse-SecPol : will turn Local Security Policy into a PsObject. You can view all the properties and make changed to the object.

Set-SecPol : will turn the Parse-SecPol object back into a config file and import it to into the Local Security Policy.

Here is a example of its usage :

Function Parse-SecPol($CfgFile){ 
    secedit /export /cfg "$CfgFile" | out-null
    $obj = New-Object psobject
    $index = 0
    $contents = Get-Content $CfgFile -raw
    [regex]::Matches($contents,"(?<=\[)(.*)(?=\])") | %{
        $title = $_
        [regex]::Matches($contents,"(?<=\]).*?((?=\[)|(\Z))", [System.Text.RegularExpressions.RegexOptions]::Singleline)[$index] | %{
            $section = new-object psobject
            $_.value -split "\r\n" | ?{$_.length -gt 0} | %{
                $value = [regex]::Match($_,"(?<=\=).*").value
                $name = [regex]::Match($_,".*(?=\=)").value
                $section | add-member -MemberType NoteProperty -Name $name.tostring().trim() -Value $value.tostring().trim() -ErrorAction SilentlyContinue | out-null
            }
            $obj | Add-Member -MemberType NoteProperty -Name $title -Value $section
        }
        $index += 1
    }
    return $obj
}

Function Set-SecPol($Object, $CfgFile){
   $SecPool.psobject.Properties.GetEnumerator() | %{
        "[$($_.Name)]"
        $_.Value | %{
            $_.psobject.Properties.GetEnumerator() | %{
                "$($_.Name)=$($_.Value)"
            }
        }
    } | out-file $CfgFile -ErrorAction Stop
    secedit /configure /db c:\windows\security\local.sdb /cfg "$CfgFile" /areas SECURITYPOLICY
}


$SecPool = Parse-SecPol -CfgFile C:\test\Test.cgf
$SecPool.'System Access'.PasswordComplexity = 1
$SecPool.'System Access'.MinimumPasswordLength = 8
$SecPool.'System Access'.MaximumPasswordAge = 60

Set-SecPol -Object $SecPool -CfgFile C:\Test\Test.cfg
ArcSet
  • 6,518
  • 1
  • 20
  • 34
  • this is outdated, is there an updated version for this? – Nuro007 Nov 19 '22 at 03:32
  • I wrote this just for this answer. I didnt write any updates. But what part is not working for you? @Nuro007 – ArcSet Nov 22 '22 at 16:00
  • There seems to be an issue with REGEX, i'm getting this error: `Exception calling "Matches" with "2" argument(s): "Value cannot be null.` – Nuro007 Nov 24 '22 at 00:10
  • it looks like that i cannot change `Event Audit` on it? is that normal or am I doing something wrong? – Nuro007 Nov 24 '22 at 04:21
2

I use Windows 7

I have solved it by using the following powershell script

$name = $PSScriptRoot + "\" + $MyInvocation.MyCommand.Name

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$name`"" -Verb RunAs; exit }

$registryPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"

$Name = "LimitBlankPasswordUse"

$value = "0"

New-ItemProperty -Path $registryPath -Name $name -Value $value ` -PropertyType DWORD -Force | Out-Null

This script will automatically run as admin, if not already opened in admin mode

I Also tried the script Raf wrote. I had version 2.0, but I only got it to work with version 4.0

Pavenhimself
  • 527
  • 1
  • 5
  • 18