блогъ

отслеживание попыток доступа по rdp

скрипт, наглядно выводящий форматированные время, IP-адреса и имена хостов, с которых неудачно пытались подключиться к Windows 2003 RDP-серверу согласно виндовому журналу событий. Для отслеживания таких попыток, необходимо включить аудит отказов во входе в систему для локальной политики аудита в параметрах безопасности (делается через оснастку secpol.msc, например). Скрипт будет полезен для открытых кишками наружу серверов терминалов.

В скрипте сразу предусмотрена возможность не выводить определенные адреса/имена хостов, или целые «диапазоны» (сравниваются строки а не маски).

'Event code 529
'кодировка ISO 8859-2
'Event code 529
'
'(0)  Сбой входа в систему:
'(1)  Причина:	неизвестное имя пользователя или неверный пароль
'(2)  Пользователь:	user
'(3)  Домен:		Domain
'(4)  Тип входа:	7
'(5)  Процесс входа:	User32  
'(6)  Пакет проверки:	Negotiate
'(7)  Рабочая станция:	workstation
'(8)  Имя вызывающего пользователя:	user$
'(9)  Домен вызывающего:	Domain
'(10) Код входа вызывающего:	(0x0,0x3E7)
'(11) Код процесса вызывающего:	2804
'(12) Промежуточные службы:	-
'(13) Адрес сети источника: 127.0.0.1
'(14) Порт источника: 123456

Dim ArrayOfValues(14)

Dim ArrayOfIPExclusions(2)
ArrayOfIPExclusions(0) = "192.168.0."
ArrayOfIPExclusions(1) = "10.0."
ArrayOfIPExclusions(2) = "10.10.10."

Dim ArrayOfHOSTExclusions(0)
ArrayOfHOSTExclusions(0) = "admin.max.org.ua"

Set HOSTSDictionary = CreateObject("Scripting.Dictionary")

strComputer = "."
set objShell = createobject("wscript.shell")
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set dtmStartDate = CreateObject("WbemScripting.SWbemDateTime")
Set dtmEndDate = CreateObject("WbemScripting.SWbemDateTime")

DateStart = Now() - 120
DateStop = Now()
dtmStartDate.SetVarDate DateStart, True
dtmEndDate.SetVarDate DateStop, True

Set colLoggedEvents = objWMIService.ExecQuery _
    ("Select * from Win32_NTLogEvent Where Logfile = 'Security' AND EventCode = '529' AND EventType = 5 AND TimeWritten >= '" _
    & dtmStartDate & "' AND TimeWritten  "" then
      
        SplittedRow = Split(row, ":")
        ArrayOfValues(currentValue) = Trim(Replace(SplittedRow(1), Chr(9), ""))
        currentValue = currentValue + 1
      
      end if

    Next
    
    IPExistsInExclusions = 0
    IP = ArrayOfValues(13) 
    
    'сравним со списком IP адресов, которые исключаем из вывода скрипта
    for each row in ArrayOfIPExclusions
    
      if InStr(IP, row) > 0 then
      
        IPExistsInExclusions = 1
        exit for
      
      end if
    
    next

    if IPExistsInExclusions = 0 then
      
      HOSTExistsInExclusions = 0
      
      'если IP содержит лишние знаки имя хоста узнавать не будем
      strhost = " "
      if objRegEx.Replace(IP, "") = "..." then 
      
        'проверим, не получали ли мы имя хоста по этому IP раньше
        if HOSTSDictionary.Exists(IP) = false then
      
          'http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/f21292fd-e9d7-4a57-a14e-31461aeab905/
          strParams = "%comspec% /c nslookup " & IP
          Set objExecObj = objShell.exec(strParams)
      
          do while not objExecObj.StdOut.AtEndOfStream
            strText = objExecObj.StdOut.Readline()
            if instr(strText, "Server") then 
              strServer = trim(replace(strText,"Server:",""))
            elseif instr (strText, "Name") Then
              strhost = trim(replace(strText,"Name:",""))
            end if
          loop

          HOSTSDictionary.Add IP, strhost
        
        'если получали - просто подставим это имя хоста
        else HOSTSDictionary.Exists(IP)
      
          strhost = HOSTSDictionary.Item(IP)
      
        end if

        'сравним со списком хостов, которые исключаем из вывода скрипта
        for each row in ArrayOfHOSTExclusions
      
         if InStr(LCase(strhost), row) > 0 then
      
            HOSTExistsInExclusions = 1
            exit for
      
          end if
      
        next

      end if
     
      if HOSTExistsInExclusions = 0 then
      
        IP = IP & Left("               ", 15 - Len(IP))
        strhost = strhost & Left("                                       ", 40 - Len(strhost))
        Wscript.Echo objDay & "." & objMonth & "." & objYear & " " & Mid(objEvent.TimeWritten, 9, 2) & ":" & Mid(objEvent.TimeWritten, 11, 2) & ":" & Mid(objEvent.TimeWritten, 13, 2) & "; IP: " & IP & " (" & strhost & "); user: " & ArrayOfValues(2)
      
      end if
      
    end if

    'Wscript.Echo "Record Number: " & objEvent.RecordNumber
    'Wscript.Echo "Source Name: " & objEvent.SourceName
    'Wscript.Echo "Time Written: " & objEvent.TimeWritten
    'Wscript.Echo "Event Type: " & objEvent.Type
    'Wscript.Echo "User: " & objEvent.User
    
Next

скачать: rdp.vbs (4278 Загрузок)

результатом выполнения такого скрипта из командной строки «cscript rdp.vbs > rdp.txt», будет файл, примерно такого содержания:

01.12.2012 13:53:25; IP: xx.xx.xx.xx     (xx.xx.xx.xx.internet.net              ); user: Администратор
01.12.2012 12:45:30; IP: xx.xx.xx.xx     (xx.xx.xx.xx.internet.net              ); user: Администратор
23.11.2012 18:06:23; IP: xx.xx.xx.xx     (xx-xx-xx-xx-gprs.telefona.net     ); user: user2
20.11.2012 14:25:25; IP: xx.xx.xx.xx     (xx-xx-xx-xx-gprs.telefona.net     ); user: user1
19.11.2012 17:48:20; IP: xx.xx.xx.xx     (server17.max.org.ua                  ); user: Администратор

подчеркну, что скрипт необходимо сохранять в кодировке ISO 8859-2, или же скачать готовый файл выше.

кстати, хорошей идеей было бы прикручивание утилиты Whois от Марка Руссиновича, которая отображала бы данные по IP адресу в той же строке. Велкам в комментарии 🙂

UPD 05.12.12. Прикрутил получение имени хоста по IP если оно доступно, а также возможность исключить из вывода определенные имена хостов. Текст скрипта а также файл обновлены.

UPD 13.09.13. Добавил в запрос выборку в определенном интервале дат. В примере выбираются события за последние 120 дней. Оптимизировал процесс получения имени хоста — если оно уже было получено для IP-адреса то повторно запрашиваться не будет, а будет взято из соответствия. Также предусмотрел ситуацию, когда в поле IP события может попасть вовсе не IP-адрес. Также, из-за отбора в диапазоне дат данные в результат выводятся в возрастающем порядке, т.е. последние события будут в конце файла, что не очень удобно. Добавил комментарии в код.

VN:F [1.8.8_1072]
обождите...
Rating: 4.3/5 (3 votes cast)
отслеживание попыток доступа по rdp4.353