ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

john 密码审计实战:哈希识别、字典规则与防破解加固

john 密码审计实战:哈希识别、字典规则与防破解加固 同事在群里甩过来一份内部自查报告说系统里还有一批账号的密码强度不达标需要我做一次密码安全审计。我当时手上能用的工具就一个john。很多人第一次听到“john 破解用户密码”这个说法第一反应会往歪处想但实际在一线做安全运维john the ripper 这类工具用得最多的场景恰恰是自查——给自己管的服务器、自己负责的业务系统、自己交付给客户的加密文件做一次强度体检看看哪些口令能在几分钟内被字典跑出来然后把它们换掉。真正危险的不是工具而是你从来不知道自己系统的密码到底有多脆。这篇内容就是把我这些年用 john 做密码审计和配套防破解加固的完整流程拆开讲一遍包括安装避坑、哈希识别、字典与规则调优、ZIP 压缩包密码自查以及更重要的那半边怎么让你的密码体系扛得住同类工具的冲击。适合安全运维、后端开发、运维工程师以及需要给自己产品或交付物做安全加固的从业者参考基础薄弱的朋友也能照着走一遍。1. 先搞清楚 john 到底在破解什么1.1 哈希不是密码破解的本质是比对新手最容易卡住的点是把“破解密码”想象成某种能直接读出明文的魔法。实际不是。现代系统里存的基本都是口令的散列值john 拿到的输入通常长这样admin:$6$kH9x...$3fA1bZ...:1000:1000:Admin:/home/admin:/bin/bash冒号后面那一串才是它真正处理的东西。john 的工作流程非常朴素——按某种策略生成候选口令用同样的算法算出散列值再跟目标散列值逐字节比对命中即停。所以它的速度上限并不取决于算法多聪明而取决于两件事候选口令的生成效率以及单位时间内能做多少次哈希运算。理解这一点之后很多后来的困惑就自动解开了。为什么字典文件质量决定成败因为候选池里没有正确答案跑一万年也没用。为什么同一个口令在不同系统上被跑出来的时间差几十倍因为 SHA-512 迭代轮数、bcrypt 的 cost 因子、内存硬算法带来的成本完全不同。为什么显卡比 CPU 快那么多因为哈希运算高度并行而 GPU 的核心数量是 CPU 的几十上百倍。我在实际项目里见过最典型的误判就是有人拿一堆 MD5 历史库去套现代系统发现跑不出来就觉得 john 没用。其实是对手从 MD5 换成了 bcrypt难度差了好几个数量级工具没问题是目标变了。1.2 三种模式对应三种完全不同的思路john 的模式选择不是随便挑的每种模式背后是一套假设你在什么场景下用哪种模式取决于你对目标口令的了解程度。单模式Single假设的是“用户图省事口令跟自己的账号信息有关”。它会拿用户名、家目录、GECOS 字段里的信息做变形组合。这个模式最大的价值是快——通常几秒钟就能跑完一轮而且命中率出乎意料地高。很多企业内网里zhangsan2024、liwei123这类口令就是被这个模式秒破的。字典模式Wordlist是最常用的。它把字典文件里的每一行当候选配合规则引擎做变形。它的核心变量只有两个字典的覆盖范围和规则的想象力。这两个变量的可调空间非常大后面我会单独拿一章讲。增量模式Incremental是穷举按字符集逐步爆破从短到长。它是最后手段因为时间成本呈指数增长。但它的好处是不依赖任何字典质量纯靠算力和时间硬堆。我在实操里的顺序固定是先 Single 跑一遍几十秒再 Wordlist 加规则几小时量级最后才考虑 Incremental。绝大多数真实场景在前两步就结束了直接上 Incremental 是新手最常见的资源浪费。1.3 它能做和它做不到的边界把边界划清楚能省掉大量试错。john 能做的是识别上百种哈希格式、处理多种加密容器的提取文件、支持规则变形、支持增量穷举、支持会话保存与恢复、支持多种加速后端。john 做不到的是绕过加盐salt 会显著增加成本但理论上仍可爆破、绕过强算法Argon2、高 cost 的 bcrypt 在合理口令面前基本无解、绕过非密码保护机制比如双因素、硬件密钥、绕过访问控制它处理的是离线文件不是在线爆破。注意john 处理的是“离线样本”。它不能登录任何系统也不做网络请求。这一点决定了它的合规边界——你可以用它审计你手里有权查看的哈希文件但拿到别人的哈希文件本身就是另一回事了。2. 安装与环境准备的那些坑2.1 版本路线怎么选john 有两条主要的版本路线很多人卡在第一步就是因为装错了版本还不知道。一条是社区版俗称 jumbo 之外的经典版本功能相对基础格式支持较少胜在稳定、编译简单。另一条是社区增强版通常叫 jumbo支持格式扩展到了上百种包括各种文档格式、容器格式的提取工具比如专门处理压缩包的那个辅助程序规则引擎也更完整。我的建议很直接做安全审计就用增强版。理由不是它“更强”而是它自带了一整套格式提取辅助程序你不用自己去写脚本解析文件头。少写一个解析器就少一个出错点。增强版官方提供的是源码包需要自己编译。编译前要确认系统里有 C 编译器、make以及几个可选依赖库。如果打算用 OpenMP 多线程还要确认编译器支持并打开对应开关。缺依赖不会导致编译失败而是会静默降级——你跑起来发现只用了一个核心性能差一大截还以为是硬件问题。我在第一次编译时踩的坑就是没装 OpenMP 开发包跑了一晚上才发现 CPU 占用只有 12%单核在跑。后来重新编译打开开关同样的任务时间直接掉了三分之二。2.2 各平台的落地方式不同系统上的处理方式差异不小我按我实际用过的排序说。在主流 Linux 发行版上官方源里有基础版本装起来一条命令就行但功能比较有限。如果要增强版就下载源码包解压进去之后先跑配置脚本再编译最后把生成的可执行文件和它依赖的辅助程序放到一个统一目录里。整个过程在三十分钟内能搞定前提是依赖没缺。在 macOS 上要注意两点一是系统自带的编译工具链要先装好二是如果用 ARM 架构的机器部分加速后端需要额外配置否则会退回纯 CPU 模式。我在 M 系列芯片上编译时最开始没指定架构参数结果跑出来的二进制性能明显不对劲重新编译后正常了。在 Windows 上官方提供了预编译包解压即用但它默认只有基础格式支持。我的经验是 Windows 上更适合做基础的哈希处理和学习用途真要做大规模审计还是放到 Linux 环境脚本化和批处理都方便太多。2.3 装完先做三件事装完之后千万别急着丢文件进去跑。先做三步自检能避免后面大量无效等待。第一确认可执行文件能正常输出帮助信息这一步是确认动态库链接没问题。第二确认辅助程序目录的路径正确。增强版的格式提取工具通常在一个子目录里如果你不在那个目录下执行或者没有把它加入环境变量就会遇到“命令找不到”的问题而这不是程序坏了。第三做一次性能基线测试。用一个小字典跑一个你自己造的测试哈希看看每秒尝试次数在什么量级。这个数字是你后面判断“加速是否生效”的基准线。我一般会记录 CPU 单核、多核、以及是否启用 GPU 三种情况下的数字方便后续对比。提示把这三个数字记在一个文本文件里跟项目记录放在一起。下次换机器或者改了编译参数直接对比就能知道有没有回退。3. 拿到哈希才是真正的起点3.1 从系统影子文件里取样本这是最经典的场景。系统的账号信息分两处存放用户基本信息在一处口令散列在另一处且权限很严格。john 增强版自带了一个合并工具可以把两者合成它需要的格式。合成之后的文件里每一行包含账号名和散列值。这个时候先别急着跑先把散列算法分类统计一下。同一个文件里往往混着好几种算法——老账号可能是旧格式新账号是新格式而它们的破解难度天差地别。散列前缀对应算法抗爆破强度$1$MD5 系很弱基本秒破$5$SHA-256 系中等依赖迭代轮数$6$SHA-512 系中等偏上依赖迭代轮数$2a$/$2b$bcrypt强依赖 cost 因子$y$yescrypt强$argon2$Argon2 系强内存硬这张表是我每次做审计的第一步筛查依据。如果统计下来大部分是$6$或者$2b$那这次审计的重点就不是“能不能破”而是“多久能破”以及“口令长度分布是否合理”。如果统计里还有大量$1$那这就是一个明确的整改项跟口令本身强弱已经无关了。3.2 哈希格式识别与手动指定john 的自动识别能力不错但它不是万能的。遇到识别不了的情况你需要手动指定格式否则它会跑一套错误的算法然后告诉你“跑完了零命中”——最坑的就是这种静默失败。手动指定的方法是在命令里加上格式参数。格式名怎么查用官方的格式列表参数会输出一长串支持的格式名和对应的示例散列。我的做法是先自动跑一次观察它的运行信息里显示的格式名如果没显示或者明显不对再手动指定。有一个很容易忽略的细节从某个容器里提取出来的散列值和系统影子文件里的散列值格式可能是一样的但提取工具为了让 john 能认出来会在散列前面加一个特定的标识前缀。这些前缀是提取工具生成的不是原始数据的一部分。如果你手动编辑过提取出来的文件把这些前缀删掉了john 就可能识别不出来。3.3 压缩包密码的自查流程这条是很多人的实际需求也是搜索里出现频率很高的场景自己很久以前打包的压缩包密码想不起来了或者要验证一下交付给客户的加密包强度够不够。流程分两步。第一步是用配套的提取工具把压缩包里的加密校验信息抽出来输出成一个文本文件。这个文件里就是压缩包密码对应的散列值。第二步才是把这个文件交给 john 跑。第一步的实现方式很直白就是在命令行里调用提取工具指定压缩包路径把输出重定向到文件。这里要注意有些压缩包内部包含多个加密条目提取出来的文件会有多行这属于正常现象john 会逐行处理。第二步跑的时候关键参数是字典和规则。这里有个真实经验压缩包密码在现实中往往比系统口令更“聪明”一点因为人设压缩包密码的时候通常知道它是自己用的会设得长一些。所以单纯跑一个大路货字典命中率不高配合规则变形才是正解。我个人的经验是如果对方是人为主观设定的密码包含日期、姓名缩写变形的概率很高规则引擎里要专门打开针对这类变形组合的规则集。跑出来之后john 会把结果存在它自己的结果文件里下次查看用展示参数即可不需要重新跑。这个记录文件是纯文本可以随时导出整理。3.4 文档与容器格式的通用套路除了压缩包还有几类特别常见PDF、办公文档、以及某些数据库的凭据容器。它们的处理套路是一致的先用对应的提取工具把加密参数抽出来再交给 john。这里有一个跨格式的通用注意点提取工具的输出质量和 john 的版本强相关。新版 john 支持的格式多但提取工具可能对某些新版本文档格式支持不完整。比如某个办公文档套件的新格式用旧版提取工具抽出来的散列可能是空的或者抽出来但 john 识别不了。这种情况下别硬刚。我的处理办法是先用文档自身的命令行工具把文件降级保存成老格式再提取。多数情况下问题就解决了。这个技巧在看文档里是找不到的纯靠踩坑积累。3.5 命令行参数怎么控制效率参数用对了同样的硬件能省一半时间。我固定会看这几个维度。并发控制默认情况下 john 会尽量用满可用核心。如果你在共享服务器上跑记得限制并发数别把生产环境的 CPU 跑满。这个参数在 john 的选项里可以直接指定。会话管理长任务一定要用会话参数保存进度中途中断可以用恢复参数接着跑不用从头来。我吃过一次亏跑了十几个小时的增量任务机器重启全没了只能重来。结果查看和清理查看用展示参数清理用重置参数。这两个操作我看很多人搞混——如果你只想看结果千万不要动记录文件一旦误删已经跑出来的结果就没了而且 john 不会重新记录。注意跑任何长时间任务之前先用一个小字典做一轮完整测试确认参数、字典路径、输出路径全对。五分钟的测试能省掉十小时的返工。4. 字典、规则与增量把效率拉满4.1 字典的清洗比收集更重要新手最爱干的事是到处收集字典包几十个 G 拼在一起。我早期也这么干效果很差。原因很简单字典是按“命中概率”排序才有价值的你拼成一坨john 从里面顺序读前面几百万条垃圾条目把时间全耗光了。正确做法是先做去重和清洗再去掉明显不适用的部分。我这里有几个固定步骤去重、去掉纯数字的超长序列这些交给增量模式更高效、把跟目标环境相关的词汇前置。所谓“跟目标环境相关”指的是项目名、公司名、产品名、缩写、常见拼音组合、年份组合。这一步的效果是决定性的。我在一次内部审计里标准大字典跑了两小时零命中把我整理的环境相关词汇放到前面重跑十七分钟出了六个结果。还有一个容易被忽略的点字典文件的编码。如果你的系统环境是 UTF-8而字典文件是别的编码某些字符会被错误解析导致候选口令失真。这个错误非常隐蔽因为程序不会报错只是安静地少跑一些候选。4.2 规则引擎才是真正的放大器字典模式如果只是原样读每一行那它的能力上限就是字典本身。规则引擎的作用是把每一条基础词做变形一变十、十变百。常用的变形维度包括大小写切换、首字母大写、末尾加数字、末尾加常见符号、数字替换字母比如用 0 替 o用 1 替 i、前后加年份、重复拼接、常见大小写混写模式。这些变形的组合数量可以很轻松地到几万倍。规则集的用法很灵活。你可以用内置的规则集也可以自己写规则文件。我遇到需要针对性审计的场景比如某个部门的口令风格有固定规律就会专门写一个精简规则集把命中率最高的变形排在前面。这里有一个必须知道的事实规则越多单条基础词的处理时间越长。全量规则跑一遍一个上百万条的字典时间成本可能是一天以上。所以我的策略是分级先用轻量规则快速过一遍再上重量规则最后才是增量。阶段策略预期时间说明第一轮单模式秒到分钟用账号信息变形第二轮精简字典 轻量规则十分钟到一小时高频口令第三轮完整字典 完整规则几小时到一天主流规律覆盖第四轮增量模式天到周兜底看投入产出这张表是我做任何一次审计前都会先拟出来的时间预算。拟不出来就别开跑因为跑到一半你会陷入“要不要停”的纠结。4.3 增量模式与加速后端增量模式需要设定字符集和长度范围。字符集越大、长度上限越高搜索空间越大。这里有一个简单但很多人算错的账搜索空间是字符集大小的长度次方。字符集扩一倍长度加一搜索空间就是几倍到十几倍的差距。所以我用增量模式的策略永远是“先窄后宽”先用数字加小写字母跑短长度再扩展到包含大写和符号长度上限一点点往上加。同时开启会话保存因为增量任务几乎不可能一次跑完。关于加速后端核心逻辑是哈希运算可以被高度并行化而 GPU 的核心数量远超 CPU。约翰的增强版支持多种加速后端配置正确的情况下能带来数量级的提升。但配置本身有门槛涉及驱动、运行库版本匹配而且只对部分哈希类型有明显收益——内存硬算法在 GPU 上优势会被削弱因为显存带宽和容量成为新瓶颈。我的建议是分两步走先把 CPU 多线程这条路走通、性能基线测出来确保流程跑得通再考虑上 GPU。顺序反了的话你会在驱动问题上耗掉大量时间而且分不清是工具问题还是配置问题。4.4 时间成本与投入产出怎么算这是整个流程里最没有标准答案但最需要判断力的部分。我一般用三个指标做决策。第一是覆盖率当前策略能覆盖候选空间的比例。第二是单位时间命中数每跑一小时能出几个结果。第三是整改成本如果这一批口令破不出来直接强制重置的成本有多大。实操中当命中曲线明显走平——比如跑了三小时只多出一个结果——就该停了。剩下的那部分口令从防御角度看反而是好消息说明它们已经足够强。这时候正确动作是拿着已经破出来的弱口令清单去推动整改而不是硬啃剩下那部分。我见过太多人把审计做成了纯粹的算力比拼跑了一周出来两个结果报告写得像军功章。但审计的目的是改进不是炫技。能在一小时内找出二十个弱口令并让它们被换掉价值远高于一周找出一个。5. 防破解让同类工具在你的系统上效率归零5.1 口令本身怎么设才有实际意义所有加固措施里口令长度是性价比最高的一项。原因很简单搜索空间的增长速度是指数级的而人脑记忆的舒适区是线性的。长度每加一位破解成本就上一个台阶而多记两位对多数人来说并不困难。我的经验阈值是普通业务账号至少 12 位管理员级账号至少 16 位。低于这个长度无论字符集多复杂在现代硬件面前都撑不了太久。第二重要的是避免可预测的结构。很多人以为把常见词加几个符号就安全了其实规则引擎专门处理这种变形。真正有效的是使用互不相关的多个词组合或者用一句只有你自己知道的话取首字母加特殊处理。这种口令的搜索空间远大于“单词加数字”。第三是唯一性。同一个口令复用在多个系统上一次泄露就是全线失守。这一点在审计中最容易暴露——我经常在同一个组织的一批账号里看到高度相似的口令模式一次规则变形就能连着命中七八个。提示判断一个口令强不强最直接的办法就是把它对应的散列值丢给 john 跑一轮。跑不出来就是及格跑出来了就换。这个方法比任何强度评分算法都实在。5.2 存储层加固算法和参数的选择同样的口令用不同的算法存抗爆破能力可以差几个数量级。这是防御端最容易被忽略、但收益最大的一环。核心原则是选择有意设计成“慢”的算法。快速散列算法比如 MD5、SHA 系列的单轮版本的设计目标是计算快这对防御方是灾难。而专门为口令设计的算法会通过迭代轮数、内存占用、并行度限制来抬高单次计算成本。具体选择上能上内存硬算法就上。它们的特性是需要大量内存才能计算这让 GPU 并行优势大幅削弱因为显存容量是硬约束。次优选择是高 cost 的 bcryptcost 每加一计算成本翻倍。这里有一个必须注意的实操细节算法升级之后老账号的散列值还在用旧算法。有两种处理方式一是在用户下次登录时用新算法重新计算并替换二是强制批量重置。前者体验好后者更彻底。我倾向于前者但对管理员账号做后者。还有一个常被忽视的点是加盐。盐值的作用是让相同口令产生不同散列直接废掉预计算表。现代算法默认都带盐但如果你在自研系统里手动实现过散列逻辑一定要确认盐是随机生成的、每个用户独立、并且长度足够。5.3 系统层把在线试错的路堵死所有前面的加固针对的都是“离线样本被拿到”的情况。还有另一条路是攻击者直接在线试密码。这条路要靠系统策略来堵。第一是速率限制和账号锁定。失败的尝试次数达到阈值后账号临时锁定或登录延迟递增。这个机制的参数要调好阈值太低会导致服务台工单暴增阈值太高等于没有。我的经验是配合递增延迟使用比硬性锁定体验好同时依然能有效压制自动化的高频尝试。第二是日志和告警。失败尝试要记录来源、账号、时间并且对同一账号的连续失败、或同一来源对多个账号的失败尝试触发告警。这个信号的准确率很高误报主要集中在用户改密码之后忘了更新凭据的场景很好排查。第三是提高认证因子的数量。口令作为单一因子本质上就是在赌用户会设一个足够长的口令。加一个非口令因子破解的意义直接下降一个维度。5.4 加密文件与压缩包的防破解这一块经常被忽略但实际风险很实在。交付给外部的加密包如果密码设得随意对方拿到包之后跑一轮字典就开了里面的内容等于明文外发。我的固定做法有三条。密码长度上加密文件的密码我用的是跟管理员账号同级别的标准因为它的使用频率低不需要考虑输入体验。密码来源上不用人脑想的词而是从随机源生成用密码管理器保存通过安全渠道单独传递。加密算法上打包时选择支持强加密的选项不要用老式的弱加密方案。这里有一个实操细节值得单独提某些打包工具的默认加密选项可能是兼容性优先的老算法。你要在设置里手动切换到强加密而且要注意有些工具在命令行模式下默认值和图形界面下的默认值不一样。我踩过这个坑——图形界面里选了强加密脚本调用时用的是默认值出来的包强度完全不同。验证方式也很直接包做完之后用提取工具把校验信息抽出来自己跑一轮短字典。跑不出来才交付。这个自检动作花五分钟能挡掉绝大部分低级失误。5.5 制度层把自查变成常态技术措施不配合制度很容易腐化。我参与过的比较有效的做法是固定的季度自查抽一批账号的散列值用统一的时间预算跑一轮把能破出来的口令列成清单推动责任人重置。同时把“口令强度”纳入交付前的检查项。自查节奏上我建议不要搞太频繁季度一次比较合适。频率太高跑出来的都是刚换的口令价值不大频率太低问题积累太多整改阻力大。还有一点自查结果本身是敏感信息。哪些账号口令弱、弱到什么程度这份清单的敏感度不亚于口令本身。存储、传递、销毁都要有明确规则用完即删是最省事的做法。6. 常见问题排查与避坑速查6.1 典型故障对照表下面这些是我这些年遇到频率最高的问题按现象分类整理。现象可能原因处理方向跑完全程零命中格式识别错误静默用了错误算法手动指定格式参数观察运行信息只有单个核心在跑编译时未启用多线程支持重新编译并打开对应开关提取工具提示找不到命令未切换到增强版的辅助程序目录进入对应目录执行或配置环境变量提取出来的散列文件为空文件格式版本过新提取工具不支持用工具自身的命令行降级导出后再提取长任务中断后无法续跑未使用会话参数下次加会话参数用恢复参数续跑结果文件里没有记录误用了重置参数或结果文件被清理保留结果文件查看只用展示参数特定编码的字典命中异常低字典文件编码与运行环境不一致统一转成 UTF-8 后重试加速后端启用后性能没变化驱动或运行库版本不匹配或算法不适合核对版本先回归 CPU 多线程基线6.2 提升效率的几个实战心得第一条心得是排序。把字典按命中概率排序而不是按字母序。这个动作不需要任何工具但效果显著。我通常把环境相关词汇、常见弱口令、年份组合放到最前面。第二条心得是分段跑。不要一次性把规则开满分成轻、中、重三轮。第一轮跑完之后看命中分布如果前一千条就命中了 80%说明这个环境的口令强度整体偏低后续轮次可以缩短时间如果跑了很久才零星命中说明剩下的是硬骨头早点停手去推整改更划算。第三条心得是先小规模验证。任何新字典、新规则集、新参数组合都先用一个包含已知答案的小样本验证。确认流程正确之后再上真实数据。这一步看起来多余但能挡住大量“跑了十小时才发现参数写错”的事故。第四条心得是记录。每次审计都把字典版本、规则集、运行时长、命中数量记下来。几次之后你就能看出这个环境的口令强度趋势也能估算下一次需要多少时间预算。经验数据比任何理论估算都准。6.3 合规前提不能含糊这是最后一条也是最重要的一条。john 这类工具的正当使用场景非常明确对自己拥有管理权限的系统做安全自查对客户委托范围内的资产做授权评估对自己创建的加密文件做强度验证。这三个场景之外任何形式的尝试都不在讨论范围内。在实操层面我给自己定的规矩是三条一是所有审计对象必须有明确的书面授权或所有权证明二是审计过程中产生的所有中间文件提取出来的散列文件、跑出来的明文清单在任务结束后彻底清除三是审计报告只呈现统计结论和整改建议不附完整明文清单需要明细的单独走加密通道交付给指定责任人。这三条不是为了应付流程而是因为我自己见过因为文件管理不当导致的二次事故。审计数据的安全等级不低于原始数据这一点怎么强调都不过分。这几年下来我最大的体会是john 的价值从来不在“破”这个动作上而在于它把“密码到底有多弱”这件事从主观判断变成了可以量化的结论。以前跟业务方说“你这个密码强度不够”对方会说“我觉得挺复杂的”现在把散列值丢进去跑二十分钟出一份命中清单对方第二天就改完了。工具的说服力就在这儿。另一个反复验证的结论是防御端投入产出比最高的永远是那几件朴素的事把口令拉长、把算法换慢、把在线试错限速、把加密文件的密码当管理员密码对待。这些做完了再花哨的破解工具在你面前都只能干瞪眼。反过来如果这几件基础的事没做指望靠某个高级防护方案兜底那就是把房子盖在沙子上。如果你准备上手做第一轮自查我的建议是从一小批测试账号开始把单模式、字典加规则、增量这三条路的完整流程各走一遍把时间基线和命中率记下来。等流程顺了再上真实规模。别一上来就跑全量那样大概率是搭进去一整天拿到一份看不懂的结果。
返回列表