看我如何检测密码抓取神器Mimikatz的执行

阅读量    85224 |   稿费 140

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

前言

此前,我阅读了CyberWarDog的威胁主动出击(Threat Hunting)文章,并且还偶然发现并仔细阅读了他的“寻找内存中的Mimikatz”系列文章。其中,用于构建签名的方法似乎非常简单,并且在对恶意工具的分析过程中,已经解决了寻找入口的这一障碍。

用于检测Mimikatz的方法被称为分组(Grouping),具体来讲,是获取一组特殊的Artifacts,并且识别多个特殊的Artifacts同时出现的时间。在本文中,我们将参考CyberWarDog的方法,来探讨如何使用SysmonELK Stack对密码抓取神器Mimikatz进行检测与告警。

我们假设你已经拥有一个ELK Stack,并且配置了ElastAlert集成。这样,就可以在几分钟的时间里迅速将HELK搭建成功(ElastAlert后续会与其合并)。

一开始,我认为这并不是一个完美的解决方案。其思路很简单,如果在同一个主机中,有5DLL1秒钟之内被接连访问,那么就发出告警。然而,很不巧,ElastAlert没有内置这个功能,同样Python也没有。

 

Sysmon配置

我使用的Sysmon配置是Ion-Storm Sysmon Config,源文件位于: https://github.com/ion-storm/sysmon-config/blob/master/sysmonconfig-export.xml 。默认情况下,正确的事件将会被转发。其中的第571-579行如下:

<!--
Mimikatz Detection -->

<ImageLoaded
condition="is">C:WindowsSystem32WinSCard.dll</ImageLoaded>
<!--MimiKatz Detection Credit: @Cyb3rWard0g:
https://cyberwardog.blogspot.com/2017/03/chronicles-of-threat-hunter-hunting-for.html
-->

<ImageLoaded
condition="is">C:WindowsSystem32cryptdll.dll</ImageLoaded>
<!--MimiKatz Detection Credit: @Cyb3rWard0g:
https://cyberwardog.blogspot.com/2017/03/chronicles-of-threat-hunter-hunting-for.html
-->

<ImageLoaded
condition="is">C:WindowsSystem32hid.dll</ImageLoaded>
<!--MimiKatz Detection Credit: @Cyb3rWard0g:
https://cyberwardog.blogspot.com/2017/03/chronicles-of-threat-hunter-hunting-for.html
-->

<ImageLoaded
condition="is">C:WindowsSystem32samlib.dll</ImageLoaded>
<!--MimiKatz Detection Credit: @Cyb3rWard0g:
https://cyberwardog.blogspot.com/2017/03/chronicles-of-threat-hunter-hunting-for.html
-->

<ImageLoaded
condition="is">C:WindowsSystem32vaultcli.dll</ImageLoaded>
<!--MimiKatz Detection Credit: @Cyb3rWard0g:
https://cyberwardog.blogspot.com/2017/03/chronicles-of-threat-hunter-hunting-for.html
-->

<ImageLoaded
condition="is">WMINet_Utils.dll</ImageLoaded>
<!--MimiKatz Detection Credit: @Cyb3rWard0g:
https://cyberwardog.blogspot.com/2017/03/chronicles-of-threat-hunter-hunting-for.html
-->

<ImageLoaded
condition="contains">Temp</ImageLoaded>

<!--
END: Mimikatz Detection -->

最开始,我们需要写一个脚本,来进行一些逻辑上的验证。我试图让Python工具尽可能模块化,这样我们就可以轻松地对其他事件“分组”进行告警。

我们将要检测的5DLL是:

Cryptdll.dll

Hid.dll

Samlib.dll

Vaultcli.dll

Winscard.dll

在这里,还存在误报的一种可能性,如果恰巧这些DLL1分钟之内被正常访问,那么同样会产生告警。

 

告警脚本

在运行ELK Stack的服务器上,我们首先创建py-alert.py并编辑:

sudo
nano /bin/py-alert.py

py-alert.py的源代码如下:

#!/usr/bin/python
 
import sys

from argparse import ArgumentParser
import datetime
import requests
import subprocess
import os

time = datetime.datetime.now().strftime("%H:%M-%y-%m-%d")

def print_banner():
    print('''npy-alert.py is a tool written to
expand the functionality of ElastAlert
    Author: Jordan Potti
    Twitter: @ok_bye_nown'''
    )
 
