使用 ModSecurity 和 ELK 进行连续的安全监控

在这篇博文中,将讲述在建立这样一个监控和警报系统时的经历和面临的挑战。

日志记录和监控不足

2017年,OWASP引入了新的风险“日志记录和监控不足”,此风险作为网络应用风险清单前10名更新的一部分。尽管不是一个直接的漏洞,但OWASP将日志记录和监控不足列为有效的日志记录和监控是一项重要的防御措施。通过持续监控日志文件来快速检测异常可以帮助公司快速识别和响应攻击,从而有可能防止攻击。

OWASP建议:

  • 应该有一个记录各种认证和授权事件的系统,比如失败的登录尝试、暴力攻击等。
  • 必须建立有效的监测和警报系统,此系统能够发现可疑活动并及时作出反应。
  • 如果出现问题,必须通知相关团队。
  • 必须采用行业标准事故响应和恢复计划,如NIST 800-61版本2或更高版本。

不管我们是小型组织还是企业级组织,我们必须考虑的一点是监控对我们的应用程序和网络的攻击。我们需要一个实时监控系统,在那里可以保护我们的应用程序,万一有人试图攻击,我们可以识别并采取必要的行动来阻止它。

为了实现这一点,我们需要一个集中的系统,在这个系统中,我们可以连续地监控日志,在仪表板中可视化数据,并且有一个可以通知攻击的通知系统。

在这个博客中,我们将讨论如何在一个应用程序中将ModSecurity设置为一个网络应用防火墙(WAF),该应用程序将它的日志假脱机到ELK堆栈进行监控,并使用弹性文件进行报警。这可以为现有的SIEM(安全事件和事件监控)解决方案提供信息,或者作为独立的使用开源解决方案的主动监控系统。

工作流程

使用ModSecurity和ELK的连续监控和报警系统的高级工作流程可描述如下:

  1. 实施ModSecurity WAF。
  2. 分析ModSecurity WAF日志中的OWASP十大风险。
  3. 使用ELK堆栈进行分析和可视化。
  4. 监控警报攻击模式和源IP。

在网络中使用ModSecurity和ELK进行监控和报警的图示如下所示:

图表中编号实体的工作/角色如下:

  1. 被WAF阻止的恶意请求。
  2. ModSecurity作为WAF运行。
  3. 配置Nginx代理服务器。
  4. 存储在服务器上的Web应用程序。
  5. WAF通过Nginx生成的日志和应用程序日志。
  6. 节拍:将日志从服务器发送到日志存放处
  7. Logstash:一个开源的数据处理管道,从多个来源接收数据。
  8. 弹性搜索:方便地存储、搜索和分析数据。
  9. Kibana:可视化弹性搜索数据,并为所需信息提供配置仪表板的选项。
  10. 弹性搜索是一个开源框架,用于根据弹性搜索中的数据对给定模式发出警报。
  11. 通过电子邮件/其他通信渠道收到的警报。
    现在让我们详细讨论每个实体。

ModSecurity

ModSecurity是一个WAF(网络应用程序防火墙),一个开源工具包,它为网络应用程序维护者提供了对HTTP流量的可见性和对攻击的高级保护。

安装后,ModSecurity将生成一个包含所有被阻止请求的日志文件。基本上有三个日志文件将被配置成Nginx和ModSecurity配置文件:

  • 错误日志
  • 调试日志
  • 审计日志

错误日志

当在服务器上遇到错误或任何恶意尝试时,会生成错误日志。因为我们已经用Nginx配置了我们的设置,所以所有的错误日志(包括Nginx错误)都在同一个文件“error.log”中生成,该文件默认位于以下路径:
/var/log/nginx/

调试日志

调试日志用于调试目的,对故障排除非常有用。它可以通过“modsecurity.conf”文件启用。

审计日志

审核日志不仅包含ModSecurity检测到恶意事件时生成日志的详细信息,而且还包含系统客户请求的有用信息,该信息包括客户端标头和数据有效负载,默认情况下,它未启用,可以通过“modsecurity.conf”配置文件进行配置。
在这里,我们将只关注“error.log”,并解析这些信息,然后进行分析。

Elasticsearch、Logstash、Kibana


让我们了解一下Filebeat和ELK的作用:

Filebeat——Filebeat负责将所有日志转发到日志存储,日志存储可以进一步通过管道传递。它重量轻,支持SSL和TLS加密,非常可靠。

Logstash——Logstash是一个用于解析日志并将其发送到Elasticsearch的工具。它功能强大,可以创建管道和索引事件或日志。它可以用于Elasticsearch生态系统。

Elasticsearch——这是一个高度可扩展的开源分析引擎。它允许我们快速存储、搜索和分析数据。当我们处理复杂的搜索特性和需求时,它通常很有用。它还能够在Lucene标准分析器之上提供一个分布式系统用于索引。

