Feeds:
Записи
Комментарии

Archive for Март 2016

URL: https://FQDN/mapi/emsmdb/?MailboxId=ID

ID: Можно узнать используя Test E-mail AutoConfiguration или использовать  UPN

owa

$username ="mail@contoso.com"
$password = "1q2w3e4r5t"
$url = "https://mail.contoso.com/mapi/emsmdb/?MailboxId=$username"
$auth=$username+":"+$password

$Encoded = [System.Text.Encoding]::UTF8.GetBytes($auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)

$headers = @{
    "User-Agent" = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0"
    "Accept" = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    "Accept-Language" = "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3"
    "Accept-Encoding" = "gzip, deflate"
    "Authorization" = "Basic $EncodedPassword"
}

$data = Invoke-WebRequest -Uri $url -Headers $headers -SessionVariable o 
$body = $data.ParsedHtml.body.outerText.split("`r`n")
$udata = $body -match ":" -replace ": "," = " | Out-String | ConvertFrom-StringData

Вывод:

PS >  $udata | Format-Table -Auto

Name           Value
----           -----
SID            S-1-5-21-1055359317-2347530276
Authentication OrgId
Mailbox        dbxpr03mb528.eurprd03.prod.outlook.com
UPN            test@mus.onmicrosoft.com
Cafe           am2pr09ca0004.eurprd09.prod.outlook.com
Created        3/23/2016 4:35:42 PM
Vdir Path      /mapi/emsmdb/
User           test@mus.onmicrosoft.com
Organization   EURPR03A002.prod.outlook.com/Microsoft Ex
Version        15.1.443.14

Mailbox – Сервер на котором расположен почтовый ящик

Cafe(Client Access  front end server) – Сервер через которой осуществляется подключение

Реклама

Read Full Post »

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

Enable antispam functionality on Mailbox servers

Которая собственно сводится к :

& $env:ExchangeInstallPath\Scripts\Install-AntiSpamAgents.ps1
Restart-Service MSExchangeTransport

Сконфигурируем настройка для Windows Update :

  • Give me updates for other Microsoft Products when I update Windows
  • Check for Updates but let me choose whether to download and install them

wu

1.  Check for Updates but let me choose whether to download and install them

AutomaticUpdatesNotificationLevel enumeration — https://msdn.microsoft.com/en-us/library/windows/desktop/aa385806(v=vs.85).aspx

1 = «Never check for updates»

2 = «Check for updates but let me choose whether to download and install them»

3 = «Download updates but let me choose whether to install them»

4 = «Install updates automatically»

#Automatic Updates prompts users to approve updates before it downloads or installs the updates
$aunlNotifyBeforeDownload = 2
$AutoUpdate = New-Object -ComObject Microsoft.Update.AutoUpdate
$Settings = $AutoUpdate.Settings
$Settings.NotificationLevel = $aunlNotifyBeforeDownload
$Settings.FeaturedUpdatesEnabled = $true
$Settings.Save()

2. Give me updates for other Microsoft Products when I update Windows

AddServiceFlag enumeration — https://msdn.microsoft.com/en-us/library/windows/desktop/bb394819(v=vs.85).aspx

asfAllowPendingRegistration  = 0x1, asfAllowOnlineRegistration   = 0x2, asfRegisterServiceWithAU     = 0x4

PS >  1 -bor 2 -bor 4

7

#Get Updates for Other Microsoft Products
$ServiceManager = New-Object -ComObject Microsoft.Update.ServiceManager
$ServiceManager.AddService2("7971f918-a847-4430-9279-4a52d1efe18d",7,"")

3. Какое последнее доступное обновление на портале Microsoft

$url = "http://catalog.update.microsoft.com/v7/site/Rss.aspx?q=exchange+server+2007+anti-spam&lang=en"
$rss = Invoke-WebRequest $url
$xml = [xml]$rss.Content
$updates = $xml.rss.channel.item.where({$_.Title -match "Standard"})

 


