Назад | Перейти на главную страницу

Как узнать, в какое время пользователь домена вошел в систему?

В журнале событий «Безопасность» на контроллере домена Windows 2003 я вижу несколько записей о событии 540 - «Успешный вход в сеть» с интервалом в несколько минут в течение дня.

Обязательно ли первый из них для конкретного пользователя в определенный день, когда пользователь вошел в систему на своей машине?

Если нет (или даже если так), есть ли другой (лучший?) Способ узнать, в какое время пользователь вошел в систему утром?

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

Если вы ищете интерактивный вход в систему на данном клиентском компьютере, вам нужно искать длительное событие на этом клиентском компьютере. Пользователь, который входит в систему, например, с кэшированными учетными данными, не будет создавать записи в журнале событий контроллера домена. Даже если вы не ищете входа в систему с кэшированными учетными данными, настройка клиентских компьютеров на аудит событий входа в систему и просмотр журнала событий клиентского компьютера даст вам наиболее точную и удобную информацию.

В объекте пользователя AD есть атрибут, который называется Last-Logon-Timestamp. Он обновляется каждый раз, когда пользователь входит в систему, но реплицируется не чаще, чем каждые 14 дней, так как предназначен для поиска мертвых учетных записей. Его можно использовать как более точный счетчик, если вы хотите опросить каждый DC в домене для получения этой информации. Исходя из этого, вы можете отслеживать, когда пользователи аутентифицировались в домене всякий раз, когда это происходит, а не только утром.

Вы могли бы в сценарии входа в систему создать строку, которая записывает метку времени где-нибудь в файл?

Что-то вроде?

чистое время >> \ server \ logonlogs \% username% .txt

Ответ на первый вопрос из вашего заголовка «Как узнать, когда пользователь домена вошел в систему», зависит от того, на какой платформе он входит. Для Windows 2000 / XP / 2003 идентификатор события 528 с типом входа 2 покажет вам интерактивный вход в систему с локальной или доменной учетной записи. LogParser - отличный инструмент для анализа журналов событий с большого количества машин и поддерживает большое количество выходных данных. Так, например, вы можете использовать следующее для запроса журнала безопасности на удаленном компьютере и вывода в файл с разделителями табуляции:

c:>logparser.exe "select TimeGenerated, SID from \\wksname\Security where EventID = 528" -i EVT -resolveSIDs:ON -q:ON -headers:off -o:TSV >> c:\UserLogons.txt

Запрос событий из журналов безопасности в Windows Vista / 2008/7 немного отличается тем, что изменился формат файла журнала, а также идентификаторы событий. Идентификатор события 4624 с типом входа 2 покажет успешный интерактивный вход. Мы можем использовать wevtutil для запроса похожих данных и вывода их в формате XML:

c:>wevtutil qe Security /q:"*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and Task=12544 and (EventID=4624)] and EventData[Data[@Name='LogonType']='2']]" /e:Events > c:\UserLogons.xml

Что касается появления идентификатора события 540 в журналах событий безопасности на контроллере домена:

Событие 540 регистрируется по нескольким причинам. Так, например, вы можете увидеть событие с идентификатором 540 с типом входа 3, когда к общему ресурсу обращается служба сервера. Вот типы входа в систему для этого идентификатора события, предоставленные Microsoft:

2 Интерактивный Пользователь вошел в систему на этом компьютере с консоли.

3 Сеть Пользователь или компьютер вошел на этот компьютер из сети.

4 партии Пакетный тип входа в систему используется серверами пакетной обработки, где процессы могут выполняться от имени пользователя без прямого вмешательства пользователя.

5 Сервис Служба была запущена диспетчером управления службами.

7 Разблокировать Эта рабочая станция была разблокирована.

8 Сеть Очистить текст Пользователь вошел в сеть. Пароль пользователя был передан в пакет аутентификации в нехешированной форме. Встроенная проверка подлинности упаковывает все учетные данные хэша перед их отправкой по сети. Учетные данные не передаются по сети в виде открытого текста (также называемого открытым текстом).

9 NewCredentials Вызывающий клонировал свой текущий токен и указал новые учетные данные для исходящих подключений. Новый сеанс входа в систему имеет тот же локальный идентификатор, но использует другие учетные данные для других сетевых подключений.

10 RemoteInteractive Пользователь вошел в систему на этом компьютере удаленно с помощью служб терминалов или подключения к удаленному рабочему столу.

11 CachedInteractive Пользователь вошел в систему на этом компьютере с сетевыми учетными данными, которые хранились локально на компьютере. Не удалось связаться с контроллером домена для проверки учетных данных.

