历史命令时间戳还原
bash 默认只在历史文件里写命令文本、不写时间。开启 HISTTIMEFORMAT 之后,bash 每次写入历史时会先落一行以 # 开头、后接 Unix 秒数的标记,再写对应命令,因此可以把历史命令还原到秒级时间点。对 Linux 主机而言,这是少数带时间、又直接反映人工操作的痕迹来源。
基本信息
| 时间行格式 | #<Unix 秒数>,紧跟其后的那一行就是它对应的命令 |
|---|---|
| 生效方式 | HISTTIMEFORMAT 由 /etc/bashrc、~/.bashrc 或 /etc/profile 设置 |
| 换算命令 | date -d @<秒数>(GNU date);BSD 系用 date -r <秒数> |
| 默认行为 | 未设置该变量时历史文件中完全没有时间行 |
| 时间含义 | 命令被键入那一刻的秒数,取值受主机系统时钟影响 |
典型使用场景
- 还原主机上命令执行的先后顺序与相互间隔
- 判断某条命令处于入侵窗口内,还是日常运维的遗留记录
- 与认证日志的登录时段对照,确认命令归属哪个会话
- 发现历史文件被整体重写或伪造的迹象
- 导出带时间的历史清单,作为报告中的行为证据附件
解析成时间线
解析成时间线
grep -n '^#' /root/.bash_history | head # 先看时间行的分布
sed -n '1,20p' /root/.bash_history # 时间行与命令行交替出现
date -d @1697012345 '+%F %T %Z' # 单个时间行换算(GNU date)
awk '/^#/{t=substr($0,2); next} {print t" "$0}' /root/.bash_history | head -20 # 把时间挂到命令前
stat -c '%y %n' /root/.bash_history # 历史文件自身时间,作为时间区间旁证历史行读法
| 行内容 | 含义 | 注意点 |
|---|---|---|
| #1697012345 | 在其之后的命令被键入的时刻 | Unix 秒数,需按主机时区换算 |
| 普通命令文本行 | 被执行过的命令 | 不含输出,也不含被 HISTCONTROL 跳过的命令 |
| 空行与手工注释 | 人为整理或工具写入的痕迹 | 与时间行不成对时优先怀疑被改写 |
HISTCONTROL 会改变记录范围:ignorespace 跳过以空格开头的命令,ignoredups 合并连续重复命令,所以历史里的条目数并不等于命令的实际执行次数,统计时要把这一点写进说明。
历史文件可被任意改写,也是攻击者最常动手的位置;时间行没有任何校验机制,单凭它下结论风险很高,需与认证日志、审计记录或文件时间互证后才能采信。