Azure串行控制台攻防实战(第二部分)——Linux虚拟机监控与威胁狩猎

本文详细介绍了如何在Azure Linux虚拟机上启用Sysmon for Linux和Microsoft Defender for Endpoint日志记录,通过Kusto查询追踪串行控制台活动,并提供针对可疑操作的威胁狩猎技术。

Azure串行控制台攻防实战(第二部分)

启用Linux虚拟机日志记录

根据当前设置,此步骤可能非必需。如果云计算工作负载已由Microsoft Sentinel或其他SIEM解决方案监控,可跳过此部分。本节介绍如何使用Sysmon for Linux和Microsoft Defender for Endpoint代理记录Azure Linux虚拟机事件,以捕获串行控制台活动痕迹。

日志分析工作区的创建和Azure活动监控的启用已在博客第一部分介绍。要为Linux虚拟机启用日志记录,请从日志分析工作区的“代理”选项卡安装Log Analytics Linux代理。

Syslog

Syslog是Linux中常用的事件日志协议。Linux设备中的Syslog守护进程收集本地事件,并可将其发送到日志分析工作区。应用程序发送的消息可本地存储或发送到Syslog收集器。安装Azure Monitor Linux代理后,当在数据收集规则(DCR)中启用Syslog收集时,它会配置本地Syslog守护进程将消息转发给代理。Azure Monitor代理随后将这些消息传输到Azure Monitor或日志分析工作区,在Syslog表中创建相应的记录。使用此指南通过Azure Monitor代理收集Syslog事件。

Sysmon for Linux

安装Sysmon for Linux的先决条件:

  • 确保Linux虚拟机已加入日志分析工作区。
  • 使用此指南通过Azure Monitor代理收集Syslog事件。

在Linux虚拟机上使用此指南安装Sysmon。Sysmon for Linux的配置可在此处找到,并使用以下配置安装Sysmon服务:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<Sysmon schemaversion="4.70">
  <EventFiltering>
    <!-- Event ID 1 == ProcessCreate. Log all newly created processes -->
    <RuleGroup name="" groupRelation="or">
      <ProcessCreate onmatch="exclude"/>
    </RuleGroup>
    <!-- Event ID 3 == NetworkConnect Detected. Log all network connections -->
    <RuleGroup name="" groupRelation="or">
      <NetworkConnect onmatch="exclude"/>
    </RuleGroup>
    <!-- Event ID 5 == ProcessTerminate. Log all processes terminated -->
    <RuleGroup name="" groupRelation="or">
      <ProcessTerminate onmatch="exclude"/>
    </RuleGroup>
    <!-- Event ID 9 == RawAccessRead. Log all raw access read -->
    <RuleGroup name="" groupRelation="or">
      <RawAccessRead onmatch="exclude"/>
    </RuleGroup>
    <!-- Event ID 10 == ProcessAccess. Log all open process operations -->
    <RuleGroup name="" groupRelation="or">
      <ProcessAccess onmatch="exclude"/>
    </RuleGroup>
    <!-- Event ID 11 == FileCreate. Log every file creation -->
    <RuleGroup name="" groupRelation="or">
      <FileCreate onmatch="exclude"/>
    </RuleGroup>
    <!--Event ID 23 == FileDelete. Log all files being deleted -->
    <RuleGroup name="" groupRelation="or">
      <FileDelete onmatch="exclude"/>
    </RuleGroup>
  </EventFiltering>
</Sysmon>

Linux虚拟机上的串行控制台痕迹

使用串行控制台访问虚拟机的证据可在虚拟机的原生Syslog和Sysmon for Linux日志中找到。串行控制台连接通过Linux虚拟机上的/dev/ttyS0进行。

使用Syslog追踪活动

识别启动串行控制台访问Linux虚拟机,它将在ttyS0上启动连接,并显示用户名和密码的身份验证提示以登录虚拟机。可使用以下查询识别:

1
2
3
4
Syslog
| where ProcessID == 1 
| where Facility == "daemon"
| where SyslogMessage has "Found device /dev/ttyS0"

要识别在Linux虚拟机上启用/dev/ttyS0时虚拟ttyS0终端的启动,可使用以下查询:

1
2
3
4
5
Syslog
| where ProcessID == "1"
| where Facility =~ "daemon"
| where SeverityLevel =~ "info"
| where SyslogMessage has "Started Serial Getty on ttyS0"

