首页/安全/应急响应速查/Shell 历史排查(bash_history 取证)

Shell 历史排查(bash_history 取证)

命令历史是攻击手法最直接的旁证:找到所有用户的历史文件,识别被清空、被替换(软链到 /dev/null)或被改路径的情况。

应急响应速查安全更新于 2026-10-13

Shell 历史取证是什么

命令历史是攻击者行为最直接的旁证:他下载了什么、改了哪些文件、连过哪些主机,通常都能在历史文件里找到。bash 默认把交互式会话的命令写入 ~/.bash_history,并在会话正常退出时落盘,所以文件内容与登录会话次数、命令量存在可以交叉验证的关系。排查的动作有两层:找到所有用户的历史文件并看内容;同时判断它有没有被人为清空或做过手脚。

基本信息

默认位置各用户家目录下的 .bash_history;可被 HISTFILE 改到别处
其他 shell.zsh_history、.python_history、.mysql_history、.viminfo、.lesshst 同样留有操作痕迹
时间戳默认不记录时间;会话写入时会插入以 # 开头的时间戳行(存在 HISTTIMEFORMAT 时更明确)
常见反取证文件为空或只有几条、软链到 /dev/null、mtime 很新、属主异常
不记录的情况非交互式 shell、设置 HISTFILE=/dev/null、unset HISTFILE、命令前加空格配合 HISTCONTROL=ignorespace
权限要求普通用户只看得到自己的;其他用户需 root

典型使用场景

  • 确认攻击者登录后执行过什么,还原攻击链条
  • 判断主机是否被人清理过痕迹(历史为空本身就是信号)
  • 定位攻击者下载与释放的文件路径,为清理与检索提供关键字
  • 从历史里提取其他被访问的主机地址,用于判断横向范围
  • 为时间线补充命令级证据,与登录日志、进程记录互相印证

全盘定位并检查历史文件

全盘定位并检查历史文件
find / -xdev -name '.*history' -ls 2>/dev/null | head -n 30      # 全盘找历史文件
ls -la /root/.bash_history /home/*/.bash_history 2>/dev/null     # 权限、属主与时间
ls -l /root/.bash_history | grep -- '->'                         # 是否为软链接指向 /dev/null
tail -n 50 /root/.bash_history                                   # 看最近执行的命令
grep -c '' /root/.bash_history 2>/dev/null                        # 总行数,只有个位数就很可疑
awk -F: '{print $1, $7}' /etc/passwd | grep -v nologin | head    # 哪些账号有可用 shell,需要逐一查

可疑迹象读法

现象可能的含义下一步
文件为空但账号有登录记录被人为清空(history -c 或直接清空文件)与 auth.log 对照,确认登录次数与命令量的矛盾
文件是 /dev/null 的软链接刻意让记录丢弃检查是谁改的,并用上游日志补齐
文件只有极少几条命令攻击者保持历史精简,或刚被清理结合进程记录与网络连接还原
mtime 明显晚于最后登录时间有人在退出后又改过文件记录时间差异,作为篡改证据
属主不是该用户文件被替换或复制过来检查完整属性与 inode
命令存在明显缺口(编号跳号)部分记录被删除按缺口前后的命令推断被删内容
历史被清空本身就是高价值信号:不要因为「没内容」就跳过。把它与登录时间、shell 活动、进程记录交叉印证,往往能证明有人在刻意隐藏行为——这比看到几条正常命令更有判断价值。
留意历史里与其他文件的关联:curl 下载的地址、写入的脚本路径、编译或提权的命令,都是后续排查的关键字。把这些命令按时间(能取到时间戳时)排序,就是一条命令级时间线。

提取关键线索

提取关键线索
grep -nE 'curl|wget|chmod|chattr|nc |base64|crontab|useradd|visudo' /root/.bash_history | head -n 40   # 高价值命令
grep -nE 'ssh |scp |rsync ' /root/.bash_history | head -n 20                                        # 可能存在的横向痕迹
grep -rhoE '([0-9]{1,3}\.){3}[0-9]{1,3}' /root/.bash_history | sort -u | head -n 20                 # 提取地址
ls -l --time-style=full-iso /root/.bash_history /home/*/.bash_history 2>/dev/null | tee /evidence/hist_meta.txt
排查时不要直接在原文件上编辑或重命名:历史文件的 mtime 与 inode 分布本身就是篡改判据。要分析就复制到证据目录,原件保持不动。
能取到时间戳就一定要取:带时间戳的历史可以与登录日志、进程启动时间对齐,形成命令级时间线;没有时间戳时只能按命令顺序推断,结论里要写清这是推断而不是事实。

易错点

  • 只看 root 的:Web 服务账号与运维账号的历史同样有料,尤其部署账号常有大量命令
  • 看到空历史就跳过:先看权限与软链指向,空往往说明刚被清理,是重要线索而不是无关项
  • 把历史当权威证据:它没有默认时间戳,且可能被改写,需与登录与进程记录互相印证
  • 忽略其他 shell 与工具历史:zsh、python、mysql、vim 都会留下操作痕迹
  • 在原件上动手:重命名或编辑会改变时间戳,破坏篡改判定的依据

数据来源与参考

  • Bash 参考手册:HISTFILE 与 HISTTIMEFORMAT
  • SANS 反取证迹象识别

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