Linux操作系统敏感文件监控开发

敏感文件监控

入侵检测很多,总结起来就是两大部分:流量,文件。

针对敏感文件进行监控:是否被篡改,是否新增内容,是否被删除... 进而发送通知,系统管理员可以及时关注到系统的运行情况。

一、敏感文件的监控原理

判断一个文件是否被篡改:可以使用 md5sum 命令记录文件的md5的数字指纹。md5是一种摘要算法,是不可逆的加密,只用于表示某个文件是否被篡改,或者用于保存密码。

在安全状态下,针对敏感文件生成基线的摘要数据(保存起来,下一次,再根据当前最新的文件状态生成一次,两次进行对比,可以知道是否被篡改)(潜在的风险:基线数据也被改了。解决方案:离线保存)

另外,针对文本型文件,还可以继续深入,去比较那些内容被篡改了。

二、先进行基线操作

 进行备份
 cd /opt
 mkdir -p baselearn/files
 cd baselearn/
 cp ../learn/* ./files/
 ​
 将 /opt/learn 中的文件备份在 /opt/baselearn/files/ 里面,一旦 /opt/learn 中的文件被篡改了,通过和 /opt/baselearn/files/ 中的文件进行md5sum 和 diff 的对比,就知道了到底是哪里出了问题
 ​
 md5sum /opt/learn*  #md5无法针对文件夹进行摘要,所以,如果learn目录下有文件夹则此命令无法成功执行
 那我们该如何解决这个问题呢?即如何直接对全部的文件进行md5加密计算?
 我们应该尝试先找到所有的文件,这样执行md5就容易多了
 find /opt/learn -type f | xargs md5sum  
 #这是比较标准的用法,找到/opt/learn这个目录下的所有文件并计算其md5摘要值
 find /opt/learn -type f | xargs md5sum > /opt/baselearn/learn.md5.base  
 #将上面计算好的基线数据保存起来
 #利用 md5sum -c learn.md5.base 来检查文件是否被篡改
 md5sum -c learn.md5.base
 ​
 说白了 -c 参数是用来重新检查文件的md5值的,比如我将一个目录下的所有文件的md5值全部重定向到了一个文件中(例如 learn.md5.base),然后我使用 md5sum -c learn.md5.base 就可以重新检查之前检查过的目录然后和这个文件中的md5值进行对比

image-20231015162153010

当然上面这个图不是上面的文件,只是演示一下结果

image-20231015163023147

其次,我们还可以使用 --quiet 参数来直接输出重新计算错误的文件

 md5sum -c --quiet learn.md5.base
 #当然,这种方式完全可以使用grep来代替
 ​
 #然后将对比失败的文件信息保存到 learn.diff
 md5sum -c --quiet learn.md5.base > learn.diff

image-20231015163151100

三、比较文件内容的具体修改部分

在这里使用的是 diff

 diff /opt/learn/date.txt /opt/baselearn/files/date.txt
 2d1
 < 2021-08-18 15:44:06
 ​
 diff /opt/baselearn/files/date.txt /opt/learn/date.txt
 1a2
 > 2021-08-18 15:44:06
 ​
 比较两个文件内容的不同之处:d 代表删除,a 代表新增, c 代表修改
 2d1 :左边的文件的第二行相对于右边的文件第一行删除了一行

那么如何检测目录下有新增的文件,在这里就拿 /opt/learn/ 目录中的文件 和 /opt/baselearn/files/ 中的文件进对比(因为原本/opt/baselearn/files/ 中的文件就是/opt/learn/ 中文件的备份 )

 diff /opt/learn/ /opt/baselearn/files/ | grep ^diff | awk '{print $2}'
 #最终结果就是被修改的文件
 diff /opt/learn/ /opt/baselearn/files/ | grep ^Only     #列出文件新增或删除的信息
 ​
 基于上述信息,通过sed替换得到完整的文件名
 diff /opt/learn/ /opt/baselearn/files/ | grep ^Only | sed -e 's/Only in //g' -e 's/://g'
 ​
 例如:
 [root@mycentos learn]# md5sum -c learn.md5.base 
 /opt/learn/moniter.sh: 确定
 /opt/learn/site_check.log: 确定
 /opt/learn/site_check.sh: 确定
 /opt/learn/test.txt: 确定
 ​
 [root@mycentos learn]# md5sum -c learn.md5.base | sed 's/: 确定//g'
 /opt/learn/moniter.sh
 /opt/learn/site_check.log
 /opt/learn/site_check.sh
 /opt/learn/test.txt
 ​

 target=$1 #这是原来的目录
 base=$2 #这是备份出来的目录
 action=$3
 ​
 if [ $action = "new" ]; then
     mkdir $base/files   #创建备份的目标位置
     cp $target/* $base/files/   #执行备份
     find $target -type f | xargs md5sum > $base/learn.md5   #将备份前目录下的所有文件生成md5摘    要值并输出重定向到 /opt/baselearn/learn.md5 中
 fi
 ​
 echo > $base/result.log
 ​
 md5sum -c --quiet $base/learn.md5 1> $base/learn.diff 2> /dev/null  #重新计算 /opt/baselearn/learn.md5 这个文件中不同文件的md5值并进行比较,将对比结果不一样的文件输出重定向,1> 重定向我们想要的内容,2> 将类似于 “md5sum: /opt/learn/moniter.sh: 没有那个文件或目录md5sum: 警告:1 个列出的文件无法读取”这种的信息丢掉
 ​
 remove=$(cat $base/learn.diff | grep "打开或读取失败" | sed 's/打开或读取失败//g') #意思就是查询之后删除一点内容,使输出更简洁 英文版的就将 打开或读取失败 换为 FAILED open or read
 ​
 if [ $? -eq 0 ]; then
     echo "$target folder was removed some files: $remove" | tee -a $base/result.log
 fi
 ​
 change=$(cat $base/learn.diff | grep "失败$")
 if [ $? -eq 0 ]; then
     echo "$target folder was changed some files: $change" | tee -a $base/result.log
     diff $target/ $base/files/
 fi
 #英文版的就将 失败 换为 FAILED
 ​
 list=$(diff $target/ $base/files/ | grep ^只在 | sed -e 's/只在 //g' -e 's/ 存在://g') #英文版的就是Only 和 :
 if [ $? -eq 0 ]; then
     echo "两个目录中有文件的数量的变化:$list" | tee -a $base/result.log
 fi
 ​
 mail -s "关键文件监控警报" 2811403517@qq.com < $base/result.log

比较文件的具体修改内容

 [root@mycentos opt]# diff /opt/learn/date.txt /opt/baselearn/files/date.txt
 2d1
 < 2023-10-16 19:15:34
 ​
 [root@mycentos opt]# diff /opt/baselearn/files/date.txt /opt/learn/date.txt
 1a2
 > 2023-10-16 19:15:34
 ​
 比较两个文件内容的不同之处: d 代表 删除,a 代表 新增,c 代表 修改
 ​
 #如何检测被检测目录下有新的文件
 diff /opt/learn /opt/baselearn/files/
 ​
 diff /opt/learn/ /opt/baselearn/files/ | grep ^diff | awk '{print $2}'
 ​
 diff /opt/learn/ /opt/baselearn/files/ | grep ^Only     #列出文件新增或删除的信息
 ​
 #基于上述信息,通过sed替换得到完整的文件名
 diff /opt/learn/ /opt/baselearn/files/ | grep ^Only | sed -e 's/Only in //g' -e 's/://g

image-20231016193726961

优化

1.完成上述敏感文件检测的脚本

2.确保已知的4个bug被修复:

  • 参数没有检查

  • 没有判断文件被修改的内容

    image-20231016204515306

    这个问题可以用 diff 的结果来解决,搭配 grep awk 等指令

  • 路径名里少了 / 符

  • 不管如何哪怕 $remove 和 $change 是空的,if 条件判断也依然是对的

3.防火墙应急安全

  • 如果发现有用户远程登录,并且失败多次,则直接封锁IP,并且强制断开对方可能的SSH连接

 target=$1 #这是原来的目录
 base=$2 #这是备份出来的目录
 action=$3
 ​
 ​
 if [ $action = "new" ]; then
         mkdir $base/files       #创建备份的目标位置
         cp $target/* $base/files/       #执行备份
         find $target -type f | xargs md5sum > $base/learn.md5
 fi
 ​
 echo > $base/result.log
 #正事开始之前,先清空日志文件
 ​
 md5sum -c --quiet $base/learn.md5 1> $base/learn.diff 2> /dev/null
 ​
 remove=$(cat $base/learn.diff | grep "打开或读取失败" | sed 's/:打开或读取失败//g')
 ​
 if [ $? -eq 0 ]; then
         echo "$target folder was removed some files: $remove" | tee -a $base/result.log
 fi
 ​
 change=$(cat $base/learn.diff | grep "失败$" | sed -e 's/失败//g' -e 's/: 打开或读取失败//g')
 if [ $? -eq 0 ]; then
         echo "$target folder was changed some files: $change" | tee -a $base/result.log
         diff $target/ $base/files/  #这个输出的就是两个文件不同的内容
 fi
 ​
 list=$(diff $target/ $base/files/ | grep ^只在 | sed -e 's/只在 //g' -e 's/ 存在://g' | sed 's/\g')
 if [ $? -eq 0 ]; then
         echo "两个目录中有文件的数量的变化:$list" | tee -a $base/result.log
 fi
 ​
 mail -s "关键文件监控警报" 2811403517@qq.com < $base/result.log
 ​

问题一:

输出错误信息,但错误结果为空

image-20231018215101553

从这里我们可以看到,就算我们

/opt/baselearn/learn.diff 文件中没有任何关于 FAILED open or read 的信息

但是我们依然使用了 sed 而且该命令使用完了之后 $? 的结果还是 0

我们将其赋值给 remove 的命令的 $? 的结果是 0 说明我们将一个空赋值给了 remove

这样使得 if [ $? -eq 0 ] 判断条件虽然成立,但是 remove 这个变量却是空的

所以就导致了,即使没有remove这个错,但依然输出了这句话 $target folder was removed some files

image-20231018215805044

就像这样,明明是空,但却依然输出了前面的话,该如何解决呢?

 将
 if [ $? -eq 0 ]; then
         echo "$target folder was removed some files: $remove" | tee -a $base/result.log
 fi
 改为
 if [ ${#remove} -gt 0 ]; then
         echo "$target folder was removed some files: $remove" | tee -a $base/result.log
 fi

同理可得:

 将
 if [ $? -eq 0 ]; then
         echo "$target folder was changed some files: $change" | tee -a $base/result.log
         diff $target/ $base/files/  #这个输出的就是两个文件不同的内容
 fi
 改为
 if [ ${#change} -gt 0 ]; then
         echo "$target folder was changed some files: $change" | tee -a $base/result.log
         diff $target/ $base/files/  #这个输出的就是两个文件不同的内容
 fi
 ​
 ​
 将
 if [ $? -eq 0 ]; then
         echo "两个目录中有文件的数量的变化:$list" | tee -a $base/result.log
 fi
 改为
 if [ ${#list} -gt 0 ]; then
         echo "两个目录中有文件的数量的变化:$list" | tee -a $base/result.log
 fi

问题二:

简化界面输出:

 将
 echo "$target folder was removed some files: $remove" | tee -a $base/result.log
 改为
 echo -e "******$target folder was removed some files:****** \n$remove\n" | tee -a $base/result.log
 ​
 同理:其他的 echo 都是一样的
 ​
 ​

问题三:

双斜杠的输出

image-20231019175654879

 将
 list=$(diff $target/ $base/files/ | grep ^只在 | sed -e 's/只在 //g' -e 's/ 存在://g' | sed 's/\g')
 if [ $? -eq 0 ]; then
         echo "两个目录中有文件的数量的变化:$list" | tee -a $base/result.log
 fi
 修改为
 list=$(diff $target/ $base/files/ | grep ^只在 | sed -e 's/只在 //g' -e 's/ 存在://g' -e 's/\/\//\//g')
 if [ ${#list} -gt 0 ]; then
         echo -e "******两个目录中有文件的数量的变化:****** \n$list" | tee -a $base/result.log
         diff $target/ $base/files/ | head -n 1 | sed -e 's/\/\//\//g'
         echo -e "\n"
 fi
 ​

问题四:

判断文件参数是否存在

使用 test 命令,配合逻辑或

在最上面的 参数 赋值 下面添加以下指令

 if [ ! -d $target ]; then
         echo "参数一不是一个有效目录"
         if [ ! -d $base ]; then
                 echo "参数二不是一个有效目录"
         fi
         exit 1
 fi
 ​

问题五:

如果将脚本应用于真正的文件中会有什么样的效果?

image-20231019204348071

image-20231019204356177

image-20231019204920491

如果第一个参数下还有目录呢,我们 cp 只是 cp 的普通文件

我们可以看到问题有:略过目录;自动执行了最后一个文件数量变化的检查功能

如何解决这些问题呢?

为什么会略过目录???

 仔细一想原来是cp命令的问题,我们普通的cp命令只是简单的拷贝普通文件,要想拷贝目录,还得加上 -r 参数
 将
 cp $target/* $base/files/
 改为
 cp -r $target/* $base/files/

改完之后就变成了这样

image-20231019205055034

最终成果:

 target=$1 #这是原来的目录
 base=$2 #这是备份出来的目录
 action=$3
 ​
 if [ ! -d $target ]; then
         echo "参数一不是一个有效目录"
         if [ ! -d $base ]; then
                 echo "参数二不是一个有效目录"
         fi
         exit 1
 fi
 ​
 if [ $action = "new" ]; then
         mkdir $base/files       #创建备份的目标位置
         cp -r $target/* $base/files/       #执行备份
         find $target -type f | xargs md5sum > $base/learn.md5
 fi
 ​
 echo > $base/result.log
 #正事开始之前,先清空日志文件
 ​
 md5sum -c --quiet $base/learn.md5 1> $base/learn.diff 2> /dev/null
 ​
 remove=$(cat $base/learn.diff | grep "打开或读取失败" | sed 's/:打开或读取失败//g')
 ​
 if [ ${#remove} -gt 0 ]; then
         echo -e "******$target folder was removed some files:****** \n$remove\n" | tee -a $base/result.log
 fi
 ​
 change=$(cat $base/learn.diff | grep "失败$" | sed -e 's/失败//g' -e 's/: 打开或读取失败//g')
 if [ ${#change} -gt 0 ]; then
         echo "******$target folder was changed some files:****** \n$change" | tee -a $base/result.log
         diff $target/ $base/files/  #这个输出的就是两个文件不同的内容
 fi
 ​
 list=$(diff $target/ $base/files/ | grep ^只在 | sed -e 's/只在 //g' -e 's/ 存在://g' -e 's/\/\//\//g')
 if [ ${#list} -gt 0 ]; then
         echo -e "******两个目录中有文件的数量的变化:****** \n$list" | tee -a $base/result.log
         diff $target/ $base/files/ | head -n 1 | sed -e 's/\/\//\//g'
         echo -e "\n"
 fi
 ​
 mail -s "关键文件监控警报" 2811403517@qq.com < $base/result.log

扩展内容:

目前的功能主要实现了针对某个特定目录下的所有普通文件进行监控,到那时,如果作为一个真正意义上的监控工具,通常会监控多个目录,会监控多个文件,甚至会指定监控某些特定文件

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值