码迷,mamicode.com
首页 > 系统相关 > 详细

用powershell脚本自动阻止OWA爆破AD账户密码

时间:2015-09-18 21:52:49      阅读:625      评论:0      收藏:0      [点我收藏+]

标签:

This artical will also be published in English: http://www.cnblogs.com/LarryAtCNBlog/p/4820327.html

以前所在的公司OWA什么的都不对外开放倒是从来没有经历过利用Exchange OWA的AD账户密码爆破行为,入职了一个新的公司后OWA对公网开放使用,结果引来了不少的攻击。于是乎做了一个powershell的脚本,数据源基于Exchange CAS上的security日志,用计划任务每10分钟检查一次,超过阀值的则扔进CAS的防火墙block掉。

环境是Windows 2012 / Exchange 2013

另外,需要注意如下几点,

首先CAS服务器一般都不止一台,而且做了NLB,因此脚本要放在每台CAS上都设置执行,

其次验证错误的日志ID号为4625,Message里包括了详细信息如源IP,账户名什么的,

技术分享

再次CAS服务器上需要开启日志审核,否则可能没有该日志被记录下来。

流程先描述一下,

脚本运行后从Security日志中抓取过去10分钟的条目,过滤出所有4625的条目;逐条对每条4625日志循环,从日志的XML数据中提取出被验证的账户和验证源IP,以IP为key,账户为值,记录于哈希表中;最后对哈希表中的的IP做循环将超过阀值的IP加入防火墙block掉,发出邮件告警。

#进入脚本所在目录
Set-Location (Get-Item ($MyInvocation.MyCommand.Definition)).DirectoryName

#要追踪多长时间之前的日志,和计划任务也要对应好
$MinutesToBack = 10

$Date = Get-Date
$strDate = $Date.ToString(‘yyyy-MM-dd‘)

$End_time = $Date
$Start_time = $Date.AddMinutes(-$MinutesToBack)

#定义两个日志文件,邮件告警时仅会发送过去10分钟的日志内容
$strLogFile = "${strDate}.txt"
$strLogFile_e = "${strDate}_e.txt"

Set-Content -Path $strLogFile_e -Value $null

#从FW_WhiteList.txt读取白名单的IP地址,总归会有些例外,例外的IP地址以每行的形式写在该文本中
$WhiteList = @(Get-Content -Path ‘FW_WhiteList.txt‘ -ErrorAction:SilentlyContinue)
#定义加入防火墙的阀值,50代表验证的密码错误次数,10代表账号去掉重复之后的账户数目,两个值都被超过就会被加入防火墙,白名单中的例外
$t_4625_fw = @(50, 10)
#没什么好说的,邮件告警部分
$Mail_From = "$($env:COMPUTERNAME)@xxxx.yyyy"
$Mail_To = ‘user1@xxxx.yyyy‘, ‘user2@xxxx.yyyy‘
$Mail_Subject = ‘邮件标题‘

$Mail_SMTPServer = ‘SMTP地址‘

由于日志是直接以4625来判断,我也就直接把4625直接写死在了脚本中。

这里为会什么要用Get-WinEvent呢?因为它有一个方法获取日志的xml格式数据,处理起来有通用的方法,不用管地区语言之类的,

#日志信息
Add-Log -Path $strLogFile_e -Value "Catch logs after : $($Start_time.ToString(‘HH:mm:ss‘))" -Type Info
Add-Log -Path $strLogFile_e -Value "Catch logs before: $($End_time.ToString(‘HH:mm:ss‘))" -Type Info

#从Eventlog中抓过去一段时间的日志
$4625 = @(Get-WinEvent -FilterHashtable @{LogName = ‘Security‘; Id = 4625; StartTime = $Start_time; EndTime = $End_time;} -ErrorAction:SilentlyContinue)
#输出4625日志数目
Add-Log -Path $strLogFile_e -Value "Total 4625 logs count : [$($4625.Count)]" -Type Info

对每条日志循环处理,转换为xml后取出IP和账户名存在hash table中,

# http://schemas.microsoft.com/win/2004/08/events/event
# index 5 = TargetUserName
# index 19 = IpAddress
$s_4625 = @{}
foreach($e in $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)
}

将Hash table中的key也就是IP做循环,以之前定义的阀值相对比后做加入防火墙的操作,

foreach($IP in $s_4625.Keys)
{
    $tmp = @($s_4625.$IP | Group-Object | Sort-Object Count -Descending)
    Add-Log -Path $strLogFile_e -Value "过去[${MinutesToBack}]分钟[IP地址][错误量][账户][前5]:[$IP][$($s_4625.$IP.Count)][$($tmp.Count)][$($tmp[0..4] | %{$_.Name, $_.Count -join ‘:‘})]" -Type Info
    if($s_4625.$IP.Count -ge $t_4625_fw[0] -and $tmp.Count -ge $t_4625_fw[1])
    {
        $tmp.Name | Add-Content -Path "$IP.log" -Encoding Default
        if($WhiteList -notcontains $IP)
        {
            $Mail = $true
            New-NetFirewallRule -DisplayName "ScriptAuto_$IP" -Profile Any -Action Block -RemoteAddress $IP -Direction Inbound -ErrorAction:SilentlyContinue
            if(!$?)
            {
                Add-Log -Path $strLogFile_e -Value ‘加入firewall失败,原因:‘ -Type Error
                Add-Log -Path $strLogFile_e -Value $Error[0] -Type Error
            }
            else
            {
                Add-Log -Path $strLogFile_e -Value "[$IP]加入防火墙" -Type Warning
            }
        }
        else
        {
            Add-Log -Path $strLogFile_e -Value "[$IP]在白名单中" -Type Info
        }
    }
    else
    {
        Add-Log -Path $strLogFile_e -Value "[$IP]未超过阀值" -Type Info
    }
}

最后如果有必要发出邮件的话就通过smtp发出,

If($Mail)
{
    try
    {
        Send-MailMessage -From $Mail_From -To $Mail_To -Subject $Mail_Subject -SmtpServer $Mail_SMTPServer -Body ((Get-Content $strLogFile_e -Encoding Default) -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 $strLogFile
Add-Log -Path $strLogFile_e -Value ‘Completed‘ -Type Info

计划任务中设置每10分钟跑一次,根据自己环境和经验设置好阀值,最近想通过OWA爆破密码的IP也是各种被封掉,效果还是明显的。

用powershell脚本自动阻止OWA爆破AD账户密码

标签:

原文地址:http://www.cnblogs.com/LarryAtCNBlog/p/4816788.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!