Kibana——这是一个与Elasticsearch集群交互的用户界面工具,并且能够可视化Elasticsearch数据。

分析ModSecurity 错误日志

现在让我们分析日志,了解在创建监控可视化时有用的所有参数。

下图显示了一个示例攻击错误日志。

上面截图中的每个编号部分解释如下:

  1. 我们首先需要的是生成请求的客户端IP地址。
  2. 下一个重要信息是ModSecurity配置文件路径,ModSecurity在其中定义攻击规则。攻击名称将从路径中提取。在上图中,文件路径如下:/usr/local/OWA sp-modsecurity-CRS/rules/REQUEST-941-APPLication-ACCEST-XSS . conf
  3. 接下来的信息是由ModSecurity生成的消息,它将在未来的工作中对我们有用。
  4. 包含攻击参数和有效载荷的数据。
  5. 最重要的是——我们从日志中提取的URI。
  6. 用于跟踪目的的唯一id值。

配置ELK

您可以在系统中配置Filebeat、Elasticsearch、Logsost和Kibana:

使用Filebeat配置日志

一旦安装了Filebeat,我们就需要在Filebeat配置文件中提供日志,这样它就可以将日志发送到Logstash。然后,Logstash会将它们发送到Elasticsearch。

Filebeat.yml——配置文件:

 filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
filebeat.modules:
-module: logstash
 log:
   enabled: true
filebeat.inputs:
-type: log
 enabled: true
 paths:
  /etc/log/nginx/error.log
output.logstash:
 enabled: true
 hosts: logstash_server
ssl.enabled: false

配置Logstash

Logstash配置文件采用JSON格式,位于“/etc/logstash/conf.d”。配置文件由三部分组成:输入、过滤器和输出。
我们创建了一个配置文件“beats-input.conf”,然后我们设置了“Filebeat”输入:

beats-input.conf:

input {
beats {
port => 5044
codec => "json"
     }
}
Filter {
        if [message] =~ "\A\{.+\}\z" {
   json {
     source => "message"
     target => "httpRequest"
   }
   mutate {
     remove_field => [ "json", "message" ]
   }
}
mutate {
          remove_field => [ "json", "agent" ]
          remove_field => [ "json", "tags" ]
          remove_field => [ "json", "thread_name" ]
    }
}
output {
   elasticsearch {
     hosts => [“elasticsearch_server:9200]
     manage_template => false
     index => "logstash-%{+YYYY.MM.dd}"
  }
}

将数据输入Elasticsearch

一旦一切就绪,数据将被解析并发送到Elasticsearch服务器,该服务器将快速索引和分析数据。下一步是可视化的Kibana弹性搜索的设置。


设置Kibana

为了从Elasticsearch中获取数据,首先我们需要在Kibana创建一个“索引模式”,然后按照下图所示的步骤操作:

步骤1:通过在索引模式字段中将索引模式定义为logstash-* 来创建索引模式。

步骤2:接下来,在时间过滤器字段中提供@timestamp,这将确保按时间过滤您的数据。

步骤3:点击“Discovery”图标来查看你的日志。

你应该会看到消息字段中反映的所有WAF错误日志。

Kibana可视化的ModSecurity日志

在Elasticsearch中输入日志后,我们会将单个信息(如下所述)作为索引进行分离,这样我们就可以在仪表板上显示所需的信息。

我们需要仪表板上日志的以下信息:

  • 客户端IP地址
  • 攻击请求
  • 攻击名称
  • 攻击模式(有效载荷)
  • 攻击网址

当日志从Logstash发送到Elasticsearch并在Kibana中呈现时,数据在“消息”字段中以非结构化方式发送。在这种情况下查询有意义的信息会很麻烦,因为所有的日志数据都存储在一个键下。日志消息应该更好地组织,因此我们使用Grok。

Logstash Gork过滤器插件

Grok是Logstash中的一个过滤插件,它将非结构化数据解析成结构化和可查询的数据。它使用文本模式来匹配日志文件中的行。

如果你仔细观察原始数据,你会发现它实际上是由不同的部分组成的,每个部分由一个空格隔开。

在利用Logstash Grok过滤器的同时,使用Grok过滤器模式创建结构化数据。Logstash Grok过滤器具有100多种内置模式,用于结构化非结构化数据。

由于我们在modsecurity “error.log”数据的内置模式方面运气不佳,我们使用一个名为Grok调试器的在线工具和一些有用的Grok模式构建了一个定制的Grok模式。

定制模式。

Grok支持正则表达式。Grok使用的正则表达式库是Oniguruma,更多细节可以访问Grok过滤器插件网站。

使用oniguruma正则表达式将允许您匹配一段文本并将其保存为字段,语法:

(?< field_name >the pattern here)