在Syslog原生日志中发现使用串行控制台成功访问虚拟机:

1
2
3
4
Syslog
| where ProcessID == 1 
| where ProcessName =~ "systemd"
| where SyslogMessage has "serial-getty@ttyS0.service: Succeeded"

查找使用串行控制台连接虚拟机的失败登录尝试。失败尝试次数也会在syslog日志中捕获对应用户帐户的时间点:

1
2
3
Syslog
| where ProcessName =~ "login"
| where SyslogMessage has "FAILED LOGIN" and SyslogMessage has "/dev/ttyS0"  

使用串行控制台成功身份验证后使用sudo将在syslog authpriv日志中捕获,执行的命令带有sudo,并且带有sudo的命令也会被捕获:

1
2
3
Syslog
| where ProcessName =~ "sudo"
| where SyslogMessage has "TTY=ttyS0" and SyslogMessage has "USER=root"  

使用Sysmon for Linux追踪活动

成功安装Sysmon for Linux后,日志分析工作区开始在包含“Linux-Sysmon”的syslog消息中捕获Sysmon事件。以下查询可用于识别通过串行控制台访问的Linux虚拟机上的所有进程执行事件。Sysmon for Linux在事件ID 1下记录Linux虚拟机上的所有ProcessCreate事件。

此Kusto查询可以解析当前配置文件中提到的所有事件的Sysmon for Linux日志。此查询可保存为函数(例如Sysmon_for_linux),以使用事件ID字段搜索Linux虚拟机上的不同事件。

使用串行控制台的Linux虚拟机上的每个进程都有唯一的父进程和命令行。父进程ID将根据串行控制台会话而变化。父进程将是/usr/bin/bash,父进程命令行将是-bash。以下Kusto查询可以解析Sysmon for Linux日志中的事件ID 1(ProcessCreate),以识别使用串行控制台特殊管理控制台(SAC)执行的进程。但此查询有一个注意事项,因为它只投影从SAC控制台执行的直接子进程,而不是从shell脚本生成的进程。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Sysmon_for_Linux
| where EventID == 1 
| where ParentCommandLine == "-bash" or ParentCommandLine == "bash"
| extend ParentProcessId=tostring(ParentProcessId)
| join kind=inner (Sysmon_for_Linux
    | where EventID == 1
    | extend ProcessId=tostring(ProcessId)
    | where ParentImage has "/bin/login")
    on $left.ParentProcessId == $right.ProcessId 
| project
    UtcTime,
    Computer,
    User,
    CurrentDirectory,
    Image,
    CommandLine,
    ParentImage,
    ParentCommandLine,
    InitiatingProcessParentImage=ParentImage1,
    InitiatingProcessParentCommandLine=CommandLine1,
    LogonId,
    ProcessId,
    ParentProcessId,
    InitiatingProcessParentId=ParentProcessId1

例如,以下查询可以识别使用串行控制台在虚拟机上执行的进程(在登录用户上下文中)的所有公共网络连接:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Sysmon_for_Linux 
| where EventID == 3 // Network Connect
| where not(ipv4_is_private(tostring(DestinationIp)))
| where not(User in~ ("omsagent", "syslog", "systemd-resolve"))
| where not(Image has_any ("/opt/microsoft/azuremonitoragent/", "/opt/microsoft/omsagent/"))
| where DestinationIp !in ("127.0.0.1")
| project
    UtcTime,
    EventID,
    Image,
    tostring(ProcessId),
    tostring(User),
    Computer,
    Protocol,
    SourceIp,
    DestinationIp,
    SourcePort,
    DestinationPort,
    Operation
| join kind=inner (
    Sysmon_for_Linux
    | where EventID == 1 //Process Create
    | where ParentCommandLine == "-bash" or ParentCommandLine == "bash"
    | extend ParentProcessId=tostring(ParentProcessId)
    | join kind=inner (Sysmon_for_Linux
        | where EventID == 1
        | extend ProcessId=tostring(ProcessId)
        | where ParentImage has "/bin/login")
        on $left.ParentProcessId == $right.ProcessId 
    | project
        UtcTime,
        Computer,
        tostring(User),
        CurrentDirectory,
        Image,
        CommandLine,
        ParentImage,
        ParentCommandLine,
        InitiatingProcessParentImage=ParentImage1,
        InitiatingProcessParentCommandLine=CommandLine1,
        LogonId,
        tostring(ProcessId),
        ParentProcessId,
        InitiatingProcessParentId=ParentProcessId1)
    on ProcessId, User, Computer