Хорошей охоты.

Извиняюсь за длинный пост, но это то, что я использую. Возможно, вы могли бы немного упростить это:

' **********************************************************************
' AuditUsers
' ==========
'
'  UserAccountControl
'  SCRIPT                         0x0001 1
'  ACCOUNTDISABLE                 0x0002 2
'  HOMEDIR_REQUIRED               0x0008 8
'  LOCKOUT                        0x0010 16
'  PASSWD_NOTREQD                 0x0020 32
'  PASSWD_CANT_CHANGE             0x0040 64
'  ENCRYPTED_TEXT_PWD_ALLOWED     0x0080 128
'  TEMP_DUPLICATE_ACCOUNT         0x0100 256
'  NORMAL_ACCOUNT                 0x0200 512
'  INTERDOMAIN_TRUST_ACCOUNT      0x0800 2048
'  WORKSTATION_TRUST_ACCOUNT      0x1000 4096
'  SERVER_TRUST_ACCOUNT           0x2000 8192
'  DONT_EXPIRE_PASSWORD           0x10000 65536
'  MNS_LOGON_ACCOUNT              0x20000 131072
'  SMARTCARD_REQUIRED             0x40000 262144
'  TRUSTED_FOR_DELEGATION         0x80000 524288
'  NOT_DELEGATED                  0x100000 1048576
'  USE_DES_KEY_ONLY               0x200000 2097152
'  DONT_REQ_PREAUTH               0x400000 4194304
'  PASSWORD_EXPIRED               0x800000 8388608
'  TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000 16777216
'
'  objUser.get("userAccountControl")
' **********************************************************************

option explicit

' *** Global constants

const HKEY_CLASSES_ROOT   = &H80000000
const HKEY_CURRENT_USER   = &H80000001
const HKEY_LOCAL_MACHINE  = &H80000002
const HKEY_USERS          = &H80000003
const HKEY_CURRENT_CONFIG = &H80000005

const REG_SZ        = 1
const REG_EXPAND_SZ = 2
const REG_BINARY    = 3
const REG_DWORD     = 4
const REG_MULTI_SZ  = 7

' *** User account status flags

const SCRIPT                         = &H0001
const ACCOUNTDISABLE                 = &H0002
const HOMEDIR_REQUIRED               = &H0008
const LOCKOUT                        = &H0010
const PASSWD_NOTREQD                 = &H0020
const PASSWD_CANT_CHANGE             = &H0040
const ENCRYPTED_TEXT_PWD_ALLOWED     = &H0080
const TEMP_DUPLICATE_ACCOUNT         = &H0100
const NORMAL_ACCOUNT                 = &H0200
const INTERDOMAIN_TRUST_ACCOUNT      = &H0800
const WORKSTATION_TRUST_ACCOUNT      = &H1000
const SERVER_TRUST_ACCOUNT           = &H2000
const DONT_EXPIRE_PASSWORD           = &H10000
const MNS_LOGON_ACCOUNT              = &H20000
const SMARTCARD_REQUIRED             = &H40000
const TRUSTED_FOR_DELEGATION         = &H80000
const NOT_DELEGATED                  = &H100000
const USE_DES_KEY_ONLY               = &H200000
const DONT_REQ_PREAUTH               = &H400000
const PASSWORD_EXPIRED               = &H800000
const TRUSTED_TO_AUTH_FOR_DELEGATION = &H1000000

dim wsh_shell, wsh_env, domain_name, server_name
dim initial_ou, computer, last_logon, i

dim users(4, 1000) ' 0 = username, 1 = display_name, 2 = is_disabled, 3 = lastlogon_date, 4 = group membership
dim num_users
const MAX_USERS = 1000

wscript.echo "Audit users started at " & formatdatetime(now(), 0)

' *** Get the domain name

set wsh_shell = Wscript.CreateObject("Wscript.Shell")
set wsh_env   = wsh_shell.Environment("PROCESS")
domain_name   = wsh_env("USERDNSDOMAIN")
server_name   = wsh_env("COMPUTERNAME")
set wsh_env = nothing
set wsh_shell = nothing

' *** Open the Computers container

domain_name = split(domain_name, ".")

initial_ou = "LDAP://DC=" & domain_name(0)
for i = 1 to ubound(domain_name)
  initial_ou = initial_ou & ",DC=" & domain_name(i)
next

wscript.echo "Checking domain " & initial_ou

' *** Find all users

set initial_ou = GetObject(initial_ou)

