基于ossec工具调用lynis进行证书的扫描实现

基于ossec工具调用lynis进行证书的扫描实现

0.前言

在完成对于ossec的搭建以及lynis的搭建后,现在进行两者的结合,尝试实现基于ossec系统调用lynis进行过期证书的扫描

1.确定基础环境

  首先这里使用的版本ossec为2.8版本:

1
/var/ossec/bin/ossec-control restart

  然后查看lynis版本

1
lynis show version

2.设置环境变量

  在确定好版本后,接下来需要自定义一个脚本文件,让OSSEC调用Lynis来检查服务器证书的过期情况,但是由于我们如前片文章所介绍的样子,使用的是拉去压缩包的安装方式,并不是直接使用了yum安装,所以我们为了方便ossec的执行和调用,需要将lynis设置为环境变量

  首先编辑~/.bashrc文件

1
vim ~/.bashrc

  在文件末尾处添加

1
export PATH=$PATH:/home/lfs/lynis/lynis

  将/home/lfs/lynis/lynis替换为lynis可执行文件所在的实际目录路径即可,退出编辑模式,运行命令使得修改生效

1
2
cat ~/.bashrc
source ~/.bashrc

  这种则是会在当前用户的终端生效,而如果需要再所以用户的终端生效,则是在/etc/profile进行修改

1
2
3
4
vim /etc/profile
export PATH=$PATH:/home/lfs/lynis/lynis
cat /etc/profile
source /etc/profile

  这里发现了一个问题,尽管我们能够在lynis的文件夹中进行变量的使用,但是主要不在该指定的文件路径,变量无法使用,这会报错。,总觉得是个基本问题,但是无法解决:

  我怀疑是lynis具有比较特殊的东西,之前配置mysql等内容都没有问题,为了不影响进度,我直接删除了拉取安装的lynis文件,进行了yum的相关下载:

1
2
yum install epel-release -y
yum install lynis -y

  这样子就能任意位置直接执行lynis命令:

1
lynis

3.证书定位

  既然是要对证书进行过期查询,那我们就需要知道证书的路径,一般证书是我们自己存放,对于位置确定可以采用两种办法

  • 使用openssl命令

  使用openssl命令:运行以下命令来查看默认证书存储位置:

1
openssl version -d

  这表示CentOS上的证书文件路径为/etc/pki/tls。这也是OpenSSL的默认证书存储位置,可以在该目录下找到各种类型的证书文件,如.crt和.pem等,这里我们可以查看Openssl的配置文件,打开/etc/pki/tls/openssl.cnf文件,并搜索dir关键字,也能够找到证书和密钥文件的默认存储位置

  • find搜索

  使用find命令,运行以下命令来搜索系统上的证书文件

1
find / -name "*.crt" -o -name "*.pem"

4.创建自定义脚本

  在完成基础环境以及环境变量的修改后,接下来我们需要创建文件并写入脚本内容,写出一个openssl作为检测证书是否过期的命令后,添加到lynis的plugins模块中,最后使用ossec进行调用Lynis实现检查服务器证书的过期情况。在/home/lfs/目录下创建一个名为custom_pem_check.sh的脚本文件,首先我们需要找到plugins的扩展文件

1
2
3
4
find / -name plugins
cd /usr/share/lynis/plugins
ls
vim custom_pem_check.sh
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
#!/bin/sh

# Lynis Plugin: Check if /etc/pki/tls/cert.pem is expired

CERT_FILE="/etc/pki/tls/cert.pem"
EXPIRED="no"

if [ -f "$CERT_FILE" ]; then
EXPIRATION_DATE=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
EXPIRATION_TIMESTAMP=$(date -d "$EXPIRATION_DATE" +%s)
CURRENT_TIMESTAMP=$(date +%s)

if [ "$CURRENT_TIMESTAMP" -gt "$EXPIRATION_TIMESTAMP" ]; then
EXPIRED="yes"
fi
else
echo "The certificate file $CERT_FILE does not exist."
exit 1
fi