| project UtcTime,Computer,User, Image, CommandLine,SourcePort,DestinationIp,DestinationPort 

使用Microsoft Defender for Endpoint(MDE)追踪活动

Microsoft Defender for Endpoint捕获Linux虚拟机的Azure串行控制台活动。此活动包括通过SAC控制台登录虚拟机、执行所有进程以及使用登录的串行控制台建立网络连接。到Linux虚拟机的串行控制台连接在具有设备/dev/vc/的虚拟控制台终端上建立。在一般场景中,到任何设备的直接串行控制台访问通过/dev/ttyS0进行。以下MDE的Kusto查询将提供与登录用户、执行的进程以及使用串行控制台建立的网络连接相关的信息。

以下MDE的Kusto查询将识别使用串行控制台登录的用户:

1
2
3
4
DeviceLogonEvents
| extend Terminal=tostring(parse_json(AdditionalFields).["Terminal"])
| where Terminal has "ttyS0" 
| project Timestamp, DeviceName,ActionType,LogonType,AccountDomain,AccountName,InitiatingProcessCommandLine, Terminal

以下Kusto查询识别通过串行控制台连接的会话期间执行的所有进程:

1
2
3
4
5
6
DeviceProcessEvents
| extend InitiatingProcessPosixAttachedTerminal=tostring(parse_json(AdditionalFields).InitiatingProcessPosixAttachedTerminal)
| where InitiatingProcessPosixAttachedTerminal != ""
| where InitiatingProcessPosixAttachedTerminal has "/dev/vc/" //virtual console devices for Serial Console 
| project Timestamp,DeviceName,FileName,ProcessCommandLine,InitiatingProcessFileName,InitiatingProcessCommandLine,AccountName,InitiatingProcessPosixAttachedTerminal
| sort by Timestamp desc 

以下Kusto查询将识别使用串行控制台执行的进程的所有网络连接:

1
2
3
4
DeviceNetworkEvents
| extend InitiatingProcessPosixAttachedTerminal=tostring(parse_json(AdditionalFields).InitiatingProcessPosixAttachedTerminal)
| where InitiatingProcessPosixAttachedTerminal has "/dev/vc/" //virtual console devices for Serial Console 
| project Timestamp,DeviceName,ActionType,RemoteIP,RemoteIPType,InitiatingProcessCommandLine, InitiatingProcessAccountName,InitiatingProcessPosixAttachedTerminal

狩猎可疑操作

以下是防御者可用于检测Azure串行控制台周围可疑活动的几个示例。

使用Sysmon for Linux事件日志狩猎可疑操作

攻击者可以通过Azure串行控制台获得初始访问权限,任何后续活动都可以使用串行控制台生成的进程谱系来识别。虽然有多个KQL(Kusto查询语言)狩猎查询可用于检测Linux虚拟机上的可疑操作,但以下Kusto查询对于狩猎最常见的技术特别有用。请注意,以下查询并未涵盖所有Linux攻击技术。但是,它提供了进程层次结构,安全分析师可以利用它来识别通过串行控制台在Linux机器上完成的活动。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Sysmon_for_Linux
| where EventID == 1 
| where ParentCommandLine == "-bash" or ParentCommandLine == "bash"
| extend ParentProcessId=tostring(ParentProcessId)
| join kind=inner (Sysmon_for_Linux
    | where EventID == 1
    | extend ProcessId=tostring(ProcessId)
    | where ParentImage has "/bin/login")
    on $left.ParentProcessId == $right.ProcessId 
