暴力破解的自动阻断 项目背景:
只要是暴漏在公网云服务器,每天都会有大量的暴力破解行为
解决方法:
1.更换端口(无济于事) 2.买云防护,waf (贵)
爆破破解的一个自动阻断
re正则表达式 re模块 findall 找到匹配到的所有子串,并返回一个列表,如果没有匹配到就返回空
search 函数 扫描整个字符串,并且返回第一个,如果没匹配到就返回空
匹配元字符
1 2 3 4 \d 匹配所有数字0 -9 \D 匹配非数字\w 匹配所有单词字符,包括大小写字母 数字 下划线 中文\W 匹配剩下的,空格 换行符 特殊字符
匹配字符集
1 2 3 4 字符的集合,用表示,字符集内用“^”表示“非” \d= \D= \w!=??? 还有中文
匹配空白字符
1 2 3 4 空白符包含:' ' 空格 \n换行符 \t制表符 \r回车符 使用\s来匹配他们 [^\s] = \S
**{} **表示匹配标定字符数量
特殊数量符号
1 2 3 4 特殊数量符号:* 匹配前一个字符0or无限次 + 匹配前一个字符1or无限次. 匹配除换行符\n意外的任意1个字符
字符组 把字符用()括起来,叫字符组,目的就为将匹配成的字符串分组
匹配参数模式
1 2 3 4 findall方法其实他有第三个参数,他是默认参数,参数模式。 re.I 忽略大小写 re.S 匹配空白符 多个参数用 “|”
subprocess模块 项目需求:执行命令并将输出劫持实现日志的监控
用于启动新的进程的模块,它可以用于执行外部命令,获取进程的输出,向进程发送输入和等待进程结束。
多进程协同,python里大概有这么三种方式 1.os.system函数 阻塞式 2.multiprocessing 模块 使用场景,密集型的计算
3.subprocess模块
1 2 3 4 subprocess.run 执行指定的命令,等待命令执行完成后返回一个对象subprocess.call 执行指定的命令,返回命令执行的状态 (成功为0 失败为非0 )subprocess.check_all 与上面类似,区别是会输出报错subprocess.getoutput 执行命令,返回结果
参数说明:
1 2 3 4 5 6 7 8 subprocess.run (args, *, stdin =None, input =None, stdout =None, stderr =None, shell =False , timeout =None, check =False , universal_newlines =False ) subprocess.call(args, *, stdin =None, stdout =None, stderr =None, shell =False , timeout =None) args:要执行的命令,必须是个字符串,字符串参数列表 stdin stdout stderr : 子进程的标准输入 输出 错误 最常用的是subprocess.PIPE timeout : 设置命令超时 shell : 值为bool,如果参数为ture 将通过操作系统的shell执行命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 subprocess.Popen (它是上述几个方法的父类)process = subprocess.Popen( cmd, shell =True, stdout = subprocess.PIPE, stdin = subprocess.PIPE, stderr = subprocess.PIPE) shell : 打开终端,Linux中是终端,Windows中是cmdstdout =subprocess.PIPE:如果该命令执行成功,那么将该命令的标准输出放入管道 终端输入命令分两种:1. 直接在终端输入2. 进入环境再输入,比如python
在shell中执行命令:
在python终端中执行命令:
命令联动:
Linux日志分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 /var/ log/cron 记录系统的定时任务/var/ log/cups 打印信息的日志/var/ log/message 记录的系统重要信息的日志/var/ log/btmp 登录失败/var/ log/lastlog 最后一次登录/var/ log/wtmp 成功登录记录/var/ log/secure 登录日志/var/ log/utmp 目前登录用户的信息 登录成功 Accepted password for root from 172.30 .230.1 port 59865 ssh2 登录失败 Failed password for root from 172.30 .230.1 port 59891 ssh2 常用命令:find grep awk sed cat tail head
案例:
1 2 /etc/passwd从第10行开始显示5行cat /etc/passwd | tail -n +10 | head -n 5
1 2 只显示/etc/ passwd的账户名 cat /etc/ passwd | awk -F ':' '{print $1}'
1 2 3 4 定位有多少个ip在爆破主机的root账户 从/var/ log/secure中分析 登录失败:grep "Failed password for root" /var/ log/secure | awk '{print $11}' | sort | uniq -c | sort -nr 登录成功:grep "Accepted" /var/ log/secure | awk '{print $11}' | sort | uniq -c | sort -nr
封禁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 hosts黑名单 /etc/hosts.deny hosts白名单 /etc/hosts.allow 配置格式: 服务:地址:允许/封禁 服务: ssh ftp smb telnet 关键字(all):禁止或允许运行所有的服务 all:192 .168 .0 .10 :deny(全封) all:192 .168 .0 .10 :allow(加白) 地址:192.168.0.10 192.168.0.10 /24 (封C段)192 .168 .0 .*(封C段)192 .168 .0 . (封C段)
1 2 3 4 5 6 7 8 9 密码爆破 hydra hydra -l root -P 密码字典.txt -vV -e ns 10.210.100.131 ssh-l 指定用户 -L 指定用户字典 -P 指定密码字典 -vV 显示提示信息 -e ns 允许为空密码 ip 爆破的服务
1 2 封禁:sshd: 10.210 .100 .128 :deny
攻击机无法连接和爆破
项目实现思路 1.打开安全日志
2.实时监控安全日志
3.解析日志每一行的内容,找出正在爆破的ip
4.设置一个阈值,超过阈值后,封禁ip 添加到hosts.deny中
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 import reimport subprocessimport time logFile = '/var/log/secure' hostDeny = '/etc/hosts.deny' password_wrong_num = 5 def getDenies (): deniedDict = {} list = open (hostDeny).readlines() for ip in list : group = re.search(r'(\d+\.\d+\.\d+\.\d+)' ,ip) if group: deniedDict[group[1 ]] = '1' return deniedDictdef monitorLog (Logfile ): tempIp = {} deniedDict = getDenies() popen = subprocess.Popen('tail -f ' +logFile,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True ) while True : time.sleep(0.1 ) line = popen.stdout.readline().strip() if line: group = re.search('Invalid user \w+ from (\d+\.\d+\.\d+\.\d+)' ,str (line)) if group and not deniedDict.get(group[1 ]): subprocess.getoutput('echo \'sshd:{}\' >> {}' .format (group[1 ],hostDeny)) deniedDict[group[1 ]] = '1' time_str = time.strftime('%Y-%m-%d %H:%M:%S' ,time.localtime(time.time())) print ('{} --- and ip:{} to hosts.deny for invalid usr' .format (time_str,group[1 ])) continue group = re.search('Failed password for \w+ from (\d+\.\d+\.\d+\.\d+)' ,str (line)) if group: ip = group[1 ] if not tempIp.get(ip): tempIp[ip] = 1 else : tempIp[ip] = tempIp[ip]+1 if tempIp[ip] > password_wrong_num and not deniedDict.get(ip): del tempIp[ip] subprocess.getoutput('echo \'sshd:{}\' >> {}' .format (ip,hostDeny)) deniedDict[ip]='1' time_str = time.strftime('%Y-%m-%d %H:%M:%S' ,time.localtime(time.time())) print ('{} --- and ip:{} to hosts.deny for invalid password' .format (time_str,group[1 ]))if __name__ == '__main__' : monitorLog(logFile)
其中group[1]即匹配到的ip
靶机启动脚本:
攻击机执行爆破: