Как запустить командлет модуля PowerShell как SYSTEM?

Создан модуль PowerShell, он имеет функцию и предоставляет командлет для этой функции. встроенный PowerShell 5.1 и pwsh.exe 7.3.1 (устанавливается с помощью установщика MSI) могут без проблем обнаружить и запустить командлет.

теперь мне нужен этот командлет для «запуска независимо от того, вошел ли пользователь в систему или нет» в планировщике задач Windows.

проблема возникает, когда я пытаюсь запустить командлет моего модуля PowerShell как NT AUTHORITY\SYSTEM.

Что мне нужно сделать, потому что в планировщике задач это кажется единственным способом получить запланированное задание «запускаться независимо от того, вошел ли пользователь в систему или нет». (Я не хочу вручную вводить имя пользователя или пароль любой учетной записи пользователя Windows)

В идеале я бы предпочел использовать встроенную группу безопасности администраторов, но, как вы видите, я не смогу запустить задачу, если пользователь не вошел в систему.

поэтому я действительно застрял здесь, не зная, что делать. Я предполагаю, что это один из крайних случаев, с которыми я сталкиваюсь.

Мне нужно найти способ, чтобы, когда PowerShell работает как SYSTEM, он по-прежнему мог обнаруживать командлет моего модуля.

Я знаю, что мой командлет не обнаруживается, когда PowerShell работает как SYSTEM, потому что я тестировал его с помощью PsExec64.

Я поместил сюда свой модуль PowerShell (именно там они устанавливаются по умолчанию из онлайн-галерей):

C:\Users\<UserName>\OneDrive\Documents\PowerShell\Modules\ModuleFolder

Это весь блок сценария PowerShell, который я использую для создания своей задачи.

$action = New-ScheduledTaskAction -Execute "pwsh.exe" -Argument "-command 'myCmdLet -parameter1 $variable1"

# First thing I tried
$TaskPrincipal = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Administrators" -RunLevel Highest

# Second thing I tried
$TaskPrincipal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest

$trigger = New-ScheduledTaskTrigger -AtStartup

Register-ScheduledTask -Action $action -Trigger $trigger -Principal $TaskPrincipal -TaskName "Name" -Description "Description"

$TaskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Compatibility Win8 -StartWhenAvailable

Set-ScheduledTask -TaskName "Name" -Settings $TaskSettings 

ОБНОВЛЯТЬ:

Я нашла способ:

$TaskPrincipal = New-ScheduledTaskPrincipal -LogonType S4U -UserId $env:USERNAME -RunLevel Highest

который запускает задачу от имени администратора (поскольку командлет модуля не будет работать даже без прав администратора), а также проверяет эти 2 поля, которые я действительно хотел сделать. тем не менее, я все еще ищу способ сделать командлет моего модуля известным PowerShell, когда он работает как SYSTEM, он предоставит 1 преимущество, AFAIK, которое заключается в удалении зависимости от конкретной учетной записи пользователя, существующей на компьютере.

Говоря прагматически, разве вы не можете просто добавить Import-Module C:\Users\<UserName>\OneDrive\Documents\PowerShell\Modules\Mo‌​duleFolder\<YourModu‌​le> к своему pwsh.exe звонку?

mklement0 06.01.2023 18:40

Я не могу. модуль, который я делаю, требует ввода от пользователя, после того, как эти входы будут введены с помощью командлета модуля, будут запущены команды, а затем будет создана задача с этими входами в планировщике задач Windows, которую мне нужно запустить независимо от того, какие пользователь вошел в систему. поэтому сам файл модуля, который находится там, не имеет никаких входных данных и имеет только функцию, которая принимает параметры. Я не понимаю, почему для PowerShell нет надлежащего официального параметра, чтобы установить флажок для Run whether user is logged on or not и Do not store password The task will only have access to local resources

Jameschad 06.01.2023 18:47

Я не понимаю: предлагаемый вызов Import-Module просто сделал бы автоматический импорт вашего модуля, на который вы сейчас пытаетесь положиться, явным. По определению вы пытаетесь работать не в интерактивном режиме, верно?

mklement0 06.01.2023 19:14