首先,让我们使用以下语法从消息数据中过滤时间戳:

(?< timestamp >%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME})

然后,我们将使用语法 % {GREEDYDATA:field_name} 作为攻击字段,隔离能够过滤的非格式化数据。

GREEDYDATA的意思是“.* ”。 他们扩展到尽可能多的字符,这是限制其周围的基础。

我们已经通过使用Grok过滤器 %{IP:客户端} 过滤了客户端的IP,它基本上是从日志数据中过滤IP地址。

以下是上述案例的Grok代码片段,解释了将非格式化数据隔离为攻击字段并删除消息字段的方法。

grok {
     match => { "message" => "(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) %{GREEDYDATA:attack}, client: %{IP:client}, server: %{GREEDYDATA:server}"}
     remove_field => ["message"]
}

grok的输出-

[error] 34#34: *215 [client 192.168.33.1] ModSecurity: Access denied with code 403 (phase 2). detected XSS using libinjection. [file "/usr/local/owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "37"] [id "941100"] [rev ""] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:email: "><Script>alert(0)</script>"] [severity "2"] [ver "OWASP_CRS/3.2.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "OWASP_CRS"] [tag "OWASP_CRS/WEB_ATTACK/XSS"] [tag "WASCTC/WASC-8"] [tag "WASCTC/WASC-22"] [tag "OWASP_TOP_10/A3"] [tag "OWASP_AppSensor/IE1"] [tag "CAPEC-242"] [hostname "172.18.0.2"] [uri "/login.action"] [unique_id "158625916198.227197"] [ref "v661,27t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls"]

现在我们需要从攻击域数据中过滤非格式化的值:

  • 攻击名称
  • 攻击请求
  • 攻击模式(有效载荷)
  • 攻击网址

攻击名称

因为我们没有其他非格式化值的Grok模式,所以我们可以使用正则表达式来查找非格式化的值。下面我们使用正则表达式来查找单独的攻击名称。

你可以使用这个网站进行在线正则表达式的创建、测试和调试——https://regex101.com/

如下图所示,在Grok调试器中,我们提取了路径值,然后将路径值从/usr/local/owasp-modsecurity-CRS/rules/REQUEST-941-APPLication-ACCEST-XSS.conf中剥离出来,作为REQUEST-941-APPLication-ACCEST-XSS

grok {
     match => {"attack" => "(?<attack_file>\[file \".+\/(.*?).conf\"\])"}
}
grok {
     match => {"attack_file" => "(?<attack_name>[A-Z][^.]+)"}
     remove_field => ["attack_file"]
}

其他数值

同样,我们从攻击字段数据中去除了其他值,并创建了一个包含所有隔离值的完整Logstash配置文件。

完全Logstash配置

input
{
   beats
   {
       ssl => false
       port => 5000
       codec => "json"
   }
}
filter {
   grok {
       match => { "message" => "(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER:threadid}\: \*%{NUMBER:connectionid} %{GREEDYDATA:attack}, client: %{IP:client}, server: %{GREEDYDATA:server}"}
       remove_field => ["message"]
 }
   grok {
       match => {"attack" => "(?<attack_file>\[file \".+\/(.*?).conf\"\])"}
 }
 grok {
       match => {"attack_file" => "(?<attack_name>[A-Z][^.]+)"}
       remove_field => ["attack_file"]
 }
   grok {
       match => {"attack" => "(?<attack_message>\[msg \"(.*?)\"\])"}
   }
   grok {
       match => {"attack" => "(?<attack_data>\[data \"(.*?)\"\])"}
   }
   grok {
       match => {"attack" => "(?<attack_uri>\[uri \"(.*?)\"\])"}
       remove_field => ["attack"]
   }
   grok {
       match => {"attack_uri" => "(?<attack_url>[/].+\")"}
   }
   if [message] =~ "\A\{.+\}\z" {
       json {
         source => "message"
         target => "httpRequest"
       }
       mutate {
         remove_field => [ "json", "message" ]
       }
   }
   mutate {
         remove_field => [ "json", "agent" ]
         remove_field => [ "json", "tags" ]
         remove_field => [ "json", "thread_name" ]
   }
}
output {
   elasticsearch {
     hosts => ["{{elasticsearch_server}}"]
     manage_template => false
     index => "logstash-%{+YYYY.MM.dd}"
  }
}

现在Elasticsearch索引中有多个字段,它可以过滤单个值。

攻击仪表板

现在让我们创建一个包含所有攻击计数和模式的仪表板。根据我们的要求,我们也可以把它想象成饼图或任何东西。

这总结了我们如何使用ModSecurity框架建立一个连续的安全监控和警报系统,并为进一步的微调留有余地。这个可以实现数据的可视化,并且可以根据需求定制仪表板。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!