Shell

#1 Используем SEP для борьбы с локальными администраторами

В этой теме 3 сообщения

У меня часто спрашивают - а что НЕ умеет твой SEP? Часто этот вопрос вводит в ступор, потому как по сути SEP дает мне довольно таки огромный потенциал разрешения моих задач и целей.

Итак, ближе к сути: Нужно вылавливать не лигитимных пользователей, которым не разрешено быть в группе локальных администраторов.

Для этого мной решено использовать:

1) vbscript который будет запускаться в политике Host Integrity по расписанию и записывать данные в БД на SQL в центральном офисе.

2) собственно, саму отдельную БД на SQL 2008

3) обрабатывающие процедуры.

В скрипте сразу закладывается логика - какие пользователи разрешены (экономлю трафик), на каких компьютерах (по MAC, ибо много у которых меняется IP) не запускать скрипт.

Итак, делаем новую политику в Host Integrity, выбираем Custom Requirements. Все далее как на скриншоте ниже (в окне имени файла вводим любое имя.vbs, ставим удаление скрипта после его исполнения (скрипт будет во временной директории ОС), в строке выполнения команды пишем cscript %F%)

2f258c21605f.jpg

Теперь редактируем под себя и вставляем сам скрипт:

'НЕ ЗАПУСКАТЬ НА СЕРВЕРАХ И КОНТРОЛЛЕРАХ ДОМЕНА!'или убрать сначала блокировку учеток в группе админов...'On  Error Resume  Nexterrors = 0 'выставляем счетчик для результата в host integritySet objRun = CreateObject("wscript.Shell")strUserName = objRun.ExpandEnvironmentStrings("%USERNAME%")Dim strComputer, member, strUsername, IsMemberDim grp, obj, objRunstrComputer = "."'объявляем массив разрешенных имен пользователейdim AllowUsersAllowUsers = "Administrator,Администратор,shell,Boss"AllowUsers = Split(AllowUsers,",")'объявляем массив разрешенных локальных пользователейdim LocalAccountsLocalAccounts = "Administrator,Администратор"LocalAccounts = Split(LocalAccounts,",")'объявляем массив mac-адресов не подлежащих проверке.dim MacAddressesMacAddresses = "00:21:9b:e5:76:f8,00:26:2d:81:70:70,00:0e:a6:f5:41:fb"'00:23:54:BD:F3:08 MyMacAddresses = Split(MacAddresses,",")'задаем параиетры соединения с БДSet objConn = CreateObject("ADODB.Connection")Set objRecordset = CreateObject("ADODB.Recordset")Set objRecordsetLast = CreateObject("ADODB.Recordset")Set objRecordsetChange = CreateObject("ADODB.Recordset")ServerName = "10.0.0.2" 'имя или IP-адрес сервераDSN = "LocalAdmins" 'имя базы данныхUID = "vbs" 'логин пользователя SQL-сервераPWD = "Sfgs%4F#D" 'пароль пользователя SQL-сервераConnectString = "Provider=SQLOLEDB;" & _                "Data Source=" & ServerName & _                ";Initial Catalog=" & DSN & _                ";UID=" & UID & ";PWD=" & PWDobjConn.ConnectionString = ConnectStringobjConn.ConnectionTimeOut = 15objConn.CommandTimeout = 30'получаем имя компаSet WshNetwork = WScript.CreateObject("WScript.Network")'WScript.Echo " " &WshNetwork.ComputerName CompName = LCase(WshNetwork.ComputerName)'получаем полное имя доменаSet objSystemInfo = CreateObject("ADSystemInfo") 'wscript.echo objSystemInfo.DomainDNSNameDomainName = LCase(objSystemInfo.DomainDNSName)'получаем IP и MACSet objWMIService = GetObject( _     "winmgmts:\\" & strComputer & "\root\cimv2")Set IPConfigSet = objWMIService.ExecQuery _("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True")For Each IPConfig in IPConfigSet    If Not IsNull(IPConfig.IPAddress) Then         For i=LBound(IPConfig.IPAddress) _            to UBound(IPConfig.IPAddress)                If Not (IPConfig.IPAddress(i)="0.0.0.0") Then            IPAddress = IPAddr + IPConfig.IPAddress(i)            MACAddress = IPConfig.MACAddress            'Wscript.Echo "IP Address: " & IPAddress & " MACAddress: " & IPConfig.MACAddress                End if        Nextend ifnext'проверяем mac-адреса на исключенияFor Each address in MacAddresses    If LCase(address) = LCase(MACAddress) then    'Wscript.echo "Этот компьютер находится в исключениях проверки по критерию MAC"    Wscript.quit(0) 'и завершаем скрипт если MAC перечислен    Exit for    End ifNext'проверяем не заблокирован ли пользовательFunction dis(Username)    Set Accounts = GetObject("WinNT://" & strComputer & "")    Accounts.Filter = Array("user")        For each user in Accounts            If LCase(user.Name) = LCase(Username) then                If user.AccountDisabled = False then                dis = 0                'wscript.echo "Пользователь " & Username & " Не заблокирован"                Else                dis = 1                'wscript.echo "Пользователь " & Username & " Уже блокирован"                exit for                end if            end if        nextEnd function'ищем группу администраторов и проверяем её членовSet colGroups = GetObject("WinNT://" & strComputer & "") 'UPcolGroups.Filter = Array("group")Dim Result ()ReDim Result(1)For Each objGroup In colGroups    If  objGroup.Name = "Administrators" or objGroup.Name ="Администраторы" Then          i=0        For Each objUser in objGroup.Members                'проверяем языковое соответствие учетных записей администраторов                   if LCase(objUser.Name) = "administrators" and LCase(objGroup.Name) = "администраторы" or LCase(objUser.Name) = "администратор" and LCase(objGroup.Name) = "administrators" then                    Set ExistLocalAccounts = GetObject("WinNT://" & strComputer & "")                    ExistLocalAccounts.Filter = Array("user")                        For Each user In ExistLocalAccounts                            For Each allowuser In LocalAccounts                            c = 0                                If LCase(user.Name) = LCase(allowuser) then exit for                                    If user.AccountDisabled = False then                                    notallowaccs = user.Name                            c = 1                                    end if                        next                            if c = 1 then                            'wscript.Echo "Итог: НЕТ В БАЗЕ ЛОКАЛЬНОГО ПОЛЬЗОВАТЕЛЯ " & notallowaccs & " <--- Незаблокирован"                            'user.AccountDisabled = True                            'user.SetInfo                            errors = 1                            end if                                    Next                    Disabled = dis(objUser.Name)                    'wscript.echo "Обнаружено языковое несоответствие учетной записи администраторов"                    objConn.Open                    Set objRecordset = objConn.Execute("insert into CommonAdmins (CompName,DomainName,IPAddress,MacAddress,UserName,Disabled,GroupName,date) values ('" & CompName &"','"& DomainName &"','"& IPAddress &"','"& MACAddress &"','" & objUser.Name & "','"& Disabled &"','"& objGroup.Name &"', getdate())")                    objConn.Close                 end if         GroupName = objGroup.Name         IsMember = objUser.Name         Result(i)=IsMember         i=i+1         ReDim Preserve Result(i)         Next     End IfNextReDim Preserve Result(i-1)'сравниваем полученный массив пользователей-админов с разрешенными локальными админами.for each adminuser in Result    for each admins in AllowUsers     x = 0     if LCase(adminuser) = LCase(admins) then exit for    x = 1    next        if x = 1 then        isMember = adminuser        'WScript.Echo "Итог: НЕТ В БАЗЕ " & IsMember        errors = 1        Disabled = dis(IsMember)        objConn.Open        Set objRecordset = objConn.Execute("insert into CommonAdmins (CompName,DomainName,IPAddress,MACAddress,UserName,Disabled,GroupName,date) values ('" & CompName &"','"& DomainName &"','"& IPAddress &"','"& MACAddress &"','" & IsMember & "','"& Disabled &"','"& GroupName &"', getdate())")        objConn.Close         end ifnextIf errors = 1 Then   'WScript.echo "Выходим с кодом 1 для Host Integrity"        WScript.Quit(1) ' --- Quit with errorsElse    WScript.Quit(0) ' --- Quit with not errorsEnd If

