3

I have a BATCH script that makes symlinks with mklink. When I run it as an administrator or as a system account (with psexec -s -e) it works as it should. But when I try to use it in a GPO as a startup script it gives me an error "you do not have sufficient privilege to perform this operation" on a target computer. Windows 7 Pro SP1 x64. UAC is disabled.

Batch example:

mklink C:\log\cmd.link.exe C:\Windows\System32\cmd.exe >> C:\log\symlink.log 2>&1

I also tried to wrap it into a powershell script:

Start-Process -FilePath "$env:windir\system32\cmd.exe" -ArgumentList "/c mklink C:\log\cmd.link.exe C:\Windows\System32\cmd.exe >> C:\log\symlink.txt 2>&1" -Verb RunAs

but got the same error. What am I doing wrong?

Maybe there's another way to create a SymLink with GPO or PowerShell?

3
  • You're sure you mean a startup script and not a logon script? Commented Oct 8, 2015 at 21:41
  • Yes, I'm pretty sure. Script that runs before logon on a system startup.
    – n01d
    Commented Oct 9, 2015 at 6:45
  • OK, in that case I have no idea what's causing the problem, but you should be able to work around it by having the startup script call psexec (since you know that works). Commented Oct 9, 2015 at 6:51

2 Answers 2

5

It appeared that the Group Policy Client (gpsvc) service (since GPO scripts runs with its privilegies) does not contain the privilege to create symolic links (SeCreateSymbolicLinkPrivilege):

C:\>sc qprivs gpsvc
[SC] QueryServiceConfig2 SUCCESS

SERVICE_NAME: gpsvc
        PRIVILEGES       : SeTakeOwnershipPrivilege
                         : SeIncreaseQuotaPrivilege
                         : SeAssignPrimaryTokenPrivilege
                         : SeSecurityPrivilege
                         : SeChangeNotifyPrivilege
                         : SeCreatePermanentPrivilege
                         : SeShutdownPrivilege
                         : SeLoadDriverPrivilege
                         : SeRestorePrivilege
                         : SeBackupPrivilege

If I want to use this privilege I should at first grant this privelege to the service. It can be done with this command:

sc privs gpsvc SeTakeOwnershipPrivilege/SeIncreaseQuotaPrivilege/SeAssignPrimaryTokenPrivilege/SeSecurityPrivilege/SeChangeNotifyPrivilege/SeCreatePermanentPrivilege/SeShutdownPrivilege/SeLoadDriverPrivilege/SeRestorePrivilege/SeBackupPrivilege/SeCreateSymbolicLinkPrivilege

After that you will be able to use mklink inside GPO scripts.

There are several caveats:

  1. You should list all permissions (current + new). Otherwise you risk to replace all permissions with one.
  2. The command needs System account permission to set privileges so you'll need to use psexec or GPO script (not sure).
  3. If you intend to use psexec it will throw you an error about argument being too long. So you should save this command as a .bat file and then run it with psexec.

Many thanks to @PetSerAl who helped me to find this out.

0

I still had an issue running the sc.exe commands with PowerShell as a startup script via Group Policy. It was being denied access per Start-Transcript log file. I used the below PowerShell logic for example and it did not work for me in my case.

I tried several variations of multiple things and syntaxes using PowerShell.exe, -verb RunAs, Start-Process and slews of things short of running it as a local script with Task Scheduler as SYSTEM which I was trying to avoid.

Note: This is just a general example of one of the variations that failed with the same result and transcript output as all other variations tried.

$privs = (sc.exe qprivs gpsvc).Split(":")[5..99] | % { Process { If( $_.Trim().Length -gt 0 ){ $_.Trim() } } };
$privs = $privs + "SeCreateSymbolicLinkPrivilege";
$privs = $privs -Join "/";

Invoke-Expression "sc.exe privs gpsvc $privs"

A solution that works (in my case)

I used the below PowerShell logic as a startup script via Group Policy and now creating symbolic links works. To keep the example simple, I used Google Chrome for generalization.

Basically I had to manipulate the multistring registry value of the correlated permissions for the service rather than using sc.exe appending the needed "SeCreateSymbolicLinkPrivilege" value that way.

#Start-Transcript -Path C:\Log\Transcript.txt

$v = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\gpsvc").RequiredPrivileges;
If ( $v -notcontains "SeCreateSymbolicLinkPrivilege" ) {
    $v = $v + "SeCreateSymbolicLinkPrivilege";
    Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\gpsvc" RequiredPrivileges $v -Type MultiString;
    };

$Chrome86 = "C:\Program Files (x86)\Google\Chrome";
$Chrome = "C:\Program Files\Google\Chrome";

If(!(Test-Path $Chrome86)){
    If(Test-Path $Chrome){New-Item -Path $Chrome86 -ItemType SymbolicLink -Value $Chrome -Force}
}
If(!(Test-Path $Chrome)){
    If(Test-Path $Chrome86){New-Item -Path $Chrome -ItemType SymbolicLink -Value $Chrome86 -Force}
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.