PS > $updates[0]
title       : Microsoft Exchange Server Standard Anti-spam Filter Updates v3.3.15608.880
link        : http://go.microsoft.com/fwlink/?LinkID=116494&updateid=0909e460-45b1-4991-80d0-f0e19b103e34
category    : {Software, Exchange, Definition Updates}
description : Microsoft Exchange Server Standard Anti-spam Filter Updates keep the heuristics for the anti-spam
              content filter current.
pubDate     : 2016-01-15 10:02:17Z
guid        : 0909e460-45b1-4991-80d0-f0e19b103e34#2016-01-15 10:02:17Z

PS > $updates | Select @{n="Version";e={($_.Title -Split "Updates ")[1]}},pubDate

Version        pubDate
-------        -------
v3.3.15608.880 2016-01-15 10:02:17Z
v3.3.15604.885 2015-12-31 09:14:36Z
v3.3.15601.886 2015-12-16 08:35:28Z
v3.3.15517.887 2015-11-26 10:01:25Z
v3.3.15426.898 2015-10-27 08:55:15Z

PS > $updates | Select @{n="Version";e={($_.Title -Split "Updates ")[1]}},pubDate -First 1

Version        pubDate
-------        -------
v3.3.15608.880 2016-01-15 10:02:17Z

Последнее обновление было выпущено - 2016-01-15 10:02:17Z

up

 

4. Последнее установленное обновление Microsoft Exchange Server Standard Anti-spam Filter Updates на сервере

$pattern = "Microsoft Exchange Server Standard Anti-spam Filter Updates"
$Session= New-Object -ComObject Microsoft.Update.Session
$Search= $Session.CreateUpdateSearcher()
$HistoryCount = $Search.GetTotalHistoryCount()
$Updates = $Search.QueryHistory(0, $HistoryCount) | Where Title -match $pattern
$Updates | Select @{n="Version";e={($_.Title -Split "Updates ")[1]}},Date

PS > $Updates | Select @{n="Version";e={($_.Title -Split "Updates ")[1]}},Date

Version         Date
-------         ----
v3.3.15608.880  09.02.2016 6:29:11
v3.3.15604.885  13.01.2016 6:26:42
v3.3.15601.886  24.12.2015 10:14:50
v3.3.15517.887  03.12.2015 6:10:37
v3.3.15426.898  03.11.2015 13:17:34

PS > $Updates | Select @{n="Version";e={($_.Title -Split "Updates ")[1]}},Date -First 1

Version        Date
-------        ----
v3.3.15608.880 09.02.2016 6:29:11

 

Можно посмотреть  процесс , который выполнил установку обновления ClientApplicationID:

 

Operation           : 1
ResultCode          : 2
HResult             : 0
Title               : Microsoft Exchange Server Standard Anti-spam Filter Updates v3.3.15608.880
Description         : Microsoft Exchange Server Standard Anti-spam Filter Updates keep the heuristics for the
                      anti-spam content filter current.
UnmappedResultCode  : 0
ClientApplicationID : <<PROCESS>>: powershell.exe
ServerSelection     : 3
ServiceID           : 7971f918-a847-4430-9279-4a52d1efe18d
SupportUrl          : http://go.microsoft.com/fwlink/?LinkID=76087&clcid=0x409


5. Получим список обновлений с серверов Microsoft и установим
    Microsoft Exchange Server Standard Anti-spam Filter Updates

Есть пример Vbscript’a — Searching, Downloading, and Installing Updates , где показан пример работы.