Теперь готовим саму БД.

Делаем отдельную БД (или изменяем в параметрах скрипта ниже и выше на свои) с именем LocalAdmins. В ней создадим маленькую табличку

USE [LocalAdmins]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE TABLE [dbo].[CommonAdmins](    [iPAddress] [varchar](15) NULL,    [MACAddress] [varchar](17) NULL,    [userName] [varchar](128) NULL,    [Disabled] [nchar](10) NULL,    [GroupName] [varchar](50) NULL,    [Date] [datetime] NULL,    [incRegister] [int] NOT NULL,    [DomainName] [varchar](128) NULL,    [CompName] [varchar](128) NULL) ON [PRIMARY]GOSET ANSI_PADDING OFFGOALTER TABLE [dbo].[CommonAdmins] ADD  CONSTRAINT [DF_CommonAdmins_UserName]  DEFAULT (NULL) FOR [userName]GOALTER TABLE [dbo].[CommonAdmins] ADD  CONSTRAINT [DF_CommonAdmins_Disabled]  DEFAULT (NULL) FOR [Disabled]GOALTER TABLE [dbo].[CommonAdmins] ADD  CONSTRAINT [DF_CommonAdmins_IncRegister]  DEFAULT ((0)) FOR [incRegister]GO

Теперь создадим 2 процедуры. Как и в предыдущей теме, я использую две процедуры. Первая будет работать по таблице, вторая - отсылать письма по подготовленным критериям и уже отфильтрованной таблице первой процедурой.