num_users = 0
FindAllUsers initial_ou

' *** Post the data

for i = 0 to num_users-1
  wscript.echo users(0, i) & "," & users(1, i) & "," & users(2, i) & "," & users(3, i) & "," & users(4, i)
next

' *** All done

wscript.echo "Audit users finished at " & formatdatetime(now(), 0)

set initial_ou = nothing

wscript.quit 0


' **********************************************************************
' FindAllUsers
' ------------
' **********************************************************************

sub FindAllUsers(fau_OU)

  dim ou_name, user, user_dn, display_name, lastlogon_date
  dim ldap_user, group_array, i

  ou_name = fau_OU.distinguishedName

' *** First list users in this OU

  for each user in fau_OU
    if lcase(user.class) = "user" then
      user_dn = "LDAP://CN=" & user.displayName & "," & ou_name

' *** Check we haven't found too many users

      if num_users >= MAX_USERS then
        wscript.echo "WARNING: exceeded maximum number of users - " & cstr(MAX_USERS)
        exit for
      end if

' *** New user

      users(0, num_users) = lcase(user.samAccountName)

' *** Get the display name; error trap this because it can fail

      users(1, num_users) = ""

      on error resume next
      err = 0
      display_name = user.get("displayName")
      if err = 0 then users(1, num_users) = display_name
      on error goto 0

' *** Get the enabled/disabled status

      users(2, num_users) = user.get("UserAccountControl") and ACCOUNTDISABLE

      if users(2, num_users) = 0 then
        users(2, num_users) = "0"
      else
        users(2, num_users) = "1"
      end if

' *** Get the last logon date; this may fail so trap errors

      lastlogon_date = 0

      on error resume next
      set lastlogon_date = user.get("lastLogon")
      if err = 0 then
        if not isempty(lastlogon_date) then
          lastlogon_date = LongTimeToDate(lastlogon_date)
          if lastlogon_date < 0 then lastlogon_date = 0
        end if
      end if
      on error goto 0

      users(3, num_users) = formatdatetime(lastlogon_date, 0)

' *** Get the group membership

      users(4, num_users) = ""

      on error resume next

      err = 0
      set ldap_user = GetObject(user_dn)
      if err = 0 then
        on error goto 0

        group_array = ldap_user.MemberOf

        if not isempty(group_array) then
          if TypeName(group_array) = "String" then
            users(4, num_users) = group_array
          else
            for i = lbound(group_array) to ubound(group_array)
              if users(4, num_users) <> "" then users(4, num_users) = users(4, num_users) & ";"
              users(4, num_users) = users(4, num_users) & TrimGroupName(group_array(i))
            next
          end if
        end if

        set ldap_user = nothing
      end if

      on error goto 0

' *** Finished with this user

      num_users = num_users + 1
    end if
  next

' *** Now recurse into subcontainers

  for each user in fau_OU
    if lcase(user.class) = "organizationalunit" or lcase(user.class) = "container" then
      FindAllUsers user
    end if
  next

' *** All done

end sub


' **********************************************************************
' TrimGroupName
' -------------
' Turn the distinguished name into a simply group name
' **********************************************************************

function TrimGroupName(tgn_FullName)

  dim group_name, len_group, c

  TrimGroupName = ""
  group_name = ""

  len_group = len(tgn_FullName)
  if len_group < 4 then exit function

  for i = 4 to len_group
    c = mid(tgn_FullName, i, 1)
    if c = "," then exit for
    group_name = group_name + c
  next

  group_name = lcase(group_name)
  TrimGroupName = group_name

end function


' **********************************************************************
' LongTimeToDate
' --------------
' Convert the ADSI longint timestamp to a VBScript format date
' **********************************************************************

function LongTimeToDate(lt_Time)

  dim ltdate

  ltdate = lt_Time.HighPart * (2^32) + lt_Time.LowPart
  ltdate = ltdate / (60 * 10000000)
  ltdate = ltdate / 1440
  ltdate = ltdate + #1/1/1601#

  LongTimeToDate = ltdate

end function

JR

Не имеет отношения к вашему вопросу, но почему бы не отфильтровать эти события, вам не наплевать, когда у вас есть такой уровень возвратов событий. Ошибки с серьезностью 3 или выше, человек, не теряйте время!

Если вы не хотите копаться в журналах безопасности, вы также можете попробовать инструменты блокировки и управления учетной записью. (ссылка на сайт). Это добавляет дополнительную страницу свойств к сведениям об учетной записи в ADUC, включая «время последнего входа в систему».