def main():
    global arguments
    parser = ArgumentParser()
    parser.add_argument("-T",
dest="action",required=True,help="Action Type: Send Alert (S) or
Data Write (D)")
    parser.add_argument("-a",
dest="detection",required=True,help="Alert Name")
    parser.add_argument("-c",
dest="host",required=False,help="Host to record")
    parser.add_argument("-S",
dest="slack",required=False,help="Slack Web Hook")
    parser.add_argument("-t",
dest="tripped",required=False,help="Number or Hosts needed to
alert")
 
    if len(sys.argv) == 1:
        print_banner()
        parser.error("No arguments
given.")
        parser.print_usage
        sys.exit()
 
    arguments = parser.parse_args()
    outfile = '/tmp/'+arguments.detection
    if arguments.action == 'D':
        with open (outfile, "a+") as
out_file:
           
out_file.write(arguments.host+"n")
 
    if arguments.action == 'S':
        command = "head -50 %s | sort |
uniq -c | gawk '$1>=%s{print $2}'" %(outfile,arguments.tripped)
        print(command)
        output = os.popen(command).read()
        if output != '':
            output = str(output)
            output = output.replace('b'','')
            output = output.replace('\n','')
            out_file = open(outfile, 'w')
            out_file.write("Host: " +
output)
            out_file.write("Alert Type:
" + arguments.detection+"n")
            out_file.write("Time: " +
time)
            out_file = open(outfile, 'r')
            webhook_url = arguments.slack
            slack_data =
{"text":out_file.read()}
            slack_data = str(slack_data)
            slack_data =
"payload="+slack_data
            response = requests.post(
                webhook_url, data=slack_data,
                headers={'Content-Type':
'application/x-www-form-urlencoded'})
            if response.status_code != 200:
                raise ValueError('Request to
slack returned an error %s, the response is: %s' % (response.status_code,
response.text))
            os.remove(outfile)
 
main()

然后,执行该Python脚本:

sudo chmod 755 /bin/py-alert.py

该脚本可以处理我们的全部逻辑,并负责发送Slack Notification告警通知。借助这些选项,我们可以对任何事件组合进行告警。

 

配置告警规则

接下来,将我们的单个规则添加到告警规则目录中。

可以从GitHub获取到我们的规则:

git clone https://github.com/jordanpotti/ElastAlertGrouper.git

随后,将规则文件复制到ElastAlert规则目录中:

sudo cp ElastAlertGrouper/alert_rules/* /etc/elastalert/alert_rules/

现在,在规则目录中就已经有了6条新规则。当指定DLL被加载时,相应的规则将被匹配到,随后立即发出告警。

以下为samlib.yaml的源代码:

es_host:
localhost

es_port:
9200

name:
"samlib"

realert:

    minutes: 0

index:
winlogbeat-*

filter:

-
query:

    wildcard:

        event_data.ImageLoaded:
"*samlib*"

type:
any

alert:

    - command

command:
["/bin/py-alert.py","-T","D","-a","Mimikatz","-c","%(computer_name)s"]

如你所见,我们配置了典型的告警规则选项,并且会在event_data.ImageLoaded中查询samlib。当告警被触发时,会使用如下命令调用我们的Python脚本:

python3
/bin/py-alert.py –T D –a Mimikatz –o /tmp/mimikatz –c $ComputerName

其中的参数-T用于指定脚本将要采取的动作,由于我们这里只是将主机名写入文件,所以我们要使用“Document”或者“D”选项。

其中的参数-a是告警类型,在这里是Mimikatz

其中的参数-c是从告警事件中获取的主机名。

上面的设置针对所有DLL告警事件。因此,当Mimikatz在系统中运行时,输出文件中将会有5个主机名被写入。

 

配置捕获Mimikatz的规则

接下来,让我们来看看Mimikatz的规则:

es_host:
localhost

es_port:
9200

name:
"Mimikatz"

index:
elastalert_status

realert:

    minutes: 0

type:
cardinality

cardinality_field:
rule_name

max_cardinality:
4

filter:

-
terms:

    rule_name:

        - winscard

        - cryptdll

        - hid

        - samlib

        - vaultcli

-
term:

    alert_sent: true

timeframe:

    seconds: 1

alert:

    - command

command:
["python3","/bin/py-alert.py",
"-T","S","-S","SLACKWEBHOOK","-a","Mimikatz","-t","5"]

此告警使用了另外一个索引。实际上,ElastAlert有它自己的索引,在每次告警时都会对其进行查询。因此,我们现在可以查看这个索引,来确认5DLL的告警是不是在1秒之内被接连触发的。这一过程只需要通过对DLL规则进行筛选就可以完成,并且它只返回那些alert_sent标志设置为true的内容,并且只在1秒之内识别出5个结果的时候才发出告警。

此时,我们需要生成一个Slack Web Hook,并使用我们的Web钩子替换“SLACKWEBHOOK”。

其中,告警功能的实现同样是通过调用一个Python脚本:

python3
/bin/py-alert.py –T S –S SLACKWEBHOOK –a Mimikatz –t 5

其中的参数-T代表要执行的操作,在这里,我们要执行“Send”操作。

其中的参数-S需要配置为我们的Slack Web Hook

其中的参数-a代表需要对哪些检测到的类型进行告警。

其中的参数-t代表次数,我们只在输出文件中有5个或者更多特定的主机名时才会产生告警。

最后一部分是最重要的,其中的这个数字应该是我们“分组”中的规则数量。

 

测试过程

接下来,我们运行Mimikatz

立即收到了相关告警:

 

总结

有一点需要特别强调,上述内容已经在实验室的环境中进行了测试,而我们实验室的环境中只有几个终端主机。如果需要在生产环境中进行部署,可能需要根据终端的数量进行相应的调整。

关于如何手动部署的更深入指导,请参考我们实验室的文章:https://cyberwardog.blogspot.com/2017/02/setting-up-pentesting-i-mean-threat_98.html

如果在过程中遇到任何问题,欢迎随时通过Twitter https://twitter.com/ok_bye_now或电子邮件admin@jordanpotti.com与我联系。

我们在本文中涉及到的脚本,并不保证一定能在所有人的环境中成功实现,需要以此为参考进行相应的调整。大家知道,不要盲目信任网络上的脚本,需要加以自行判断。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多