Первая процедура :

Use LocalAdmins;GOAlter PROCEDURE Clean_LocalAdminsASBEGINDECLARE @comp varchar(128), @domain varchar(128), @ip varchar(15), @users varchar(128),@group varchar(50), @date datetime, @inc int;DECLARE LACursor0 CURSOR LOCAL FOR SELECT DISTINCT CompName,DomainName,convert(varchar(15),IPAddress),UserName,GroupName,Date,IncRegister  FROM CommonAdminsorder by dateDECLARE @count int--Заменяем IP в случае выдачи скриптом из диапазона Reserved\BcastUpdate CommonAdminsSet IPAddress = 'APIPA'Where IPAddress like '%169.254.%'--меняем домен для корректной регистрации объекта инцидентаUpdate CommonAdminsSet DomainName = 'sk.domain.gk'where IPAddress like '%10.1.2.%' or IPAddress like '%10.1.1.%' or IPAddress like '%10.1.3.%'Update CommonAdminsSet DomainName = 'office.domain.gk'where IPAddress like '%10.0.17.%' or IPAddress like '%10.0.18.%'--иногда, увы скрипт не отрабатывает из за выключения питания или потери канала. Удаляем неполные данныеDELETE from CommonAdminswhere (IPAddress is NULL and MACAddress is NULL) or UserName is NULL and (GroupName is NULL)    OPEN LACursor0    FETCH NEXT FROM LACursor0 INTO @comp,@domain,@ip,@users,@group,@date,@incWHILE @@FETCH_STATUS = 0    BEGIN--считаем количество новых записей - если есть новые, делаем их актуальными, увеличиваем инкремент (IncRegister) чтобы потом контролировать--отсылку письма    Select @count = COUNT(*) from CommonAdminsWhere CompName = @comp and DomainName = @domain and convert(varchar(15),IPAddress) = @ip and UserName = @users and GroupName = @group        if @count > 1 --or @count =  0        BEGIN        Update CommonAdmins        SET IncRegister = + @count        WHERE CompName = @comp and DomainName = @domain and convert(varchar(15),IPAddress) = @ip and UserName = @users and GroupName = @group        Delete from CommonAdmins where CompName = @comp and DomainName = @domain and UserName = @users and GroupName = @group and Date < @date        END            FETCH NEXT FROM LACursor0 INTO @comp,@domain,@ip,@users,@group,@date,@inc    END;        CLOSE LACursor0;    DEALLOCATE LACursor0;--удаляем неактуальные данные, старее 120 часов :)Delete from CommonAdmins where Date < DATEADD (HOUR, -120, getdate())ENDGO

