Powershell unauthorized access
My PowerShell sensor returns an error message. What can I do?
When I add a Windows Updates Status (PowerShell) sensor to my PRTG installation, an error message appears.
The error message is “An unknown security error occurred”. The connection to the remote server failed and WinRM is unable to process the request. There seems to be an issue with Kerberos authentication.
The error message is «No Logon Servers Available«.
The error message is «Unauthorized Access«.
I also get this error message after creating other PowerShell sensors. What can I do?
Last change on May 21, 2019 5:37:37 AM by Maike Behnsen [Paessler Support]
4 Replies
This article applies to PRTG Network Monitor 19 or later
Tips for Running Sensors Using PowerShell Scripts
There are a few things to consider when using PowerShell sensors. This applies to pre-configured sensors, for example, the Windows Updates Status sensor, as well as to custom sensors that execute a PowerShell script, for example, the EXE/Script Advanced sensor. Please see below for possible resolution steps for PowerShell errors.
«Unknown Security Error» with PowerShell Sensors
If you add a PowerShell sensor to your PRTG installation, you may sometimes get an error message as given below (or similar). However, your computers are in the domain and credentials are valid.
In this case, use the FQDN (Fully Qualified Domain Name) instead of the IP address. You can specify the FQDN in the IPv4 Address/DNS Name field in the settings of the sensor’s parent device.
Error Message:
Connecting to remote server failed with the following error message: WinRM cannot process the request. The following error occurred while using Kerberos authentication: Unknown security error. Possible causes are: -The user name or password specified are invalid. -Kerberos is used when no authentication method and no user name are specified. -Kerberos accepts domain user names, but not local user names. -The Service Principal Name (SPN) for the remote computer name and port does not exist. -The client and remote computers are in different domains and there is no trust between the two domains. After checking for the above issues, try the following: -Check the Event Viewer for events related to authentication. -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport. Note that computers in the TrustedHosts list might not be authenticated. -For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
«No Logon Servers Available» with PowerShell Sensors
If WinRM cannot process the request and you get a No Logon Servers Available error, see I get the error «WinRM cannot process the request» when I try to use a Powershell Sensor.
«Unauthorized Access» with PowerShell Sensors
64-bit Windows systems run two PowerShell versions, the 64-bit and the 32-bit PowerShell version. Because PRTG calls the 32-bit PowerShell version, make sure that you set the correct execution policy not only for the 64-bit version, but also for the 32-bit version. The execution policy should be unrestricted: Set-ExecutionPolicy Unrestricted Otherwise, your PowerShell sensors will throw the error message Unauthorized Access. For more information, see Powershell 32bit or 64bit and Execution Policy.
Note: The user context may be different when the script is executed by the PRTG probe (this is the «LOCAL SYSTEM» account by default) and not by your Windows account when manually running the script.
Last change on Jul 12, 2019 8:22:14 AM by Maike Behnsen [Paessler Support]
PowerShell: Выполнение сценариев отключено в этой системе
В операционной системе Windows 10 имеется мощный инструмент для управления и выполнения различных задач — это PowerShell. Эта консоль предназначена для администраторов, поскольку она позволяет им контролировать всю операционную систему с помощью сценариев (script). PowerShell используется многими фоновыми приложениями для внесения изменений в систему и это ставит под угрозу безопасность нашего ПК.
Сценарий (script) — простая программа написана в коде, который работает линейно на нашем компьютере. Мы можем создавать и выполнять собственные сценарии для автоматизации задач, или приложения могут выполнять их для выполнения определенных конфигураций и задач. По умолчанию Windows 10 не запрещает ни приложениям, ни нам запускать сценарии в системе, если они подписаны или являются «своими». Проблема возникает, когда мы запускаем свой скрипт, и нам выдает ошибку «Выполнение сценариев отключено в этой системе«. Это многоуровневая мера безопасности в PowerShell, которая предотвращает запуск вредоносных сценариев и может нанести вред системе. Давайте разберем, как изменить политики безопасности для PowerShell.
Политики выполнения скриптов в PowerShell
Если вы увидели ошибку «Выполнение сценариев отключено в этой системе«, то можем проверить конфигурацию политик для запуска сценариев, которые настроены в Windows 10. Откройте PowerShell от имени администратора и:
- Get-ExecutionPolicy -List
Мы можем видеть несколько уровней разрешений политик для запуска сценариев.
Чтобы изменить политику запуска скрипта, вы должны знать различные уровни привилегий, которые мы можем назначить каждому из областей.
- Restricted: заблокировано выполнение любых скриптов, но разрешается работа интерактивных команд.
- RemoteSigned: загруженные скрипты должны быть подписаны доверенным издателем. Локальные скрипты работают без подписи
- AllSigned: разрешает выполнение любого подписанного скрипта, как локального, так и удаленного (загруженного).
- Unrestricted: без ограничений. Вы можете запустить все сценарии, даже те, которые не подписаны.
Когда вы знаете условия и ограничения скриптов, то можете изменить их. К примеру, чтобы исправить ошибку «Выполнение сценариев отключено в этой системе» достаточно ввести один апплет. Откройте PowerShell от имени админа и:
- Set-ExecutionPolicy Unrestricted -Scope CurrentUser — запуск без ограничения для пользователя.
- Set-ExecutionPolicyRestricted -Scope CurrentUser вернуть назад, если будет нужно.
Разрешает без ограничений выполнять сценарии для локального пользователя. Ключ -Scope определяет, к чему применяется изменение политики. Когда вы вводите «CurrentUser«, то применяется только к текущему пользователю, а когда вы вводите «LocalMachine«, он применяется ко всей системе.
Если выше способ не помог вам запустить свой скрипт и ошибка «Выполнение сценариев отключено в этой системе» появляется, то можно снять полностью ограничения. Вы должны понимать, что это большой риск и ваш скрипт должен быть безопасен на 101%. Откройте PowerShell от имени админа и:
- Set-ExecutionPolicy Unrestricted — разрешить выполнение скриптов без ограничений.
- Set-ExecutionPolicy Restricted — вернуть назад по умолчанию.
Создание и изменение в Powershell NTFS разрешений ACL
Основной способ ограничения доступа к файлам и папкам дает файловая система NTFS с ее таблицами ACL. Это может быть право только на чтение файла (открытие и просмотр), на чтение и запись (открытие, просмотр, изменение и сохранение) и многие другие. Такие права мы чаще устанавливаем через GUI назначая права не конечному пользователю, а группе в которой он состоит. Все действия по созданию и изменению мы так же можем сделать через Powershell.
Навигация по посту:
На мой взгляд использование консоли Powershell лишнее при выдаче таких прав. Риск совершить ошибку в консоли намного выше, чем при работе в GUI, да и время для написания команды уйдет больше. Есть специфичные задачи, например в виде аудита или перенос прав где Powershell очень поможет.
Основы разрешений
ACL (access controll list) — делится на два вида:
- SACL (System Access Control List) — используется для аудита;
- DACL (Discretionary Access Control List) — используется для выдачи и проверки разрешений пользователям и группам.
Оба этих типа разрешений хранятся в специальной таблице MFT (Master File Table).
Основное средство для редактирования этих разрешений в GUI можно увидеть зайдя в свойства файла или папки:
В области 4 выделены следующие разрешения:
- Read — открытие файла и папки;
- List folder contents — открытие папки;
- Write — создание файлов и папок и их изменение;
- Read & Execute — открытие и запуск исполняемых файлов;
- Modify — открытие, создание, изменение и удаление файлов и папок;
- Full Control — включает разрешения modify, а так же управление разрешениями файла или папки.
Чаще всего мы работаем с разрешениями выше, но есть еще один список с возможностью настройки прав более тонко:
Как можно догадаться — разрешения указанные в области 1 это просто набор нескольких правил из области 3. Их так же еще называют «Premission Sets» и «Special Premissions».
Групповые разрешения могут принимать флаги Allow и Deny, которые разрешат или запретят указанные действия. Указывать разрешения для пользователей через Deny считается плохой практикой и практически не используется.
Кроме этого существует наследование:
Наследование помогает установить разрешения для одной папки так, что оно будет применяться ко вложенным файлам и папкам. Если наследование отключить (2), то у нас будет возможность убрать все наследуемые разрешения или оставить их.
Функции по работе со строками в Powershell
Получение текущих разрешений в Powershell
На примере ниже я верну разрешения для папки «C:TestFolder»
В области 1 выделен владелец папки, а под областью 2 отображаются все группы и пользователи с правами.
Мы можем проверять права не только локальной, но и сетевой папки. На примере ниже возвращена та же папка:
Поиск всех папок с правами у определенной группы
Представим, что мы хотим проверить права данные определенной группе. Мы можем заходить в свойства каждой папки и смотреть вкладку «Безопасности», а можем сделать это через Powershell.
Обычно у нас есть какой-то каталог с общим доступом с папками внутри, на которые мы выдаем разрешения. В моем случае такой каталог «Moscow», а на папки внутри я уже даю права:
В следующем примере я узнаю на какие папки установлены разрешения для TestGroup:
Изменение, копирование и добавление разрешений
Еще одна причина использовать Powershell — это возможность копирования разрешений. Например так я поставлю разрешения для папки Folder2 такие же, как и Folder2:
Возможности добавить нового пользователя в список ACL или изменить его права одним командлетом у нас нет. В обоих случаях мы должны будет создавать копию объекта ACL, изменять ее отдельным классом, а затем применять используя метод. Сам объект, который мы получаем через Get-ACL, имеет множество методов:
Для создания нового объекта с правами используется класс «FileSystemAccessRule», который в команде будет выглядеть так:
Расшифровать значения можно следующим образом:
- IdentityReferenceString — пользователь или группа формата «DOMAINAdministrator»;
- FileSystemRights — сами разрешения, например «Read»;
- InheritanceFlags и PropagationFlags — определяют наследование. Например вы можете сделать так, что папки внутри указанной будут наследовать разрешения, а файлы нет. Ниже будут приведены несколько примеров. Более подробно об этом можно почитать на сайте Microsoft;
- AccessCpmtrolType — разрешить или запретить (Allow/Deny).
Изменение и добавление прав у пользователя и групп
Допустим у нас есть пользователь «Test User (001)» с возможностью чтения папки «Folder1» и мы хотим добавить еще права на запись. Это будет выглядеть так:
Наследование типа ‘ContainerInherit, ObjectInherit’ говорит о том, что оно касается этой папки и всех вложенных папок и файлов.
Таким же образом работает добавление новой группы или пользователя в список ACL:
Права, которые мы можем дать имеют сокращенное название и они отображены далее:
У вас может быть много ошибок связанных с созданием класса с новыми разрешениями. Я бы советовал выводить существующие права и сравнивал бы их с новыми — это позволит снизить вероятность ошибок.
При этом вы можете применить набор разрешений, например в виде Write, но результат будет отображаться в виде «Special Premission»:
Если бы я указал наследование в виде ‘ContainerInherit, ObjectInherit’, то права бы применились как нужно:
Поэтому я рекомендую смотреть существующие разрешения на примере того, как я сделал это выше.
Удаление прав у пользователя или группы
Для удаления всех разрешений есть метод «RemoveAccessRuleAll». Работает он так же:
Для удаления конкретного права, например только возможность чтения, есть метод «RemoveAccessRule». С этим методом у меня были проблемы после которых действующие разрешения менялись на Special и изменить эту ситуацию у меня не получилось. Если вам нужно все же убрать одно разрешение — я бы советовал удалять все разрешения у пользователя, а затем добавлять их заново. У пользователя было право на Чтение и Запись, но мне нужно было оставить только чтение:
Смена владельца
Смена владельца файла или папки делается через метод SetOwner. Этот метод, в качестве идентификатора, принимает SID пользователя и что бы его узнать нужно использовать класс «System.Security.Principal.Ntaccount». На практике это выглядит так:
Как отсортировать в Powershell объекты через Sort-Object
Включение или отключение наследования папок и файлов
Для управления наследованием используется метод «SetAccessRuleProtection», который устанавливает следующее:
- Нужно ли блокирование от родительской папки.
- Нужна ли перезапись прав.
Значения указываются в $True или $False. Например так я включу наследование и заменю существующие разрешения родительскими:
Сбор всех прав и их экспорт в CSV
Учитывая примеры выше мы можем временно собирать отчеты по выданным правам. Пример того, как может выглядеть отчет:
Powershell атрибуты пользователя. Поиск и изменение.
Одним из часто встречающихся действий, выполняемых системными администраторами, является работа с учетными записями пользователей. Давайте посмотрим, как можно быстро находить и изменять учетные записи пользователей(доменных и локальных) с помощью Powershell.
Поиск пользователей по заданным критериям. Доменные пользователи.
Для поиска доменных пользователей используется командлет Get-ADUser. Данный командлет входит в модуль ActiveDirectory. Он доступен на серверах с установленной ролью AD DS или при установке оснастки RSAT для удаленного администрирования серверов. Модуль, также, может быть установлен и отдельно из репозитория Powershell.
Чтобы найти пользователя с определенными свойствами, нужно знать какие атрибуты у него есть и как они называются в Powershell. В этом нам поможет команда:
Get-ADUser -Filter
В данном примере производится поиск пользователя с именем, заданным в переменной $Name. Вы можете указать имя пользователя явно, только лучше использовать оператор -like
Учтите, что под именем здесь имеется ввиду полное имя пользователя.
При поиске, также, можно указать сервер(контроллер домена) и учетные данные пользователя домена, которые будут использоваться для получения сведений о пользователе.
Get-ADUser -Server DC01 -Credential $domaincredential -Filter
Давайте посмотрим вывод команды:
Как видно, свойств довольно много, и по ним можно производить поиск, а также менять эти свойства. Для того, чтобы найти пользователя по любому свойству, введите его вместо(или вместе) со свойством Name, по которому мы искали пользователя.
Для того, чтобы изменить атрибуты пользователя используется командлет Set-ADUser.
Например, чтобы изменить название улицы, указанное в свойствах пользователя Семенов, можно сразу передать результат выполнения команды Get-ADUser командлету Set-ADUser:
Get-ADUser -Server DC01 -Credential $domaincredential -Filter
В результате выполнения, получим желаемый результат в свойствах пользователя:
Powershell атрибуты пользователя. Локальные пользователи.
Для работы с учетными записями локальных пользователей используется модуль Local Accounts, доступный в репозитории Powershell Gallery(как установить модули описано здесь).
Найти пользователя можно с помощью командлета Get-LocalUser.
Синтаксис отличается от Get-ADUser. По умолчанию, без параметров Get-LocalUser выводит список всех локальных пользователей на компьютере:
Для получения информации по конкретному пользователю, нужно указать его параметры. Чтобы посмотреть доступные параметры используем командлет Get-Member:
Как можно видеть, параметров у пользователя намного меньше.
И еще, здесь есть отличие от Get-ADUser, параметр Name, который в Get-ADUser обозначал полное имя пользователя, в Get-LocalUser означает логин пользователя. Убедиться в этом можно на примере конкретного пользователя. Чтобы найти пользователя по атрибуту, отличному от его логина(Name) и SID, нужно задействовать командлет Where-Object:
Изменение атрибутов производится командлетом Set-LocalUser. Например, для изменения срока действия учетной записи с 31.08.2019 на 31.12.2020 команда выглядит так:
Get-LocalUser | Where-Object AccountExpires -like 08*31*2019* | Set-LocalUser -AccountExpires 31.12.2020
Аналогично меняются и другие атрибуты(Description, Fullname и т.д.)
И еще одно замечание. Если доменного пользователя сменить пароль перед первым входом мы можем просто с помощью параметра -ChangePasswordAtLogon, то с локальными пользователями все не так. Вариант, все же есть, и он описан в этой статье.
Данные командлеты(особенно при использовании в скриптах) очень облегчат жизнь системному администратору, если приходится часто или в большом количестве менять атрибуты пользователей. Вы можете создать(получить) список пользователей и атрибуты, которые нужно изменить и «скормив» его скрипту, быстро получить требуемый результат.
Вот такая коротенькая памятка по поиску и изменению атрибутов пользователей получилась.
Еще статьи по использованию Powershell в администрировании можно посмотреть по тегу Powershell.
Защита и шифрование паролей в скриптах PowerShell
Администраторы часто при написании сценариев автоматизации на PowerShell сохраняют пароли непосредственно в теле PoSh скрипта. Как вы понимаете, это крайне небезопасно при использовании в продуктивной среде, т.к. пароль в открытом виде могут увидеть другие пользователи сервера или администраторы. Поэтому желательно использовать более безопасный метод использования паролей в скриптах PowerShell, или шифровать пароли, если нельзя пользоваться интерактивным вводом.
Безопасно можно запросить от пользователя ввести пароль в скрипте интерактивно с помощью командлета Get-Credential. Например, запросим имя и пароль пользователя и сохраним его в объекте типа PSCredential:
При обращении к свойствам переменной можно узнать имя ползователя, который был указан.
Но при попытке вывести пароль, вернется текст System.Security.SecureString, т.к. пароль теперь хранится в виде SecureString.
Объект PSCredential, который мы сохранили в переменной $Cred теперь можно использоваться в командлетах, которые поддерживают данный вид объектов.
Параметры $Cred.Username и $Cred.Password можно использовать в командлетах, которые не поддерживают объекты PSCredential, но требуют отдельного ввода имени и пароля пользователя.
Также для запроса пароля пользователя можно использовать команлет Read-Host с атрибутом AsSecureString:
$pass = Read-Host «Введите пароль» –AsSecureString
В данном случае, вы также не сможете увидеть содержимое переменной $pass, в которой хранится пароль.
В рассмотренных выше способах использования пароля в скриптах PowerShell предполагался интерактивный ввод пароля при выполнении скрипта. Но этот способ не подойдет для различных сценариев, запускаемых автоматически или через планировщик.
В этом случае удобнее зашифровать данные учетной записи (имя и пароль) и сохранить их в зашифрованном виде в текстовый файл на диске или использовать непосредственно в скрипте.
Итак, с помощью комадлета ConvertFrom-SecureString можно преобразовать пароль из формата SecureString в шифрованную строку (шифрование выполняется с помощью Windows Data Protection API — DPAPI). Вы можете вывести шифрованный пароль на экран или сохранить в файл:
$Cred.Password| ConvertFrom-SecureString | Set-Content c:pspassfile.txt
Чтобы использовать зашифрованный пароль из файла нужно выполнить обратное преобразование в формат Securestring с помощью командлета ConvertTo-SecureString:
$username = ″corpadministrator″
$pass = Get-Content c:pspassfile.txt | ConvertTo-SecureString
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pass
Таким образом в переменной $creds мы получили объект PSCredential с учетными данными пользователя.
Однако, если попробовать скопировать файл passfile.txt на другой компьютер или использовать его под другим пользователем (не тем, под которым создавался пароль), вы увидите, что переменная $creds.password пустая и не содержит пароля. Дело в том, что шифрованием с помощью DPAPI выполняется с помощью ключей, хранящихся в профиле пользователя. Без этих ключей на другом компьютере вы не сможете расшифровать файл с паролем.
ConvertTo-SecureString : Ключ не может быть использован в указанном состоянии.
«Не удается обработать аргумент, так как значением аргумента «password» является NULL.
Укажите для аргумента «password» значение, отличное от NULL.»
Таким образом, если скрипт будет запускаться под другим (сервисным) аккаунтом или на другом компьютере, необходимо использовать другой механизм шифрования, отдичный от DPAPI. Внешний ключ шифрования можно указать с помощью параметров –Key или –SecureKey.
Например, вы можете с помощью PowerShell сгенерировать 256 битный AES ключ, который можно использовать для расшифровки файла. Сохраним ключ в текстовый файл password_aes.key.
$AESKey = New-Object Byte[] 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey)
$AESKey | out-file C:pspassword_aes.key
Теперь можно сохранить пароль в файл с помощью данного ключа:
$Cred.Password| ConvertFrom-SecureString -Key (get-content C:pspassword_aes.key)| Set-Content c:pspassfile.txt
Таким образом у нас получилось два файла: файл с зашифрованным паролем (passfile.txt) и файл с ключом шифрования (password_aes.key).
Их можно перенести на другой компьютер и попытаться из PowerShell получить пароль из файла (можно разместить файл ключа в сетевом каталоге)
$pass = Get-Content c:pspassfile.txt | ConvertTo-SecureString -Key (get-content \Server1Sharepassword_aes.key)
$pass
Если не хочется заморачивать с отдельным файлом с AES ключом, можно зашить ключ шифрования прямо в скрипт. В этом случае вместо ключа в обоих случая нужно использовать
[Byte[]] $key = (1..16)
$Cred.Password| ConvertFrom-SecureString –Key $key| Set-Content c:pspassfile.txt
А для расшифровки:
[Byte[]] $key = (1..16)
$pass = Get-Content c:pspassfile.txt | ConvertTo-SecureString -Key $key
Как вы видите пароль не пустой, значит он был успешно расшифрован и может быть использован на других компьютерах.
И напоследок, самый печальный момент. Пароль из объекта PSCredential в открытом виде вытаскивается очень просто:
Можно извлечь пароль в текстовом виде и из SecureString:
Как вы понимаете, именно поэтому нежелательно сохранять пароли привилегированных учетных записей, таких как Domain Admins где бы то ни было кроме DC.