Извините, позвольте мне попробовать еще раз, я создал модуль, загрузил его в галерею PowerShell, пользователь А установит его с помощью командлета Install-Module в обычном окне PowerShell. он будет установлен по умолчанию в C:\Users\<username>\OneDrive\Documents\PowerShell\Modules. пользователь A запустит мой модуль с помощью командлета, который он предоставляет, и передаст ему параметры. модуль запускается и выполняет свою работу, в конце необходимо создать запланированное задание, чтобы пользователю не нужно было снова повторять процесс запуска командлета с параметрами. задача, которую он создает, должна выполняться независимо от того, вошел ли пользователь в систему или не запрашивать pwd.

Jameschad 06.01.2023 19:22

Помимо противоречия в «модуль, который я делаю, требует ввода от пользователя» и «запускается независимо от того, вошел ли пользователь в систему или нет». Учетная запись SYSTEM не должна взаимодействовать с пользователем, поскольку она представляет угрозу безопасности. Любые попытки в этом направлении будут либо запрещены, либо инициировать UAC (как в случае с PSExec). Связь между этими учетными записями может / должна осуществляться только отдельными процессами через небольшие каналы, такие как реестр или файлы, содержащие безопасные настройки, избегая всего, что является исполняемым.

iRon 06.01.2023 20:00

@iRon Lol, в части противоречия, это многоцелевой модуль, который требует ввода хотя бы один раз от пользователя, после чего его необходимо запускать регулярно. в любом случае, да, вы правы, я имею в виду, что мне пришлось отключить правило ASR Block process creations originating from PSExec and WMI commands, прежде чем я смог протестировать свой модуль с помощью PSExec. так вы говорите, что я должен забыть о попытке запустить командлет моего модуля как SYSTEM в планировщике задач, и мой лучший вариант — продолжить с -LogonType S4U -UserId $env:USERNAME -RunLevel Highest?

Jameschad 06.01.2023 20:15

Почему модуль «требует ввода хотя бы один раз от пользователя»?

Bill_Stewart 06.01.2023 20:48

Проще говоря, PS ищет модули в указанных каталогах. Если вы устанавливаете для пользователя, он помещается в каталог профиля пользователя, СИСТЕМА не может «увидеть» там ваш модуль. Вы должны установить модуль для «Всех пользователей», который помещает его в системный каталог, чтобы ВСЕ пользователи могли получить к нему доступ. Будет ли это работать даже тогда, сомнительно.

Scepticalist 06.01.2023 20:53

@Bill_Stewart, потому что я так это сделал и как это работает. @Scepticalist большое спасибо, это в значительной степени отвечает на мой вопрос и помечает его как решенный. Я нашел параметр -scopeinstall-module , по этой ссылке представлена ​​вся информация: Learn.microsoft.com/en-us/powershell/module/powershellget/…

Jameschad 06.01.2023 22:23

"потому что так я сделал и так оно и работает" - мне кажется, что это хороший повод рассмотреть конструкцию, которая этого не требует.