Вторая процедура, которая будет отсылать письмо

-- ================================================Use LocalAdmins;GOAlter PROCEDURE IncMailASBEGINDECLARE @comp varchar(128), @domain varchar(128), @ip varchar(15), @users varchar(128),@group varchar(50), @date datetime, @inc intDECLARE LACursor1 CURSOR LOCAL FOR SELECT CompName,DomainName,IPAddress,UserName,GroupName,Date,IncRegister FROM CommonAdmins ORDER by UserNameDECLARE @xml NVARCHAR(MAX)DECLARE @body NVARCHAR(MAX)DECLARE @dopsubj varchar(10)--создаем отчеты    OPEN LACursor1    FETCH NEXT FROM LACursor1 INTO @comp,@domain,@ip,@users,@group,@date,@incWHILE @@FETCH_STATUS = 0    BEGIN        --PRINT @comp + @domain + @ip + @users + @group + CONVERT(VARCHAR, @date, 104)    --SELECT @comp + ', '+ @domain + ', '+ @ip + ', ' + @users + ', ' + @group + ', ' + CONVERT(VARCHAR, @date, 102)+ ', '+ CONVERT(VARCHAR, @date, 8) + ', ' + @inc                IF (@inc = 0 or @inc > 120)    and @users not like 'S-1-5-21%'        BEGIN     -- готовим письмо и отсылаем            if @inc >= 120            BEGIN            SET @dopsubj = ' ПОВТОРНО '            END            ELSE            SET @dopsubj = ' '                        --Оформляем и пишем письмо        SET @body ='Инцидент ' + @dopsubj + ' по классу информационная безопасность по объекту ' + @domain + ' "Пользователь - локальный администратор".        Пользователь ' + @users + ' на АРМ ' + @comp + ' с IP адресом ' + @ip +'  - локальный администратор ' + ' (Обнаружено событие ' + convert(varchar(24),@date) + ' по Мск).        Необходимо:1) В аттаче к инциденту прикрепить письменную объяснительную ИТ специалиста по факту инцидента.2) Обеспечить функционирование ПО без повышенных привилегий.3) Удалить пользователя из локальных администраторов.                            Письмо создано автоматически.                В группе локальных администраторов должны быть только следующие учетные записи:1)    2)3)'DECLARE @subj varchar(128)= 'Локальный администратор ' + ' Пользователь - локальный администратор. '+ ' Object: ' + @domain + ' '        EXEC msdb.dbo.sp_send_dbmail        @recipients=N'[email protected]',        @copy_recipients =N'ваш_емайл@company.ru',        @body = @body,        @body_format = 'TEXT',        @subject [email protected],        @profile_name = 'Database Mail'        END--обновляем данные о том что инцидент выслан по данному пользователю        Update CommonAdmins        Set IncRegister = @inc + 1        Where CompName = @comp and UserName = @users and GroupName = @group        FETCH NEXT FROM LACursor1 INTO @comp,@domain,@ip,@users,@group,@date,@inc    END;        CLOSE LACursor1;    DEALLOCATE LACursor1;ENDGO

Ставим шедуллер в SQL Agent на вызов этих процедур

Use LocalAdmins;GOexec Clean_LocalAdminsexec IncMail

Выше описанный метод оттестирован (в настоящее время маленькие доработки) и работоспособен.