if [ "$EXPIRED" = "yes" ]; then
echo "The certificate in $CERT_FILE has expired."
exit 2
else
echo "The certificate in $CERT_FILE is still valid."
exit 0
fi

  执行效果:

  证明脚本内容正常,接下来进行插件的引入尝试

5. lynis导入证书判断插件

  首先我们要明确我们的证书查询验证插件导入是在阶段二中,由于对于插件有关的文章介绍很少,没有办法有效的对文章的内容与区别进行描述,所以我采用了github现有的插件案例进行尝试,在成功后进行与所给的例子插件文件进行对比,最后进行模仿尝试,达到导入证书判断插件的结果(r如果熟悉的花可以直接跳到最后一小点查看证书插件内容编写)

  • 插件内容引例

  例子链接:

1
https://github.com/nancheal/lynis-plugins/blob/master/default.prf

  在链接中给出了五个文件例子,并给出了对应的规范default.prf文件

  这里导入plugin_check_docker_group_phase2插件进行延展

1
2
3
vim /usr/share/lynis/plugins
ls
vim plugin_check_docker_group_phase2

  之后复制check docker的内容进行粘贴即可:

1
https://github.com/nancheal/lynis-plugins/blob/master/plugins/plugin_check_docker_group_phase2

  这是一个检查是否有docker组用户的插件,之后修改default.prf文件

1
2
3
vim /etc/lynis/default.prf

plugin=check_docker_group
1
lynis audit system --tests GROUP-0002

  这里运行后会提示有一些权限报错问题,我们需要安装提示进行修改权限,主要是三个情况,一个是访问”owner”应该是读写或只读的,第二个是对于”组”来说不够严格。访问”组”应该是读写、只读或无访问权限,最后就是对于”其他用户”来说不够严格。访问”其他用户”应该被拒绝或者只有读取权限:

1
chmod u=rw /usr/share/lynis/plugins/plugin_check_docker_group_phase2
1
chmod g=r /usr/share/lynis/plugins/plugin_check_docker_group_phase2
1
chmod o=r /usr/share/lynis/plugins/plugin_check_docker_group_phase2

  最后运行之后查看一遍权限

1
ll

  可以看到我们的文件 权限已经进行了相应的修改,接下来再次运行

  运行成功,插件成功的插入,接下来分析文件相关内容,查看修改了什么

  • 样本内容对照

  对比于lynis所给出的最初始样本custom_plugin.template文件,首先是修改了示例配置,这里自定义的将其归类到SUID类别中。并描述了该插件的功能是检查系统中是否存在docker组用户

  在了实例配置和Lynis的屏幕输出的注释模块中间添加空间并存放了我们所需要的shell代码主体内容

  这一段就是编写检查docker组的shell主体构造代码,之后便是修改自定义测试项的指引内容:

  在这里,我们注册了一个名为”GROUP-0001”的自定义测试项。这个测试项被认为是轻量级的,然后,我们使用Display函数在屏幕上显示一些信息。通过指定不同的参数,我们可以设置缩进、显示文本、结果文本和结果文本的颜色。在这个示例中,我们显示了”- checking docker group”的文本,并将结果设置为OK,并使用绿色作为结果文本的颜色,最后,调用了一个名为check_docker_group的函数,后续的内容则没有变化,也就是说明以上用红框圈出来的内容是我们需要修改或者添加的内容,因此,我们仿照进行思路的编写

  • 证书插件内容编写

  首先我们需要将前面编写的证书脚本加入一个函数框架的壳:

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
check_certificate_expiry() {
CERT_FILE="/etc/pki/tls/cert.pem"
EXPIRED="no"

if [ -f "$CERT_FILE" ]; then
EXPIRATION_DATE=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
EXPIRATION_TIMESTAMP=$(date -d "$EXPIRATION_DATE" +%s)
CURRENT_TIMESTAMP=$(date +%s)

if [ "$CURRENT_TIMESTAMP" -gt "$EXPIRATION_TIMESTAMP" ]; then
EXPIRED="yes"
fi
else
echo "The certificate file $CERT_FILE does not exist."
return 1
fi

if [ "$EXPIRED" = "yes" ]; then
echo "The certificate in $CERT_FILE has expired."
return 2
else
echo "The certificate in $CERT_FILE is still valid."
return 0
fi
}

  之后使用样本创建一个新的插件文件:

