目录
一、在Centos下安装httpd
查看安装是否成功
重启httpd
查看80端口是否开放
在主机上查询
查看防火墙
在浏览器中查询主机IP地址
查看日志是否生成
二、AWK +iptables+shell实战脚本案例
1、封堵扫描器
(1) 开始扫描器
特别注意:在Vim中尽量不要使用空格,否则会容易报错
给deny_scan.sh文件夹访问权限
查看脚本功能是否执行正常
(2) 结束扫描器
(3)过滤单位时间内访问量最高的ip,并把它写入到一个文件中
在apache访问界面中任意请求几次,生成temp文件
原因:时间不匹配
(4)防火墙防御扫描器shell脚本
补充知识点:
第一种执行方式:括号()
第二种执行方式:反引号 ``
2、防御SSH爆破脚本
脚本规定:当ssh登录次数超过三次,脚本直接封堵
(1) 测试代码功能是否完善
(2) 使用Windows自带命令窗口进行登录失败次数测试
(3) 基线检查shell脚本
[root@localhost centos]# yum install httpd -y
[root@localhost httpd]# service restart httpd
[root@localhost httpd]# systemctl restart httpd.service
[root@localhost httpd]# curl httpd://localhost
由此可见在主机上访问成功
[root@localhost httpd]# iptables -nvxL INPUT
由此可见httpd安装成功
[root@localhost httpd]# cd /var/log/httpd
[root@localhost httpd]# ls -al
total 12
drwx------. 2 root root 41 Aug 11 19:59 .
drwxr-xr-x. 21 root root 4096 Aug 11 19:43 ..
-rw-r--r--. 1 root root 2037 Aug 11 20:06 access_log
-rw-r--r--. 1 root root 1307 Aug 11 20:06 error_log
[root@localhost httpd]# vim access_log
#!/bin/bash
#找到你的日志路径log=/var/log/httpd
#找出一分钟之内的日志,找出ip最高的十个IP
#开始时间的一分钟之前
last_minutes=1start_time=$(date -d"$last_minutes minutes ago" +"%d/%m/%Y:%H:%M:%S")
echo $start_time
[root@localhost httpd]# chmod +x deny_scan.sh
脚本执行成功
此时是2023年8月12日1:27分钟,是脚本中的一分钟前
[root@localhost centos]# echo $(date -d"$1 minutes ago" +"%d/%m/%Y:%H:%M:%S")//一分钟之前
12/08/2023:01:29:28
[root@localhost centos]# echo $(date -d"$5 minutes ago" +"%d/%m/%Y:%H:%M:%S")//五分钟之前
12/08/2023:01:29:38
#!/bin/bash
#找到你的日志路径log=/var/log/httpd
#找出一分钟之内的日志,找出ip最高的十个IP
#开始时间的一分钟之前
last_minutes=1start_time=$(date -d"$last_minutes minutes ago" +"%d/%m/%Y:%H:%M:%S")
echo $start_time#结束时间
end_time=$(date +"%d/%m/%Y:%H:%M:%S")
echo $end_time~
执行成功:
#!/bin/bash
#找到你的日志路径logfile=/var/log/httpd/
#找出一分钟之内的日志,找出ip最高的十个IP
#开始时间的一分钟之前
last_minutes=1start_time=$(date -d"$last_minutes minutes ago" +"%d/%b/%Y:%H:%M:%S")
echo $start_time#结束时间
end_time=$(date +"%d/%b/%Y:%H:%M:%S")
echo $end_time
#通过awk进行top10的ip筛选
tac $logfile/access_log | awk -v st="$start_time" -v et="$end_time" '{t=substr($4,2);if(t>=st&&t<=et){print $1}}' | sort | uniq -c |sort -nr | head -n 10 > $logfile/log-ip-top10
查看日志
脚本执行成功
top10文件已生成
查看top10 文件
[root@localhost httpd]# vim log-ip-top10
发现top10 中没有内容
[root@localhost centos]# cat /var/log/httpd/access_log | head -n 1
查看帮助文档
[root@localhost centos]# date --help
解决方法:将月份修改成如下格式:
再次运行,此时时间ip基本吻合
再次执行代码,在浏览器提交任意信息,然后查看top10
由此可见,此时log-ip-top10内已经写入文件
查看log-ip-top10文件夹
[root@localhost centos]# cat /var/log/httpd/log-ip-top10
#找到你的日志路径
logfile=/var/log/httpd/
#找出一分钟之内的日志,找出ip最高的十个IP
#开始时间的一分钟之前
last_minutes=1start_time=$(date -d"$last_minutes minutes ago" +"%d/%b/%Y:%H:%M:%S")
echo $start_time#结束时间
end_time=$(date +"%d/%b/%Y:%H:%M:%S")
echo $end_time
#通过awk进行top10的ip筛选
tac $logfile/access_log | awk -v st="$start_time" -v et="$end_time" '{t=substr($4,2);if(t>=st&&t<=et){print $1}}' | sort | uniq -c |sort -nr | head -n 10 > $logfile/log-ip-top10
#log-ip-top10————10geip
#单位时间内,只允许10次访问ips=`cat `$logfile/log-ip-top10 | awk '{if($1 > 5)print $2}'
#由于Ip筛选了10个,因此需要循环处理
for ip in $ips
do
echo $ip >> $logfile/getip.txt
echo $ip
iptables -t filter -I INPUT -p tcp -m multiport --dport 80,443 -s $ip -j DROP
done
主要功能:防御恶意扫描器扫描并封堵
[root@localhost centos]# cd /var/log/httpd
[root@localhost httpd]# cat log-ip-top10
35 192.168.17.1
[root@localhost httpd]# cat log-ip-top10 | awk '{if($1 > 10)print $2}'
192.168.17.1
执行成功
查看/var/log/httpd/有无getip
此时getip已经写入
再次刷新apache网页,会发现此时网页无法正常刷新,此时防火墙将恶意扫描器给封堵住
查看防火墙状态
[root@localhost httpd]# iptables -nvvxL INPUT --line-numbers
由此可见此时防火墙打开并防御住恶意扫描器
举例:
[root@localhost httpd]# echo $(date)
[root@localhost httpd]# echo $(id)
举例
[root@localhost httpd]# echo $`date`
[root@localhost httpd]# echo $`id`
SSH爆破文件日志放在secure文件夹中
#!/bin/bash
logfile=/var/log/secure#第一步,扫描取出IP
IP=$(awk '/Failed password/{arr[$(NF-3)++]}END{for(i in arr){if(arr[i]>=3)print i}}' $logfile)
for ip in $ips
do
#-L -n :筛选IP;tr -s:转换格式 作用:筛选曾经被封堵过的IP
tmpIP=`iptables -L -n | tr -s " " | awk '/^DROP/ && /22$/{print $4}'`#{tmpIP[@]:shell标准语法,`@`和`*`是数组的特殊索引,表示返回数组的所有成员。
echo $ {tmpIP[@]} | grep -qw $ip
#$?——上次执行命令结果 前一次结果执行正确,输出0,否则输出1
if [ $? -ne 0]then
iptables -t filter -I INPUT -P tcp --DPORT 22 -J DROP
fi
done
unset tmpIP
#以下可省略
# #查看防火墙是否安装
# rpm -q iptables-services & > /dev/null
# #如果没有安装,则安装防火墙,并将其添加到开机自启动
# if [ $? -ne 0]
# yum -y install iptables-services & > /dev/null
# systemctl enable --now iptables.service & > /dev/null# fi
# #将配置保存到/etc/sysconfig/
# iptables-save > /etc/sysconfig/iptables
# #删除临时IP
# unset tmpIP
直接打印测试,此时打印六次,正确
[root@localhost log]# awk '/Failed password/{arr[$(NF-3)]++}END{for(i in arr){print i, arr[i]}}' secure
for循环后直接打印测试:循环打印六次,正确
[root@localhost log]# awk '/Failed password/{arr[$(NF-3)]++}END{for(i in arr){if(arr[i]>=4)}}' secure
执行判断条件arr[i]>=4后打印 i 测试:因为此时循环已超过三次,所以结果只打印一次
查看以下代码筛选结果,查看有无曾经封堵的IP:其中头部是DROP的则是封堵ip的关键字
[root@localhost centos]# iptables -L -n | tr -s " "
通过awk继续筛选DROP
[root@localhost centos]# iptables -L -n | tr -s " " awk '/^DROP/ && /22$/{print $4}'
#$?——上次执行命令结果 前一次结果执行正确,输出0,执行错误输出1
if [ $? -ne 0]
如果前一个结果输出为1,说明未曾封堵过IP,如果输出为0,说明曾封堵过IP
`[ integer1 -ne integer2 ]`:如果`integer1`不等于`integer2`,则为`true`。
如果不是0,接下来调用iptables进行封堵
then
iptables -t filter -I INPUT -P TCP --DPORT 22 -J DROP
删除测试secure目录下保存的数据
[root@localhost centos]# echo "" > /var/log/secure
当第三次输入命令出错时,ssh登录过程自动结束
给 deny_ssh_scan.sh提权
[root@localhost centos]# chmod +x deny_ssh_scan.sh
[root@localhost centos]# ./deny_ssh_scan.sh
此时可以看到ssh登录已经被限制
基线检查规定:
#! /bin/bash
fail=0
pass=0
manual=0
separator="------------------------------------------------------"
check_pass(){
echo -e "\033[42;30m [++]PASS \033[0m" #成功打印绿底黑字
let pass++
}check_fail(){
echo -e "\033[41;37m [++]FAIL \033[0m" #失败打印红底白字
let fail++
}check_manual(){
echo -e "\033[43;30m [++]请手动检测该项或依据实际情况判断!! \033[0m" #未检测到文件或须手动确认打印黄底黑字
let manual++
}echo "NO.1-检查是否设置口令生存周期"
pass_max_day=`cat /etc/login.defs | grep PASS_MAX_DAYS | grep -v ^# | awk '{print $2}'`if [ "$pass_max_day" -lt "90" ]; then
check_pass
elif [ "$pass_max_day" -gt "90" ]; then
echo "口令生存周期:$pass_max_day"
check_fail
else
check_manual
fi
echo $separatorecho "NO.2-检查是否设置口令最小长度"
pass_min_len=`cat /etc/login.defs | grep PASS_MIN_LEN | grep -v ^# | awk '{print $2}'`
if test -n "$pass_min_len"; then
if [ "$pass_min_len" -lt "8" ]; then
echo "口令最小长度:$pass_min_len"
check_fail
elif [ "$pass_min_len" -ge "8" ]; then
check_pass
else
check_manual
fi
else
check_manual
fi
echo $separatorecho "NO.3-检查是否配置口令过期提醒"
pass_warn_age=`cat /etc/login.defs | grep PASS_WARN_AGE | grep -v ^# | awk '{print $2}'`
if test -n "$pass_warn_age"; then
if [ "$pass_warn_age" -lt 30 ]; then
echo "口令过期提醒天数:$pass_warn_age"
check_fail
elif [ "$pass_warn_age" -ge "30" ]; then
check_pass
else
check_manual
fi
else
check_manual
fi
echo $separatorecho "NO.4-检查是否存在空口令账户"
empty_user=`cat /etc/shadow | awk -F : 'length($2)==0 {print $1}'`
if test -z "$empty_user"; then
check_passelif test -n "$empty_user"; then
echo "请检查空口令账户:$empty_user"
check_fail
else
check_manual
fi
echo $separatorecho "NO.5-检查是否存在特权账户"
root_account=`cat /etc/passwd | awk -F : '($3==0){print $1}'`
if [ $root_account=="root" ]; then
check_passelse
echo "请检查uid为0的账户: $root_account"
check_fail
fi
echo $separator
echo "NO.6-检查错误登录是否记录到日志"
FailLogin_log=`cat /etc/login.defs | grep FAILLOG_ENAB | grep -v ^# | awk '{print $2}'`
if [ $FailLogin_log=="yes" ]; then
check_pass
elif [ $FailLogin_log=="no" ]; then
check_fail
else
check_manual
fi
echo $separatorecho "NO.7-检查口令复杂度"
min_class=`cat /etc/security/pwquality.conf | grep minclass | grep -v ^# | awk '{print $3}'`
if [ "$min_class" -lt "3" ]; then
echo "口令类型少于3种!"
check_fail
elif [ "$min_class" -ge "3" ]; then
check_pass
else
check_manual
fi
echo $separatorecho "NO.8-检查重要文件的权限"
for i in /etc/shadow /etc/gshadow
do
tmppe=`stat -c %a ${i}`
if [ "$tmppe" -gt 400 ]; then
echo "${i} 权限为$tmppe"
check_fail
elif [ "$tmppe" -le 400 ]; then
echo "${i} 权限为$tmppe"
check_pass
else
check_manual
fi
donefor i in /etc/passwd /etc/group /etc/services /etc/profile
do
tmppe=`stat -c %a ${i}`if [ "$tmppe" -gt 644 ]; then
echo "${i} 权限为$tmppe"
check_fail
elif [ "$tmppe" -le 644 ]; then
echo "${i} 权限为$tmppe"
check_pass
else
check_manual
fi
donetmppe=`stat -c %a /tmp`
if [ "$tmppe" -gt 750 ]; then
echo "/tmp目录的权限为$tmppe"
check_fail
elif [ "$tmppe" -le 750 ]; then
check_pass
else
check_manual
fi
echo $separatorecho "NO.9-检查日志服务状态"
service_status=`systemctl status rsyslog | grep Active | awk '{print $2}'`
if [ $service_status == "inactive" ]; then
echo "日志rsyslog服务状态为:$service_status"
check_fail
elif [ $service_status == "active" ]; then
check_pass
else
check_manual
fi
echo $separatorecho "NO.10-检查常见日志文件是否非任意用户读写,建议非同组用户不可写"
for f in /var/log/cron /var/log/secure /var/log/httpd /var/log/auth.log /var/log/btmp
do
if [ -a ${f} ]; then
log_per=`stat -c %a ${f}`
if [ "$log_per" -ge 770 ]; then
echo "${f} 的权限为$log_per"
check_fail
else
echo "${f}的权限为$log_per"
check_pass
fi
else
echo "${f}文件不存在!"
check_manual
fi
doneecho $separator
echo "NO.11-检查FTP是否允许匿名登录"
ps_tmp=`ps -ef | grep ftp | grep -v grep`
if [ -z "$ps_tmp" ]; then
echo "ftp服务未开启"
check_pass
else
an_login=`cat /etc/vsftpd/vsftpd.conf | grep "anonymous_enable=NO" | grep -v ^#`
if [ -z "$an_login" ]; then
check_fail
else
echo "匿名登录:$an_login"
check_pass
fi
fi
echo $separatorecho "NO.12-检查history命令显示的条数,建议设置5条"
echo "历史命令显示条数:`cat /etc/profile | grep "HISTSIZE" | awk -F "=" '{print $2}'`"
check_manual
echo $separator
echo " 共检测项:$((pass+fail+manual))"
echo -e "\033[32m 通过项:$pass \033[0m"
echo -e "\033[31m 失败项:$fail \033[0m"
echo -e "\033[33m 手动检查项:$manual \033[0m"
echo "已完成Linux安全基线检查"
在centos下对这个脚本进行测试
[root@localhost centos]# vim linux_base_security.sh
给linux_base_security.sh提权
[root@localhost centos]# chmod +x linux_base_security.sh
执行该脚本
自动检查以下内容