$pattern = "Microsoft Exchange Server Standard Anti-spam Filter Updates"
$Session = New-Object -ComObject "Microsoft.Update.Session"
$Searcher = $Session.CreateupdateSearcher()
$result = $Searcher.Search("IsInstalled=0 and Type='Software'")
$updateToInstall = New-Object -ComObject "Microsoft.Update.UpdateColl"
$updates = $result.Updates
if($updates) {
    $updates | Where Title -match $pattern | Foreach {
        $updateToInstall.Add($_) | Out-Null
    }
    if($updateToInstall) {
        $downloader = $Session.CreateUpdateDownloader()
        "Downloading..."
        $downloader.Updates = $updateToInstall
        $downloadResult = $downloader.Download()
        Write-OutPut "Download Result:"
        Write-OutPut $downloadResult
                
        $installer = $Session.CreateUpdateInstaller()
        "Installing..."
        $installer.Updates = $updateToInstall
        $installationResult = $installer.Install()
        Write-OutPut "Installation Result:"
        Write-OutPut $installationResult
    }
}

 

Q&A:

1. Можно ли установить Windows Management Framework 5.0 вместе с Exchange Server 2013 CU11?

Согласно статье Exchange Server Supportability Matrix — WMF 5.0 не поддерживается. В случае если вы установите данное

обновление, это приведет к невозможности работы с EMS. Поэтому следует удалить данное обновление для корректной работы.

2. Можно ли удалить обновление Microsoft Exchange Server Standard Anti-spam Filter Updates?

Данное обновление не поддерживает удаление. Т.к. свойство IsUninstallable=false.

VARIANT_TRUE if a user can uninstall the update from a computer; otherwise, VARIANT_FALSE.

3. Как обновить обновления ядра защиты от вредоносных программ и определения ?

Воспользоваться инструкцией из статьи — Download engine and definition updates

4. Есть ли модуль для работы с Windows Update?

MVP по PowerShell Michal Gajda , за что ему Спасибо, написал модуль — Windows Update PowerShell Module.

Для серверов у которых установлен WMF 5.0 для установки модуля лучше использовать OneGet:

https://www.powershellgallery.com/packages/PSWindowsUpdate/1.5.2.2

Read Full Post »

Рассмотрим 2 метода:

  1. Используя Com объект  InternetExplorer.Application
  2. Используя командлет Invoke-WebRequest (появился с версии 3.0)

 

Учетом успешного выполнения скрипта, будет вывод сообщения – “Ваш последний визит был: время”

1.  InternetExplorer.Application

Определим, какие поля нам требуется заполнить, достаточно просто.

В поля  “Имя Пользователя” и “Пароль” подставим значения  ,и посмотрим, какие  поля требуют заполнения.

ie

PS >  $ie.Document.forms.Item(1) | Format-Table Name,Value -Auto

name                     value
----                     -----
vb_login_username        abc
cookieuser               1
vb_login_password        abc
                         Войти
s
do                       login
vb_login_md5password
vb_login_md5password_utf

 

Как видно выше для заполнения нужны поля vb_login_username и vb_login_password.


# Имя пользователя
$login = "MyUser"
# Пароль
$pass = "Password"
# Адрес страницы
$url = "http://forum.oszone.net"
# Создание Com-объекта
$ie = New-Object -ComObject InternetExplorer.Application
# Переход к заданному адресу
$ie.Navigate($url)
# Ждем загрузки страницы
while($ie.Busy) { Start-Sleep -Milliseconds 100 }

# Объект страницы
$doc = $ie.Document
# Заполняем поле - Имя пользователя
$doc.getElementsByName("vb_login_username") | % {$_.Value = $login}
# Заполняем поле - Пароль
$doc.getElementsByName("vb_login_password") | % {$_.Value  = $pass}
# Снимаем галочку - Сохранить
$doc.getElementsByName("cookieuser") | % {$_.Value  = 0}

# Находим кнопку войти - нажимаем ее
$doc.getElementsByTagName("input") | ? {$_.Value -eq "Войти"} | % {$_.Click()}
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
# После авторизации, получаем данные
$doc.Body.OuterText.Split("`r`n") -match "Ваш последний визит"

 

2. Invoke-WebRequest

Определим, какие поля нам требуется заполнить у формы.

PS >  $r.Forms[1].Fields | Format-Table -Auto

Key                      Value
---                      -----
navbar_username          Имя пользователя
cb_cookieuser_navbar     1
vb_login_password
s                        7f2a40e2749a7bf18b1b371
do                       login
vb_login_md5password
vb_login_md5password_utf

 