| where Image has_any ("ssh", "netcat", "telnet", "rsh", "rcp", "rsync", "ftp", "smbclient", "smbmount", "smbget", "curl", "wget", "/nc", "ncat", "socat", "chisel", "pivoting", "proxy", "tunneling", "forwarding", "sshuttle", "htran", "iodine", "dnscat2", "dnscat3", "ptunnel", "udptunnel", "httptunnel", "proxytunnel", "stunnel", "sslh", "sslwrap", "proxychains")
    or Image has_any ("whoami", "history", "uname", "/ps", "passwd", "groups", "smbclient", "systemctl", "ifconfig", "/id", "ping", "traceroute", "whois", "nslookup", "dig", "host", "useradd")
    or Image has_any ("/var/tmp/")
    or CommandLine has_any ("dpkg -i", "dpkg-deb", ".deb")
    or (Image has "atd" and CommandLine has "atd")
    or (Image has "cron" and CommandLine has "cron")
    or (Image has "find" and CommandLine has "-perm")
    or (CommandLine has_any("chmod", "chown", "chattr"))
    or CommandLine has_any ("stop", "disable", "off", "pkill", "kill", "killall")
    or (Image has "find" and (CommandLine has_any ("password", "login", "token", "key")))
    or (Image has "find" and (CommandLine has_any ("pem", "pfx", "pgp", "gpg", "ppk", "p12", "cer", "p7b", "asc")))
| project
    UtcTime,
    Computer,
    User,
    CurrentDirectory,
    Image,
    CommandLine,
    ParentImage,
    ParentCommandLine,
    InitiatingProcessParentImage=ParentImage1,
    InitiatingProcessParentCommandLine=CommandLine1,
    LogonId,
    ProcessId,
    ParentProcessId,
    InitiatingProcessParentId=ParentProcessId1

使用Microsoft Defender for Endpoint狩猎可疑操作

访问串行控制台可被利用来滥用已知的本机系统映像以执行侦察、下载文件、搜索秘密和执行横向移动。以下查询将找到使用串行控制台执行的那些最常使用的本机映像:

1
2
3
4
5
6
7
8
let PotentialAbusedImages = pack_array("ssh", "netcat", "telnet", "rsh", "rcp", "rsync", "ftp", "smbclient", "smbmount", "smbget", "curl", "wget", "nc", "ncat", "socat", "chisel", "pivoting", "proxy", "tunneling", "forwarding", "sshuttle", "htran", "iodine", "dnscat2", "dnscat3", "ptunnel", "udptunnel", "httptunnel", "proxytunnel", "stunnel", "sslh", "sslwrap", "proxychains", "whoami", "history", "uname", "ps", "passwd", "groups", "smbclient", "systemctl", "ifconfig", "/id", "ping", "traceroute", "whois", "nslookup", "dig", "host", "useradd", "chmod", "chown", "chattr", "atd", "cron", "pkill", "kill", "killall");
DeviceProcessEvents
| extend InitiatingProcessPosixAttachedTerminal=tostring(parse_json(AdditionalFields).InitiatingProcessPosixAttachedTerminal)
| where InitiatingProcessPosixAttachedTerminal != ""
| where InitiatingProcessPosixAttachedTerminal has "/dev/vc/" //virtual console devices for Serial Console 
| where InitiatingProcessCommandLine has "bash"
| where FileName has_any (PotentialAbusedImages)
| project Timestamp,DeviceName,FileName,ProcessCommandLine,InitiatingProcessFileName,InitiatingProcessCommandLine,AccountName,InitiatingProcessPosixAttachedTerminal

使用Azure活动日志狩猎可疑操作

除了第一部分提到的狩猎技术外,还可以使用以下查询识别异常的串行控制台连接活动:

1
2
3
4
AzureActivity
| where OperationNameValue == "MICROSOFT.SERIALCONSOLE/SERIALPORTS/CONNECT/ACTION"
| make-series perCount=count() on TimeGenerated from ago(15d) to now() step 1d by CallerIpAddress, Caller
| render timechart 

使用启动诊断日志狩猎可疑操作

在第一部分中,我们讨论了对手如何滥用启动诊断日志来泄露敏感信息。然而,启动诊断日志仍然是活动识别的重要来源。在诸如Syslog之类的日志未备份到中央位置(如SIEM)的情况下,启动诊断日志可以提供关键见解。由于它们可能包含敏感数据,这些日志不会备份到SIEM。但在日志缺失的情况下,它们具有重要的取证价值。

以下是执行LinPEAS(一种流行的权限提升工具)和使用Netcat的反向shell连接性。[请注意,Microsoft不认可使用这些工具,读者有责任负责任和道德地使用这些工具。在使用这些工具针对Azure或其他Microsoft基础设施之前,请检查我们的服务条款。]

最佳实践

以下是我们推荐的保持Azure串行控制台安全的最佳实践非详尽列表:

  • 对所有具有“虚拟机参与者”访问权限的用户强制执行
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计