Минусы? Конечно есть что я просто физически не успеваю реализовать. Например, то что скрипт получает имя пользователей в несовсем удобном формате (нет приставки Domain\User или Computer\User - есть возможность обдурить скрипт :) , не отмечаются группа или пользователь ну и так, по мелочи)

В скриптах есть заремаренные дополнительные функции которые вы можете открыть если нужно (например, автоматическая блокировка учетной записи - аккуратнее с этим на серверах, т.к. блокируются и IIS_\IWAM_ - внесите сначала все то что нужно).

На вопросы отвечу позже, через пару неделек ;)

P.S. не забудьте создать пользователя vbs с паролем указанным в скрипте. Только дайте ему права минимальные на БД.

  • Upvote 15

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я в восхищении. Теоретически, конечно, это можно решить другими средствами, но интеграция в SEP - это замечательно.

Сами выработали практику? Читая документацию как-то не доводилось сталкиваться с подобными решениями.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Я в восхищении. Теоретически, конечно, это можно решить другими средствами, но интеграция в SEP - это замечательно.

Сами выработали практику? Читая документацию как-то не доводилось сталкиваться с подобными решениями.

Да, приходится вырабатывать коленочные решения :) На групповые политики не приходится рассчитывать так как поддоменов море и нужно учитывать человеческий фактор :)

В планах потом скрипт перегнать на c++\c# и доработать немного. В данное время не успеваю - нужно было что то временное но работающее сделать.

Еще один вопрос не решенным остался - не получилось вернуть из скрипта код ошибки для host integrity. К примеру, если локальные админы найдены - вернуть host complince error...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Создайте учетную запись или войдите, чтобы комментировать

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!


Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.


Войти с помощью Facebook Войти Войти с помощью Twitter
Anti-Malware.ru Вконтакте   Anti-Malware.ru в Facebook   Anti-Malware.ru в Twitter   Anti-Malware.ru в LinkedIn   RSS
  • Сообщения

    • santy
      RP55, смысл добавления для dll статуса "в автозапуске"? данный dll запускается только в том случае, если запущен исходный exe в образ автозапуска этот файл попадает, в списке загружаемых dll он есть, C:\USERS\POWER\APPDATA\ROAMING\GOOGLEUPDATE.DLL файл проверен при создании образа автозапуска и помечен как "НЕИЗВЕСТНЫЙ". В итоге Uvs присваивает ему статус: АКТИВНЫЙ ПОДОЗРИТЕЛЬНЫЙ DLL по этому статусу можно добавить критерий, чтобы подобные файлики попадали в отсек "ВИРУСЫ и подозрительные" для последующего анализа. (СТАТУС ~ АКТИВНЫЙ ПОДОЗРИТЕЛЬНЫЙ DLL )(1) [auto (0)]  
    • Marina35
      Одним вирусом меньше https://dr-world.ru/fbr-zaderjala-komputershika-symevshego-naiti-kluch-k-wannacry/
    • PR55.RP55
        По крайне мере некоторые устаревшие версии файла способны запускать любые соответствующие файлы\библиотеки Так например легальный\подлинный файл: GOOGLEUPDATE.EXE  прописывается в автозапуск. В каталог с файлом GOOGLEUPDATE.EXE помещается файл:  GOOPDATE.DLL Файл:  GOOPDATE.DLL  не имеет подписи - или подписан левым сертификатом и может иметь статус скрытый\системный и т.д. Таким образом файл GOOPDATE.DLL в автозапуске... А вот в логах его в автозапуске не будет. ---------- Нужно доработать uVS и считать все файлы: GOOGLEUPDATE.EXE  +++ как находящиеся в автозапуске. Тем более, что случай исключительный.    
    • AM_Bot
      Генеральный директор ГК «ИНТЕЛЛЕКТУАЛЬНАЯ БЕЗОПАСНОСТЬ» Руслан Рахметов рассказал читателям Anti-Malware.ru о рынке SGRC и IRP, истории бренда Security Vision и порассуждал о том, какой должна быть первоклассная SGRC-система. Читать далее
    • Draft