Требуется нам заполнить все поля или достаточно определенных. В этом нам поможет Fiddler.

  • Запускаем Fiddler
  • Запускаем любой браузер ( логирование командлета Invoke-WebRequest тоже поддерживается)
  • Переходим на сайт
  • Заполняем поля , нажимаем “Войти”
  • Смотрим Post запрос

iw

 

Поле vb_login_password – пустое, но вычисляется md5 hash пароля.

$md5 = [Security.Cryptography.MD5]::Create()
$bstr = [Text.Encoding]::ASCII.GetBytes("abc")
$hash = (-join ($md5.ComputeHash($bstr) | %{ "{0:X2}" -f $_})).ToLower()
$hash
900150983cd24fb0d6963f7d28e17f72

Для ASCII символов, если пароль в Unicode, данный метод не подойдет. Какой алгоритм преобразования

пароля содержащего Unicode символы — http://forum.oszone.net/clientscript/vbulletin_md5.js?v=364

Вычислим поле vb_login_md5password для Unicode , на примере – Привет:

$str = -join([char[]]"Привет" | % {"&#"+ ([int][char]$_) +";"})
(-join ($md5.ComputeHash([Text.Encoding]::ASCII.GetBytes($str))| %{ "{0:X2}" -f $_})).ToLower()

«&#»+ [int][char]П –> 1055 + “;” = “П”

Вычислим поле vb_login_md5password_utf для Unicode , на примере – Привет:

$str = [int[]][char[]]"Привет" | % {$_ -band 255} 
(-join ($md5.ComputeHash($str) | %{ "{0:X2}" -f $_})).ToLower()

При использовании полей vb_login_md5password и vb_login_md5password_utf, поле vb_login_password – не заполняем.

Но можно не утруждать себя данными алгоритмами, а просто заполнить поля vb_login_username и vb_login_password.

