Запланированная задача в Windows Server 2016, запускаемая пользователями без прав администратора
В более ранних версиях Windows Server (до 2016 года) пользователям, не имеющим прав администратора, можно было разрешить запуск запланированной задачи, выполнив следующие действия:
- Запланированная задача: запустить под системой, выполнить скрипт
- Предоставьте пользователю права на чтение и выполнение определенной задачи в папке C:\Windows\System32\Tasks\
Теперь на сервере 2016 это больше не работает. Ты знаешь как это сделать?
Спасибо
связанный пост, который не получил ответа, также не помог: разрешить пользователю без прав администратора запускать запланированное задание в Windows Server 2016
1 ответ
Покопавшись некоторое время в этой теме и попробовав несколько предложений, я придумал этот сценарий, для которого требуется инструмент PsExec из PsTools/SysInternals от Microsoft:
$task = "Test-Script"
$secdesc = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
$regkeys = Get-childitem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree"
foreach ($key in $regkeys) {
if ($key.PSChildName -eq $task) {
$t = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:")
$sddl = $secdesc.BinarySDToSDDL( $t.SD )
$newSDDL = $sddl['SDDL'] + '(A;ID;0x1301bf;;;AU)'
$binSDDL = $secdesc.SDDLToBinarySD( $newSDDL )
[string]$binSDDLStr = $([System.BitConverter]::ToString($binSDDL['BinarySD'])).replace('-','')
"reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $binSDDLStr | out-file -Encoding ascii $PWD\temp_setreg.bat
start-sleep 2
.\PsExec.exe -accepteula -nobanner -s "$PWD\temp_setreg.bat"
break
}
}
Предыстория: очевидно, что начиная с Windows 10 (и соответствующего Windows Server 2016+) параметры безопасности больше не используются из пути задачи (C:\Windows\system32\Tasks), а хранятся в реестре:
- /questions/545642/nevozmozhno-uvidet-zaplanirovannuyu-zadachu-dazhe-s-pravami-dostupa-k-system32ta/780013#780013
- /questions/429218/razresheniya-ili-acl-dlya-zaplanirovannyih-zadach/429220#429220
Я нашел сценарий, который использует значения реестра . Он создает задачу для запуска от имени СИСТЕМЫ, поэтому вы можете редактировать разрешения (поскольку администраторы также имеют разрешение только на чтение).
Я отредактировал этот сценарий, чтобы сократить его, и использовал PsExec для редактирования разрешений реестра от имени пользователя СИСТЕМА.
МестоPsExec.exe
в том же каталоге, где находится сценарий, отредактируйте первую строку, указав имя задачи. Запустите скрипт из этого каталога.
От автора сценария:(A;ID;0x1301bf;;;AU)
значит добавитьAuthenticated Users
сread and execute
разрешение.
Вы можете создать свою собственную запись разрешения, используя вкладку «Безопасность» проводника Windows, и прочитать ее из командной строки в формате SDDL следующим образом:Cacls . /S
Заменять.
с путем или файлом, если это не ваш текущий каталог.
Вот оригинальный скрипт (архив): UnlockScheduledTask.ps1
<#
.SYNOPSIS
This Powershell script updates the security descriptor for scheduled tasks so that any user can run the task.
Version 1.0 of this script only displays tasks in the root folder. I want to make sure that works first.
.DESCRIPTION
Earlier versions of Windows apparently used file permissions on C:\Windows\System32\Tasks files to manage security.
Windows now uses the SD value on tasks under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree to accomplish that.
By default, this script will display the SDDL on all tasks. If a taskname is passed as a parameter, this script will grant Authenticated users read and execute permissions to the task.
This script accepts 1 parameters.
-taskname The name of a scheduled task.
.EXAMPLE
./UnlockScheduledTask.ps1
./UnlockScheduledTask.ps1 -taskname "My task"
.NOTES
Author: Dave K. aka MotoX80 on the MS Technet forums. (I do not profess to be an expert in anything. I do claim to be dangerous with everything.)
.LINK
http://www.google.com
#>
param (
[string]$taskname = ""
)
'UnlockScheduledTask.ps1 Version 1.0'
if ($taskname -eq '') {
''
'No task name specified.'
'SDDL for all tasks will be displayed.'
''
} else {
$batFile = "$env:TEMP\Set-A-Task-Free.bat" # if you don't like my names, you can change them here.
$updateTaskName = 'Set-A-Task-Free'
''
"SDDL for $taskname will be updated via $batfile"
''
}
$wmisdh = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
$subkeys = Get-childitem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree"
foreach ($key in $subkeys) {
if ($taskname -eq '') { # if blank, show SDDL for all tasks
''
$key.PSChildName
$task = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:")
$sddl = $wmisdh.BinarySDToSDDL( $task.SD )
$sddl['SDDL']
} else {
if ($key.PSChildName -eq $taskname) {
""
$key.PSChildName
$task = Get-ItemProperty $($key.name).replace("HKEY_LOCAL_MACHINE","HKLM:")
$sddl = $wmisdh.BinarySDToSDDL( $task.SD )
$sddl['SDDL']
''
'New SDDL'
$newSD = $sddl['SDDL'] + '(A;ID;0x1301bf;;;AU)' # add authenticated users read and execute
$newSD # Note: cacls /s will display the SDDL for a file.
$newBin = $wmisdh.SDDLToBinarySD( $newsd )
[string]$newBinStr = $([System.BitConverter]::ToString($newBin['BinarySD'])).replace('-','')
# Administrators only have read permissions to the registry vlaue that needs to be updated.
# We will create a bat file with a reg.exe command to set the new SD.
# The bat file will be invoked by a scheduled task that runs as the system account.
# The bat file can also be reused if the task is deployed to other machines.
''
"reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $newBinStr
"reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{0}"" /f /v SD /t REG_BINARY /d {1}" -f $key.PSChildName, $newBinStr | out-file -Encoding ascii $batfile
''
SCHTASKS /Create /f /tn "$updateTaskName" /sc onstart /tr "cmd.exe /c $batfile" /ru system
SCHTASKS /run /tn "$updateTaskName"
$count = 0
while ($count -lt 5) {
start-sleep 5
$count++
$(Get-ScheduledTask -TaskName $updateTaskName).State
if ($(Get-ScheduledTask -TaskName $updateTaskName).State -eq 'Ready') {
$count = 99 # it's ok to procees
}
}
if ($count -ne 99) {
"Error! The $updateTaskName task is still running. "
'It should have ended by now.'
'Please investigate.'
return
}
SCHTASKS /delete /f /tn "$updateTaskName"
''
'Security has been updated. Test it.'
}
}
}