This artical'll also is published in english:http://www.cnblogs.com/larryatcnblog/p/4820327.html
Previous company OWA is not open to the public, but has never experienced the use of Exchange OWA AD account password blasting behavior, into a new company after the use of OWA to open the network, the results attracted a lot of attacks. As a PowerShell script, the data source is based on the security log on Exchange CAs and is checked every 10 minutes with a scheduled task, and the threshold is dropped into the CAS firewall block.
Environment is Windows 2012/exchange 2013
In addition, the following points need to be noted,
First CAS servers are generally more than one, and NLB, so the script to be placed on each CAS is set to execute,
Next verify the error log ID number for 4625,message includes details such as source IP, account name, etc.
You need to turn on log auditing on the CAS server again, otherwise the log may not be logged.
The process is described first,
After the script runs, it fetches the entries from the security log for the past 10 minutes, filters out all 4625 entries, and extracts the authenticated account and authentication source IP from the log's XML data by each 4625 log loop, with the IP key, the account value, and the record in the hash table. Finally, the IP in the hash table will be more than the threshold IP to join the firewall block off, send an email alert.
#进入脚本所在目录Set-location (Get-item ($MyInvocation. mycommand.definition)). directoryname# to track how long before the log, and the scheduled task should also correspond to good $minutestoback = 10$date = get-date$strdate = $Date. ToString (' yyyy-mm- DD ') $End _time = $Date $start_time = $Date. AddMinutes (-$MinutesToBack) #定义两个日志文件, mail alerts only send the last 10 minutes of log content $strlogfile = "${strdate}.txt" $strLogFile _e = "${strdate}_e.txt"set-content-path $strLogFile _e-value $null # from Fw_ WhiteList.txt read the whitelist IP address, there will be some exceptions, the exception of the IP address in the form of each line written in the text $whitelist = @ (Get-content-path ' fw_whitelist.txt '-erroraction : silentlycontinue)
#定义加入防火墙的阀值, 50 represents the number of password errors that are verified, 10 means that account numbers are removed after the duplicate, two values are added to the firewall, exceptions to the whitelist are $T_4625_FW = @ (50, 10)
#没什么好说的, the message alarm section $mail_from = "$ ($env: COMPUTERNAME) @xxxx. yyyy" $Mail _to = ' [email protected] ', ' [email protected] Xxxx.yyyy ' $Mail _subject = ' message header ' $Mail _smtpserver = ' smtp address '
Since the log is directly judged by 4625来, I have directly written 4625 dead in the script.
What are you going to do with get-winevent here? Because it has a way to get the XML format data of the log, there is a general way to handle it, regardless of the regional language,
#Log InformationAdd-log-path$strLogFile _e-value"Catch logs after: $ ($Start _time. ToString (' HH:mm:ss '))"-Type Infoadd-log-path$strLogFile _e-value"Catch logs before: $ ($End _time. ToString (' HH:mm:ss '))"-Type Info#Catch a log of time from EventLog$4625= @ (get-winevent-filterhashtable @{logname = ' Security '; Id = 4625; StartTime =$Start _time; EndTime =$End _time;} -erroraction:silentlycontinue)#output 4625 number of logsAdd-log-path$strLogFile _e-value"Total 4625 logs count: [$ ($4625.count)]"-type Info
For each log loop processing, after converting to XML, remove the IP and account name exists in the hash table,
#http://schemas.microsoft.com/win/2004/08/events/event#index 5 = targetusername#index = IpAddress$s _4625= @{}foreach($e inch $4625){ $xmlData=$IP=$Account=$null $xmlData= [XML]$e. TOXML ()$IP= $( if($xmlData. EVENT.EVENTDATA.DATA[19]. '#text '-imatch ' ^\s*$ '){' NULL '}Else { $xmlData. EVENT.EVENTDATA.DATA[19]. '#text '. Trim () } ) $Account= $( if($xmlData. EVENT.EVENTDATA.DATA[5]. '#text '-imatch ' ^\s*$ '){' NULL '}Else { $xmlData. EVENT.EVENTDATA.DATA[5]. '#text '. Trim () } ) $s _4625.$($IP) += @($Account)}
The key in the hash table is also the IP loop, in comparison with the previously defined threshold to do a firewall operation,
foreach($IP inch $s _4625. Keys) {$tmp= @($s _4625.$IP| Group-object | Sort-object Count-descending) ADD-log-path$strLogFile _e-value"past [${minutestoback}] minutes [IP address] [error volume] [account] [former 5]:[$IP][$ ($s _4625. $IP. Count)][$ ($tmp. Count)][$ ($tmp [0..4] |%{$_. Name, $_. Count-join ': '})]"-Type Infoif($s _4625.$IP. Count-ge $t _4625_FW[0]-and $tmp. Count-ge $t _4625_FW[1]) { $tmp. Name | Add-content-path"$IP. Log"-encodingDefault if($WhiteList -notcontains $IP) { $Mail=$trueNew-netfirewallrule-displayname"Scriptauto_$ip"-profile any-action block-remoteaddress$IP-direction Inbound-erroraction:silentlycontinueif(!$?) {Add-log-path$strLogFile _e-value ' Join firewall failed, reason: '-Type Error Add-log-path$strLogFile _e-value$Error[0]-Type Error}Else{ADD-log-path$strLogFile _e-value"[$IP] Join a firewall"-Type Warning}} Else{ADD-log-path$strLogFile _e-value"[$IP] in the white list"-Type Info}} Else{ADD-log-path$strLogFile _e-value"[$IP] not exceeding threshold"-Type Info}}
Finally, if it is necessary to send an email, send it through SMTP,
If($Mail) {try {Send-mailmessage-from$Mail _from-to$Mail _to-subject$Mail _subject-smtpserver$Mail _smtpserver-body ((get-content$strLogFile _e-encodingDefault)-join"' t ' n") -Encoding UTF8} catch {Add-log-path$strLogFile _e-value"Failed to send mail, cause: $ ($Error [0])"-Type Error}} Get-content-path$strLogFile _e| Add-content-path$strLogFileADD-log-path$strLogFile _e-value ' completed '-type Info
Scheduled tasks are set to run every 10 minutes, according to their own environment and experience to set the threshold, recently want to through the OWA explosion password IP is also a variety of sealed off, the effect is obvious.
Automatically block OWA bursting AD account passwords with PowerShell scripts