$login = "MyUser"
$pass = "Password"
$url = "http://forum.oszone.net"
$r = Invoke-WebRequest $url -SessionVariable oz
$form = $r.Forms[1]
$form.Fields["vb_login_username"] = $login
$form.Fields["vb_login_password"] = $pass
$r = Invoke-WebRequest -Uri ("$url/" + $form.Action)`
    -WebSession $oz -Method POST -Body $form.Fields
$r = Invoke-WebRequest -Uri $url -WebSession $oz
$r.ParsedHtml.Body.OuterText.Split("`r`n") -match "Ваш последний визит"

 

В конечном итоге получим вывод:

output

 

Read Full Post »

Для примера рассмотрим два домена contoso.com и tailspintoys.com. В домене Contoso.com добавим suffix ex.com и выполним обновление в tailspintoys.com.

Добавление UPN Suffix через ADSI:

$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()            
$dn = "cn=Partitions,cn=Configuration," + ($domain.GetDirectoryEntry()).distinguishedName 

$upn = "ex.com"            
$p = [adsi]"LDAP://$dn"            
$p.PutEX(3, "uPNSuffixes", @($upn))            
$p.SetInfo()

Где  3 – APPEND. Другие значения можно посмотреть ADS_PROPERTY_OPERATION_ENUM.

ADS_PROPERTY_APPEND

Instructs the directory service to append the specified value(s) to the existing values(s).

When the ADS_PROPERTY_APPEND operation is specified, the new attribute value(s) are automatically committed to the directory service and removed from the local cache.

This forces the local cache to be updated from the directory service the next time the attribute value(s) are retrieved.

Добавление  UPN Suffix через Set-ADObject:

Set-ADObject -Identity $dn -Add @{upnsuffixes = $upn }  
Добавление UPN Suffix через Set-ADForest:

Set-ADForest -Identity (Get-ADForest) -UPNSuffixes @{add = $upn}

Проверим, что суффикс добавился:

PS > (Get-ADForest).UPNSuffixes test.contoso.com

 

Проверим, обновился ли суффикс в другом лесе – нет, не обновился.

su

 

При нажатии кнопки Refresh, происходит обновление и мы видим, что суффикс добавился.

su1

 

Что происходит при нажатии на кнопку Refersh?

Для это установим и запустим WireShark. Удалим все фильтры , выберем адаптер и нажмем – Start Capturing packet.

В оснастке domain.msc – нажмем кнопку Refresh. Происходит вызов функции NetrGetForestTrustInformation.

В спецификации MS-NRPC есть ее описание и метод DsrGetForestTrustInformation , который реализован в

функциях I_NetLogonControl2 и DsGetForestTrustInformationW.

wr

Через I_NetLogonControl2:

$target = "contoso.com" 
Add-Type @"
    [DllImport("netapi32.dll", CharSet=CharSet.Unicode)] 
    public static extern int I_NetLogonControl2(
        string lpServerName, 
        uint lpFunctionCode, 
        uint lpQueryLevel, 
        ref IntPtr lpInputData, 
        out IntPtr queryInformation
    ); 
"@ -Name "NetLogon" -Namespace Win32Functions

$out = [IntPtr]::Zero
$domain = [Runtime.InteropServices.Marshal]::StringToCoTaskMemAuto($target)
[Win32Functions.NetLogon]::I_NetLogonControl2($null,5,2,[ref]$domain,[ref]$out)

 

5 — NETLOGON_CONTROL_REDISCOVER

Forces a domain controller (DC) to rediscover the specified trusted domain DC.

Можно обойтись и без Add-Type, т.к. при запуске PowerShell загружается непубличный класс System.DirectoryServices.ActiveDirectory.UnsafeNativeMethods в котором уже определена функция I_NetLogonControl2.

$target = "contoso.com" 
$zero = [Runtime.InteropServices.Marshal]::StringToHGlobalUni($target)
$ptr = [Runtime.InteropServices.Marshal]::AllocHGlobal(
    [Runtime.InteropServices.Marshal]::SizeOf([Intptr]::Zero)
)
[Runtime.InteropServices.Marshal]::WriteIntPtr($ptr, $zero)
$Assembly = [AppDomain]::CurrentDomain.GetAssemblies() |
    ? {$_.GlobalAssemblyCache -And 
        $_.Location.Split('\\')[-1].Equals('System.DirectoryServices.dll') }
$UnsafeNativeMethods = $Assembly.GetType(
    'System.DirectoryServices.ActiveDirectory.UnsafeNativeMethods'
)
$I_NetLogonControl2 = $UnsafeNativeMethods.GetMethod('I_NetLogonControl2')
$I_NetLogonControl2.Invoke($null,@($null,5,2,$ptr,[IntPtr]::Zero))

Через DsrGetForestTrustInformation:

Add-Type @"
    [DllImport("netapi32.dll", CharSet=CharSet.Unicode)] 
    public static extern int DsGetForestTrustInformationW(
        string ServerName, 
        string TrustedDomainName, 
        uint Flags, 
        out IntPtr ForestTrustInfo
    ); 
"@ -Name "NetLogon" -Namespace Win32Functions
$out = [IntPtr]::Zero
$domain = "contoso.com"
[Win32Functions.NetLogon]::DsGetForestTrustInformationW(
    $null,$domain,1,[ref]$out
)

Есть еще один способ, использования без Add-Type, данная методика хорошо описана у Boe Prox — http://learn-powershell.net/2014/12/18/retrieving-a-registry-key-lastwritetime-using-powershell/

$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('AD_TEMP')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('ADModule', $False)

$TypeBuilder = $ModuleBuilder.DefineType('netapi32', 'Public, Class')
  
$PInvokeMethod = $TypeBuilder.DefineMethod(
        'DsGetForestTrustInformationW', #Method Name
        [Reflection.MethodAttributes] 'PrivateScope, Public, Static, HideBySig, PinvokeImpl', #Method Attributes
        [Int], #Method Return Type
        [Type[]] @(
            [String], #ServerName
            [String], #TrustedDomainName
            [UInt32], #Flags
            [IntPtr].MakeByRefType() #ForestTrustInfo
        ) #Method Parameters
    )
  
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))

$FieldArray = [Reflection.FieldInfo[]] @(       
        [Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
        [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError'),
        [Runtime.InteropServices.DllImportAttribute].GetField('CharSet')
    )
  
$FieldValueArray = [Object[]] @(
    'DsGetForestTrustInformationW', 
    $True,
    [System.Runtime.InteropServices.CharSet]::Unicode
)
  
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder(
        $DllImportConstructor,
        @('netapi32.dll'),
        $FieldArray,
        $FieldValueArray
    )
  
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
[void]$TypeBuilder.CreateType()

$domain = "contoso.com"
[netapi32]::DsGetForestTrustInformationW($null,$domain,1,[ref][IntPtr]::Zero)

Read Full Post »

Начиная с Windows Server 2008 / Windows Vista была добавлена группа Event Log Readers (Читатели журнала событий) , которая позволяет получить доступ на чтение к журналу Security.

  1. Добавим пользователя в группу Event Log Readers (Читатели журнала событий)
    • net localgroup «Event Log Readers» TestUser /Add
  2. Производим выход и повторный вход пользователям в систему ,и проверяем если права на чтение журнала Security.

 

  • Воспользуемся оснасткой Event Viewer(Просмотр событий) , как видим все отрабатывает.

1

 

 

  • Откроем консоль PowerShell и выполним командлет Get-WinEnvent. В этот раз мы получаем ошибку , что доступ запрещен.

2

 

  • Попробуем стандартную утилиту wevtutil.  Все отрабатывает, как нужно.

3

 

  • Попробуем через WMI класс Win32_NTLogEvent. И тоже все хороршо.

5

 

  • Теперь посмотрим, может быть нам поможет старенький командлет Get-EvetLog. Тоже выкидывает ошибку, но дает полезное диагностическое сообщение.

4

 

Остается узнать, какой ключ реестра отвечает. С этим нам поможет, замечательная утилиту Procces Monitor.

6

Теперь зная путь HKLM\System\CurrentControlSet\services\eventlog\Security и требуемые права Read, назначим их группе Event Log Readers (Читатели журнала событий). Из статьи Well-known security identifiers in Windows operating systems получим SID этой группы.

SID: S-1-5-32-573
Name: BUILTIN\Event Log Readers
Description: A Builtin Local group. Members of this group can read event logs from local machine.

$key = "HKLM:\System\CurrentControlSet\services\eventlog\Security"
$acl = Get-ACL $key

$sid = New-Object Security.Principal.SecurityIdentifier("S-1-5-32-573")
$group = $sid.Translate([Security.Principal.NTAccount])

$rule = New-Object Security.AccessControl.RegistryAccessRule(
    $group.Value,
    "ReadKey",
    "ContainerInherit",
    "None",
    "Allow"
)

$acl.AddAccessRule($rule)
Set-Acl $key -AclObject $acl

 

Проверим работу командлетов Get-WinEvent/Get-EventLog. После добавления прав, оба командлета отрабатывают успешно.

7

 

 

Можно более детально раздать права — Giving Non Administrators permission to read Event Logs Windows 2003 and Windows 2008. Но тут потребуется работа с SDDL.

Для преобразования формата SDDL в более читаемый вид, возьмем функцию от Matthew Graeber ConvertFrom-SDDL.

8

Для примера  изменим S-1-5-32-573 на 0x5(ReadData,AppendData) ,как у группы Администраторы.

wevtutil sl Security /ca:»O:BAG:SYD:(A;;0xf0005;;;SY)(A;;0x5;;;BA)(A;;0x5;;;S-1-5-32-573)»

PS >  wevtutil gl security

channelAccess: O:BAG:SYD:(A;;0xf0005;;;SY)(A;;0x5;;;BA)(A;;0x5;;;S-1-5-32-573)

 

 

Read Full Post »