📚 网络安全Kali学习系列 · 模块0-4 编程基础
已完成:模块0-1 Linux系统深度(6篇) ✅ | 模块0-2 计算机网络(4篇) ✅ | 模块0-3 密码学基础(3篇) ✅
14 Python安全编程:socket编程与端口扫描器 ✅
15 Bash脚本与安全自动化:工具链与日志解析(当前篇)
16 PHP基础与Web漏洞:危险函数与代码审计
17 JavaScript与前端安全:DOM操作与XSS
Bash脚本与安全自动化:工具链与日志解析
难度:入门 | 上一篇你用 Python 写了端口扫描器,本篇用 Bash 把零散命令粘合成自动化工作流——管道连接工具链,三剑客解析日志
读完本篇你将能:用管道(|)把 nmap、grep、awk 串成单行工具链,用 for 循环批量扫描 IP 列表,用 grep+awk 从 SSH 日志中提取暴力破解 IP 并生成统计报告——这是你在模块 4 学习后渗透时,快速分析靶机日志的核心技能。
📑 本文目录
01Shell与安全自动化:为什么Bash是胶水语言
02变量与管道:连接命令的流水线
03文本三剑客:grep/awk/sed 日志解析
04批量处理实战:多IP扫描自动化
05综合实战:SSH暴力破解检测脚本
06安全红线与练习
01 Shell与安全自动化:为什么Bash是胶水语言
上一篇你用 Python 编写了端口扫描器。但安全工作中很多场景不需要写完整程序——你需要的是把 nmap 扫描结果传给 grep 筛选开放端口,再把 IP 列表喂给另一条命令批量处理。这种"命令拼接"正是 Bash 的强项:Python 是造工具的语言,Bash 是粘合工具的胶水。
Bash 当前稳定版本为 5.2(最新补丁 5.2.37,2025 年 11 月发布,5.3 已宣布将在 2026 年内发布)。Kali Linux 自 2020 版起默认交互 Shell 改为 Zsh,但系统脚本和 /bin/bash 仍然是脚本编写标准。终端输入 bash --version 可确认版本。
| 特性 |
Python |
Bash |
| 定位 |
造工具(写新工具) |
粘工具(拼已有命令) |
| 启动速度 |
需解释器加载(~50ms) |
原生内核直接执行 |
| 文本处理 |
正则库 re、字符串方法 |
grep/awk/sed 原生支持 |
| 典型场景 |
端口扫描器、漏洞 POC |
日志解析、批量扫描、报告拼接 |
安全工程师的日常 workflow 通常是:nmap 扫描 → grep 筛选 → awk 提取 → 批量处理 → 生成报告。整条链路用 Bash 管道一行命令就能搞定,不需要写 .py 文件。本篇从最基础的管道和变量讲起,最终实现一个 SSH 暴力破解检测脚本。
02 变量与管道:连接命令的流水线
管道(|)是 Bash 最核心的概念:前一条命令的输出自动变成后一条命令的输入。模块 0-1 你学过 ls -la | grep "log",这里 ls 的文件列表流入 grep 筛选含 "log" 的行。安全场景中,管道最常见的用法是把扫描工具的输出喂给文本处理工具。
先看一个安全工具链示例——用 nmap 扫描本机,把结果传给 grep 只看开放端口:
Bash
# 用 nmap 扫描本机常见端口,只显示开放端口
nmap -sT --open 127.0.0.1 | grep "open"
# 输出示例
22/tcp open ssh
80/tcp open http
443/tcp open https
数据流向:nmap 输出 → 管道 → grep 过滤 → 终端显示。如果还要进一步提取端口号,可以继续接管道:
Bash
# 提取端口号,去掉表头行
nmap --open 127.0.0.1 | grep "open" | awk '{print $1}'
# 输出
22/tcp
80/tcp
443/tcp
这里 awk '{print $1}' 把每行按空格切分,取第一列(端口号)。三个命令用两个管道串联,数据像流水线上的零件一样逐站加工。
变量让命令可复用。Bash 变量赋值时等号两边不能有空格,引用时加 $ 前缀:
Bash
target="127.0.0.1"
ports="22 80 443"
# $() 捕获命令输出存入变量
open_count=$(nmap --open $target | grep "open" | wc -l)
echo "开放端口数: $open_count"
开放端口数: 3
$() 是命令替换——先执行括号内的命令,把输出结果赋值给变量。wc -l 统计行数,3 行就代表 3 个开放端口。整行命令实现了"扫描→过滤→计数→输出"的完整链路。
💡 小贴士
变量引用时,$var 和 "$var" 有区别。不加引号时变量值会按空格拆分成多个参数;加双引号则保持为单个字符串。安全脚本中推荐始终加双引号:"$target",防止变量含空格或特殊字符时命令出错。
03 文本三剑客:grep/awk/sed 日志解析
安全分析的核心工作是"从海量日志中淘金"。一个 SSH 服务在遭受暴力破解时,/var/log/auth.log 可能每秒产生几十条认证记录。人眼逐行看是不现实的,你需要三把"手术刀":grep 过滤、awk 提取、sed 替换。
| 工具 |
核心功能 |
安全场景 |
grep |
按关键词过滤行 |
筛选 Failed password 日志 |
awk |
按列提取与统计 |
从日志行中提取 IP 地址 |
sed |
文本替换与编辑 |
清洗日志格式、去除敏感信息 |
以 SSH 认证日志为例。先看一条真实的失败登录记录长什么样:
/var/log/auth.log
Mar 15 10:23:41 kali sshd[12345]: Failed password for invalid user admin from 192.168.1.50 port 54321 ssh2
Mar 15 10:23:44 kali sshd[12345]: Failed password for root from 192.168.1.50 port 54322 ssh2
Mar 15 10:23:47 kali sshd[12345]: Failed password for invalid user test from 10.0.0.5 port 54323 ssh2
每行包含时间、主机名、进程、用户名、源 IP、端口。安全工程师需要回答三个问题:谁在攻击?试了哪些用户名?哪个 IP 尝试次数最多?三剑客逐一解决。
grep:筛选失败登录行
Bash
# 筛选所有 SSH 失败认证记录
grep "Failed password" /var/log/auth.log
# 只看最近 100 行中的失败记录
tail -100 /var/log/auth.log | grep "Failed password"
awk:提取源 IP 地址
Bash
|
1
2
3
4
5
6
7
8
9
|
# awk 按空格分列,$11 是第11列(from 后面的 IP)
grep "Failed password" /var/log/auth.log | awk '{print $11}'
# 输出
192.168.1.50
192.168.1.50
10.0.0.5
# 统计每个 IP 出现次数并排序
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn
|
最后一条命令是安全日志分析的"黄金管线":sort 排序后 uniq -c 去重并计数,再 sort -rn 按次数降序排列。输出类似:
输出
142 192.168.1.50
38 10.0.0.5
12 172.16.0.3
一眼看出 192.168.1.50 尝试了 142 次密码——这就是暴力破解的来源 IP。模块 10 防御技术中,你会学习用 fail2ban 自动封禁这类 IP,而 fail2ban 的日志分析原理和这条管道命令完全一致。
sed:清洗日志格式
有时日志中的 IP 被额外信息包裹,需要用 sed 提取纯净的 IP。下面的命令用正则把 IP 后面的 port xxx ssh2 尾巴去掉:
Bash
# sed 去掉每行 "port" 之后的内容,只留 IP
grep "Failed password" /var/log/auth.log | sed 's/port.*$//'
# s/旧文本/新文本/ : 替换命令
# port.*$ 匹配 "port" 到行尾的所有字符
# 替换为空(//之间无内容)即删除
⚠️ 常见错误
awk '{print $11}' 用固定列号提取 IP — 不同系统日志格式不同,第 11 列可能不是 IP。例如 Ubuntu 的 auth.log 格式与 Kali 略有差异,$11 可能是端口号
✓ 正确:先用 grep "Failed" | awk '{print NR": "$0}' 查看完整行和列号分布,确认 IP 在第几列后再提取。或用 grep -oP '\d+\.\d+\.\d+\.\d+' 直接用正则提取所有 IP 格式的字符串。
04 批量处理实战:多IP扫描自动化
安全评估很少只扫描一个目标。内网渗透时你可能拿到一张 50 台机器的 IP 清单,需要逐台扫描开放端口。手动一台台执行 nmap 不现实——用 Bash 的 for 循环就能自动化这个过程。
先创建一个 IP 列表文件(模拟内网资产清单),然后写脚本逐行读取并扫描:
Bash · batch_scan.sh
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
# 批量扫描 IP 列表文件中的开放端口
targets="targets.txt"
report="scan_report_$(date +%Y%m%d).txt"
while read -r ip; do
echo "[*] 扫描 $ip ..."
nmap --open -T4 "$ip" | grep "open" >> "$report"
done < "$targets"
echo "[+] 扫描完成,报告已保存到 $report"
|
使用方式:先创建 targets.txt(每行一个 IP),再赋予执行权限运行:
Bash
# 创建目标列表
echo "127.0.0.1\n192.168.1.1\n192.168.1.100" > targets.txt
# 赋予执行权限并运行
chmod +x batch_scan.sh
./batch_scan.sh
[*] 扫描 127.0.0.1 ...
[*] 扫描 192.168.1.1 ...
[*] 扫描 192.168.1.100 ...
[+] 扫描完成,报告已保存到 scan_report_20260817.txt
脚本逐行解读:while read -r ip 逐行读取文件(-r 防止反斜杠被转义)。$(date +%Y%m%d) 把当前日期嵌入报告文件名,每天扫描生成独立文件。>> 是追加重定向——每个 IP 的结果追加到同一报告文件末尾,不会覆盖之前的内容。-T4 让 nmap 使用快速扫描时序模板。
💡 小贴士
while read 比 for ip in $(cat file) 更安全。后者会把含空格的行拆成多个词,且一次性把整个文件加载到内存。前者逐行读取,适合处理大日志文件。这是 Shell 脚本中"正确读取文件行"的标准写法。
05 综合实战:SSH暴力破解检测脚本
把前面学的管道、变量、grep/awk/sed 三剑客和 for 循环组装起来,写一个完整的 SSH 暴力破解检测脚本。这个脚本会分析 /var/log/auth.log,统计每个 IP 的失败登录次数,标记超过阈值的可疑 IP,并生成格式化报告。
Bash · ssh_brute_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
|
#!/bin/bash
# SSH 暴力破解检测脚本
LOG="/var/log/auth.log"
THRESHOLD=5
if [ ! -f "$LOG" ]; then
echo "[!] 日志文件 $LOG 不存在"
echo "[*] 在 macOS 上请改用 /var/log/system.log"
exit 1
fi
echo "=== SSH 暴力破解检测报告 ==="
echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "阈值: 超过 $THRESHOLD 次失败即标记为可疑"
echo "----------------------------------------"
# 提取失败 IP → 去重计数 → 降序排序
grep "Failed password" "$LOG" | grep -oP '\d+\.\d+\.\d+\.\d+' | sort | uniq -c | sort -rn | while read -r count ip; do
if [ "$count" -gt "$THRESHOLD" ]; then
echo "[!] 可疑 $ip - $count 次失败"
else
echo "[ok] $ip - $count 次"
fi
done
|
运行后输出示例:
输出
=== SSH 暴力破解检测报告 ===
生成时间: 2026-08-17 10:30:15
阈值: 超过 5 次失败即标记为可疑
----------------------------------------
[!] 可疑 192.168.1.50 - 142 次失败
[!] 可疑 10.0.0.5 - 38 次失败
[ok] 172.16.0.3 - 3 次
这个脚本整合了本篇所有知识点:grep -oP '\d+\.\d+\.\d+\.\d+' 用正则直接从整行日志中提取 IP 地址(不依赖固定列号,比 awk '{print $11}' 更健壮);sort | uniq -c | sort -rn 是统计排序的黄金管线;while read count ip 把"次数 IP"两列读入两个变量;if [ "$count" -gt "$THRESHOLD" ] 做阈值判断——超过 5 次的标红为可疑,否则标绿为正常。
⚠️ 常见错误
if [ $count -gt 5 ] — 变量不加引号,当 $count 为空时,命令变成 if [ -gt 5 ],语法错误导致脚本中断
✓ 正确:始终加引号 if [ "$count" -gt "$THRESHOLD" ],空变量变成空字符串,条件判断不会报错
06 安全红线与练习
Bash 脚本的自动化能力是一把双刃剑。一个 for 循环就能批量扫描 100 台服务器,但如果目标列表填错了,就可能在未经授权的情况下扫描了不该扫描的网络。批量扫描比单次扫描的法律风险更大——100 台服务器的日志会同时记录你的行为。合法练习方式:扫描本机 127.0.0.1、自己的虚拟机靶场(Metasploitable)、或使用自己搭建的 Docker 容器集群。
📖 知识回顾
管道|
变量$var
命令替换$()
grep过滤
awk提取列
sed替换
sort|uniq统计
while read循环
追加重定向>>
✏️ 动手练习
🟢 基础验证
用一条管道命令统计 /etc/passwd 文件中有多少个用户使用了 /bin/bash 作为登录 Shell。提示:grep "/bin/bash" /etc/passwd | wc -l。
🟡 组合应用
修改本篇的 batch_scan.sh,在扫描每个 IP 之前先 ping -c 1 检测主机是否在线,只有在线的主机才执行 nmap 扫描。提示:用 if ping -c 1 "$ip" >/dev/null 2>&1; then ... fi 判断 ping 是否成功。
🔴 开放挑战
为 ssh_brute_check.sh 添加自动封禁功能:对于超过阈值的可疑 IP,自动调用 iptables -A INPUT -s $ip -j DROP 封禁。提示:需要 root 权限执行 iptables;添加白名单机制避免误封自己的 IP;考虑把封禁记录写入单独日志文件。这是模块 10 防御技术中 fail2ban 的核心原理。
下篇预告
16 PHP基础与Web漏洞:危险函数与代码审计
将学习 PHP 基本语法与 eval/system/include 等危险函数,理解 SQL 注入和文件上传漏洞的代码层面成因——这是模块 2 Web 渗透之前,从源码视角理解漏洞本质的关键准备