1
cp custom_plugin.template plugin_check_certificate_expiry_phase2

  这里需要注意,在前文也讲述过,对于命名规则而言是由一定讲究的,plugin [name] _phase [number]文件中,[name]的值应替换为插件的唯一名称。仅使用小写字符,数字和(可选)短划线( - )来链接两个单词。 [number]用以定义插件阶段,即1或2,我们这里选择的是2,并且这里的名字就是在default.prf中修改plugin的内容的名称

  接下来修改插件文件:

1
2
ll
vim plugin_check_certificate_expiry_phase2

  修改代码内容:

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/bin/sh

# -------------------------- CUT THIS SECTION ---------------------------
# This is a template to create a customized plugin
#
# Each plugin should at least have several variables defined with the
# prefix PLUGIN_* (see below)
#
# If you want to learn what functions you can use, check include/functions
#
# -------------------------- CUT THIS SECTION ---------------------------

#########################################################################
#
# * DO NOT REMOVE *
#-----------------------------------------------------
# PLUGIN_AUTHOR=Mr Auditor <auditor@4399.example.org>
# PLUGIN_CATEGORY=Custom
# PLUGIN_DESC=This is a custom tests about check pem
# PLUGIN_NAME=check_certificate_expiry
# PLUGIN_REQUIRED_TESTS=
#-----------------------------------------------------
#
#########################################################################
check_certificate_expiry() {
CERT_FILE="/etc/pki/tls/cert.pem"
EXPIRED="no"

if [ -f "$CERT_FILE" ]; then
EXPIRATION_DATE=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
EXPIRATION_TIMESTAMP=$(date -d "$EXPIRATION_DATE" +%s)
CURRENT_TIMESTAMP=$(date +%s)

if [ "$CURRENT_TIMESTAMP" -gt "$EXPIRATION_TIMESTAMP" ]; then
EXPIRED="yes"
fi
else
echo "The certificate file $CERT_FILE does not exist."
return 1
fi

if [ "$EXPIRED" = "yes" ]; then
echo "The certificate in $CERT_FILE has expired."
return 2
else
echo "The certificate in $CERT_FILE is still valid."
return 0
fi
}

#########################################################################
#
# Add custom section to screen output
InsertSection "Custom Plugin"
#
#################################################################################
#
# Test : CUST-0001
# Description : We show some lines on the screen

# Register our first custom test
# We consider it to be a lightweight test (no heavy IO, or long searches), no network connection needed
Register --test-no CUST-0001 --weight L --network NO --description "This is a custom tests about check pem"
if [ ${SKIPTEST} -eq 0 ]; then
# The Display function makes it easy to show something on screen, with colors.
# --indent defines amount of spaces
# --text text to be displayed on screen
# --result text at end of line
# --color color of result text
Display --indent 2 --text "- Checking certificate" --result OK --color GREEN
check_certificate_expiry;
fi
#
#################################################################################
#

# First check if OPENSSLBINARY is known as a prerequisite for this test.
if [ ! -z "${OPENSSLBINARY}" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
Register --test-no CUST-0001 --preqs-met ${PREQS_MET} --weight M --network NO --description "Description of custom test"
if [ ${SKIPTEST} -eq 0 ]; then
FOUNDPROBLEM=0
DIR="/my/path"
LogText "Test: we are going to check if we can find a particular directory (${DIR})"
# Check if a directory exists
if [ -d ${DIR} ]; then
LogText "Result: log entry for easier debugging or additional information"
else
FOUNDPROBLEM=1
LogText "Result: directory ${DIR} was not found!"
ReportWarning "${TEST_NO}" "This is a test warning line" "${DIR}" "text:Create directory ${DIR}"
fi

if [ ${FOUNDPROBLEM} -eq 0 ]; then
Display --indent 2 --text "- Checking if everything is OK..." --result OK --color GREEN
else
Display --indent 2 --text "- Checking if everything is OK..." --result WARNING --color RED
ReportSuggestion "${TEST_NO}" "This is a suggestion"
fi
fi
#
#################################################################################
#

# Wait for keypress (unless --quick is being used)
WaitForKeyPress

#EOF

  之后修改default.prf文件

1
2
3
vim /etc/lynis/default.prf

plugin=check_certificate_expiry

  再执行指令:

1
lynis audit system --tests CUST-0001

  同样的问题:

1
chmod u=rw /usr/share/lynis/plugins/plugin_check_certificate_expiry_phase2
1
chmod g=r /usr/share/lynis/plugins/plugin_check_certificate_expiry_phase2
1
chmod o=r /usr/share/lynis/plugins/plugin_check_certificate_expiry_phase2

  依旧是最后查看权限:

1
ll

  确认权限没有问题后开始执行:

1
lynis audit system --tests CUST-0001

  完成证书的导入

6.ossec实现调用lynis

  在agent上创建一个名为lynis_audit.sh的shell脚本文件。可以使用vim创建该文件,并写入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vim /home/lfs/lynis_audit.sh

#!/bin/bash
# 执行Lynis审计并将结果保存到临时文件
lynis audit system --tests CUST-0001 > /home/lfs/lynis_audit_result.txt
# 检查临时文件中是否存在"valid"关键字
grep -q "valid" /tmp/lynis_audit_result.txt
# 如果存在"valid"关键字,则返回0,否则返回1
if [ $? -eq 0 ]; then
echo "Valid keyword found."
exit 0
else
echo "Valid keyword not found."
exit 1
fi

cat /home/lfs/lynis_audit.sh

  为脚本添加可执行权限:

1
2
3
chmod +x /home/lfs/lynis_audit.sh
cd /home/lfs/
ll

  在OSSEC Agent配置文件/var/ossec/etc/ossec.conf中,添加新的本地检查,并定期运行lynis_audit.sh脚本。在部分内添加以下内容:

1
2
3
4
5
6
7
vim /var/ossec/etc/ossec.conf

<localfile>
<log_format>command</log_format>
<command>/home/lfs/lynis_audit.sh</command>
<frequency>3600</frequency>
</localfile>

  /home/lfs/lynis_audit.sh即是lynis_audit.sh脚本所在的实际路径。标签定义了脚本执行的频率,单位为秒。为铝封边观察,在这个例子中,脚本每20秒执行一次,可以执行命令进行查看脚本是否被运行了:

1
cat /var/ossec/logs/ossec.log |grep sh

  接下来在ossec server主机上的配置文件中,添加一个规则用来触发报警,在

1
<rules>

  部分中添加内容,由于一般来说ossec的规则现在基本是写在xml文件中,我们就需要找到一个相关的xml写入规则:

1
vim /var/ossec/etc/ossec.conf

  在这种情况下,我们就可以将新规则添加到local_rules.xml文件中。这是一个用于存放自定义规则的文件,通常位于/var/ossec/rules目录下

1
2
3
4
5
6
7
8
vim /var/ossec/rules/local_rules.xml


<rule id="100200" level="10">
<if_sid>530</if_sid>
<match>Valid keyword found.</match>
<description>Lynis audit found the valid keyword in the output of CUST-0001 test.</description>
</rule>

  重启server与agent的服务:

1
/var/ossec/bin/ossec-control restart

  最后查看报警内容

1
cat /var/ossec/logs/alerts/alerts.log


基于ossec工具调用lynis进行证书的扫描实现
https://one-null-pointer.github.io/2023/08/17/基于ossec工具调用lynis进行证书的扫描实现/
Author
liaoyue
Posted on
August 17, 2023
传送口