Bill_Stewart 06.01.2023 23:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
141
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обобщить:

  • Ваша проблема заключалась в том, что модуль, который вы хотите использовать в своей запланированной задаче, был установлен в области действия текущего пользователя, что не увидит задача, запущенная от имени другого пользователя, например NT AUTORITY\SYSTEM.

    • Самое простое решение — установить модуль для всех пользователей с помощью аргумента -Scope AllUsers, переданного в Install-Module (требуется повышение прав).

    • Однако есть решение, даже если это невозможно или нежелательно, а именно передать полный путь к модулю явному вызову Import-Module, выполняемому в контексте задачи, как показано ниже.

  • Поскольку ваша задача должна выполняться с повышением прав, как вы утверждаете, запуск в контексте текущего пользователя возможен только в том случае, если этот пользователь является администратором; как вы обнаружили, вы можете настроить это следующим образом (требуется повышение):

    $taskPrincipal = 
      New-ScheduledTaskPrincipal -LogonType S4U -UserId $env:USERNAME -RunLevel Highest
    
  • Запуск задачи от имени пользователя NT AUTORITY\SYSTEM неизменно запускается:

    • с повышенными правами, учитывая, что эта учетная запись является встроенной учетной записью с высокими привилегиями и расширенными локальными привилегиями, которая «действует как компьютер в сети».
    • невидимо (в том же скрытом сеансе / оконной станции, в котором работают службы, отсюда и использование -LogonType Service.
    • находится ли пользователь в данный момент в системе
    • с C:\Windows\System32 в качестве рабочего директора по умолчанию
    • со значением <hostname>$, отраженным в $env:USERNAME, где <hostname> — имя локальной машины, а $HOME / $env:USERPROFILE папка C:\Windows\system32\config\systemprofile.

Следующий автономный пример:

  • создает задачу, которая выполняется один раз, через 5 секунд после создания
  • работает как NT AUTHORITY\SYSTEM
  • создает образец модуля сценария в домашнем каталоге текущего пользователя. что задача явно импортирует
  • вызывает функцию из этого модуля, которая сообщает информацию о среде выполнения и регистрирует результат в текстовом файле в домашнем каталоге текущего пользователя.
  • ожидает выполнения задачи и показывает зарегистрированную информацию.
  • убирает за собой (создаются временные файлы ~/_test.psm1 и ~/_test.txt, а временная задача называется _Test)
#requires -RunAsAdministrator

# Abort on any error.
# Note: Since the *-ScheduledTask* cmdlets are implemented as 
#       CDXML-based *script* modules, they only see preference vars.
#       in the *global* scope - see https://github.com/PowerShell/PowerShell/issues/4568
$prevEaPref = $global:ErrorActionPreference
$global:ErrorActionPreference = 'Stop'

try {

    # Create a simple script module that exports function Get-Foo,
    # in the current user's home dir., named '_test.psm1'
    @'
function Get-Foo { "Hi, I'm running at $(Get-Date)`n * as $env:USERNAME (whose home dir. is '$HOME')`n * in '$PWD'`n * $(('NON-elevated', 'ELEVATED')[[bool] (net session 2>$null)])." }
'@ > ~/_test.psm1

    # Set up the scheduled task:

    # The command (program) to run.
    # Import the test-module via its full path, call Get-Foo, and redirect all output streams
    # to file '_test.txt' in the current users' home dir.
    $action = New-ScheduledTaskAction -Execute powershell -Argument "-ExecutionPolicy Bypass -NoProfile -Command & { Import-Module `"$((Get-Item ~/_test.psm1).FullName)`"; Get-Foo } *> `"$((Get-Item ~).FullName)\_test.txt`""

    # Run as 'NT AUTHORITY\SYSTEM', which runs:
    #  * invisibly
    #  * whether or not someone is logged on
    #  * implicitly with elevation
    $user = New-ScheduledTaskPrincipal -UserID 'NT AUTHORITY\SYSTEM' -LogonType ServiceAccount

    # # Advanced settings such as whether to allow start on demand, not running when on batter power, ... 
    # $settings = New-ScheduledTaskSettingsSet

    # When to run it: Run a few seconds from now, once.
    $secsFromNow = 5
    $when = (Get-Date).AddSeconds($secsFromNow)
    $trigger = New-ScheduledTaskTrigger -Once -At $when

    # Create the task from the above.
    $newTask = New-ScheduledTask -Action $action -Principal $user -Trigger $trigger

    # Register the task with name '_Test'
    Write-Verbose -Verbose "Creating task..."
    Register-ScheduledTask '_Test' -InputObject $newTask -Force

    Write-Verbose -Verbose "Task will execute invisibly in $secsFromNow seconds, running as 'NT AUTHORITY\SYSTEM'. Waiting (plus a few extra seconds)..."
    Start-Sleep ($secsFromNow + 5) # Wait an extra few seconds to give the task time to complete.

    Write-Verbose -Verbose "Task is assumed to have run. Output logged:"
    Get-Content ~/_test.txt
}
finally {
    # Clean up.
    Remove-Item -ErrorAction Ignore ~/_test.psm1, ~/_test.txt
    Unregister-ScheduledTask -ErrorAction Ignore -TaskName _Test -Confirm:$false
    $global:ErrorActionPreference = $prevEaPref
}

Пример вывода:

VERBOSE: Creating task...

TaskPath                                       TaskName                          State
--------                                       --------                          -----
\                                              _Test                             Ready
VERBOSE: Task will execute invisibly in 5 seconds, running as 'NT AUTHORITY\SYSTEM'. Waiting (plus a few extra seconds)...
VERBOSE: Task is assumed to have run. Output logged:
Hi, I'm running at 01/11/2023 17:06:04
 * as WORKSTATION1$ (whose home dir. is 'C:\Windows\system32\config\systemprofile')
 * in 'C:\Windows\system32'
 * ELEVATED.

Последние 4 строки — это вывод функции модуля (Get-Foo), доказывающий, что модуль был успешно импортирован в контексте задачи.

Большое спасибо, только что закончил читать это полностью, и это так информативно и поучительно.

Jameschad 12.01.2023 13:46

Другие вопросы по теме