我第一次意识到“抓包真的可以为所欲为”,是在一台完全由自己掌控的测试服务器上,看着刚提交的账号密码以明文出现在 Wireshark 的协议树里。那个瞬间你就会明白:为什么安全圈天天喊着必须上 HTTPS,为什么公共 WiFi 不敢随便登录网银,为什么很多公司的内网系统明明很老旧却仍能撑到今天——因为风险一直都在流量里摆着。
这篇文章不是鼓励你去偷别人的密码。恰恰相反,我需要带着你站在攻击者的视角,把 Wireshark 抓取网站登录密码整个过程的底层原理、实操步骤和防护手段拆一遍。适合三类人看:一是刚接触 Wireshark 的网络运维和测试人员,想在授权环境里验证自己系统的认证安全性;二是做 Web 开发、想搞清楚密码在传输过程中到底经历了什么的程序员;三是单纯对抓包感兴趣、想系统入门的安全爱好者。
提前说清楚:所有演示都基于本地虚拟机构建的测试环境,不针对任何真实线上系统。如果你把思路用到别人身上,后果自己承担。安全研究的第一原则永远是不伤害他人,先拿到授权再动手。
1. 为什么登录密码能被抓到:HTTP明文传输的底层逻辑
1.1 从一次表单提交开始讲起
在浏览器里填一个登录框,点“登录”,浏览器做的事远比表面看起来复杂。它会把表单里的字段按照 W3C 规范拼成一个 HTTP 请求,绝大多数时候是 POST 请求,然后把请求发往目标服务器。这个请求主要由三部分组成:请求行(方法、路径、协议版本)、请求头(Host、User-Agent、Content-Type 等)、请求体(表单数据本体)。
问题就出在请求体上。如果网站的协议是 HTTP 而不是 HTTPS,那么请求体的内容在网络上传输时是明文。打个比方,把 HTTP 请求想象成一张明信片:所有邮局工作人员、分拣员、转运司机,只要经手这张明信片,都能看到上面写的字。而 HTTPS 相当于一封密封好的挂号信,就算中间人拦下来,看到的也只是无法解读的密文。
所以我们先记住第一个关键结论:Wireshark 并不是“破解”了密码,它只是恰好出现在明信片的流通路径上,然后展开了那张明信片而已。所谓抓取密码,本质是抓取明文流量并从里面提取凭据。
1.2 登录表单的数据长什么样
拿最常见的登录场景举例,用户在前端填了用户名和密码,点提交。浏览器拼出来的请求体会长这样:
username=admin&password=123456&remember=on如果是 JSON 格式的接口,可能是:
{"username":"admin","password":"123456"}不管格式怎么变,核心问题是一致的:如果传输层不做加密,那么这些内容在网络上就是能够被直接读取的纯文本。Wireshark 捕获到以太网帧后,Wireshark 会层层解析:以太网头 -> IP 头 -> TCP 头 -> HTTP 层,最终在 HTTP 层直接能看到完整的请求体和响应内容。用户密码就这样出现在你的屏幕上,甚至连解码都不需要。
这也是为什么我总跟身边做开发的朋友说,你们测试任何系统,第一件事就是看看它是不是还跑在 HTTP 上。如果跑在 HTTP 上,那就不要讨论什么“加了密再入库”“用了什么强密码策略”——传输环节就已经裸奔了,那些都是后话。
1.3 为什么 HTTPS 能挡住 Wireshark
那 HTTPS 到底做了什么?简单说,HTTPS 在 HTTP 和 TCP 之间加了一层 TLS(Transport Layer Security)。双方在正式传数据之前先做握手,协商出一把对称加密的会话密钥。之后所有 HTTP 数据都被这把密钥加密后再扔到 TCP 层传输。
Wireshark 抓到的就不再是 https:// 或 http:// 能直接识别的 HTTP 包了,而是 TLS 协议的密文内容,看起来就是一堆无法解读的字节。你用过滤表达式http几乎看不到任何有用的请求头,只有tls相关的握手包和 Application Data。
所以如果你抓包发现流量是 TLS 加密的,却还想看到明文密码,通常只有两条路:一是配置 SSLKEYLOGFILE 让浏览器把会话密钥导出来给 Wireshark 用;二是拿到服务器的私钥。这两条路在实际攻击场景里都非常难走。这也解释了为什么现在直接抓包偷密码的成功率越来越低——因为互联网已经在全面 HTTPS 化了。但那并不意味着研究这个过程没有意义,恰恰相反,理解漏洞是怎么利用的,才能理解防护为什么必要。
2. 搭建本地测试环境:授权范围内的抓包实验室
2.1 用虚拟机搭一台简易 HTTP 登录服务器
为了安全地复现整个过程,我建议你在自己的电脑上用虚拟化工具搭一个环境,彻底脱离真实网络。你可以用任何你顺手的方案,VMware、VirtualBox、Docker 都可以。我常用的是 VirtualBox 里装一个精简版 Linux,然后在上面装 Nginx 或 Apache,配一个最简单的 PHP 登录页面。
整个过程不复杂,核心就三步:
- 创建一台虚拟机,网络模式选择“仅主机(Host-Only)”或“NAT”。这样抓到的流量不会跑到外部局域网去,避免干扰别人。
- 在虚拟机里安装 Web 服务。我用的是 Nginx + PHP-FPM,主要因为配置简单、环境干净。
- 写一个简单的登录页面,提交之后不跳转,直接把表单内容输出或记录下来,模拟真实的后端处理。
先看 PHP 端最简单的接收逻辑:
<?php if ($_SERVER["REQUEST_METHOD"] === "POST") { $username = $_POST["username"] ?? ""; $password = $_POST["password"] ?? ""; // 这里只是打日志,真实系统会去查数据库、比对哈希 file_put_contents("/tmp/login.log", "$username:$password\n", FILE_APPEND); echo "login success"; } else { ?> <form method="POST" action=""> <input type="text" name="username" placeholder="用户名"> <input type="password" name="password" placeholder="密码"> <button type="submit">登录</button> </form> <?php } ?>这是一个标记了演示用途的实验脚本,不是真实系统。数据库校验、密码哈希这些都没写,但在抓包研究中完全足够。真正的重点是:当你在浏览器里输入http://192.168.56.101/index.php(虚拟机的 IP,取决于你的网络配置),填上账号密码点按钮,这段请求会从你的物理机网卡发出去,经过 VirtualBox 的虚拟网络,进入虚拟机。而 Wireshark 如果正好在你的物理机网卡或虚拟网卡上抓包,就能完整看到这个过程。
如果你不想用虚拟机,也可以直接开一个本地 PHP 内置服务器:
php -S 0.0.0.0:8080 -t /path/to/webroot然后在同一台电脑上用浏览器访问http://127.0.0.1:8080,Wireshark 抓 lo(回环)接口,同样能看到明文请求。对抓包入门来说这是最快的方式。回环接口抓包有一个和物理网卡不一样的细节,等下在“常见问题”里我会专门说。
2.2 Wireshark 的安装与抓包前的配置
Wireshark 本身是免费开源的,Windows、macOS、Linux 都有对应版本。安装过程不多说,重点讲抓包前必须检查的三个配置项。
第一,确认 Npcap 或 WinPcap 是否装好。Windows 下 Wireshark 必须要靠 Npcap 才能抓到数据包。安装过程中会问你是否允许抓包时进入混杂模式,一般选上就行。如果你用的是 Linux,抓到 lo 接口和物理网卡通常都需要 root 权限或者给普通用户授权,最省事的方式是运行sudo wireshark或者把用户加入 wireshark 用户组。
第二,抓包前要选对网络接口。Wireshark 主页面上会列出所有可用的网卡接口,每个接口后面会实时跳动包数量。搞不清选哪一个的话,可以先观察哪个接口的流量最多、和你操作的网段对应。比如我用 VirtualBox 仅主机模式,虚拟机的 IP 是 192.168.56.101,那我应该选虚拟网卡 VirtualBox Host-Only Ethernet Adapter,而不是我的物理 WiFi 网卡。
第三,设置好捕获过滤器。捕获过滤器的语法和显示过滤器不一样,它是真正在采集阶段就做过滤,只把满足条件的数据包留下来,能大幅减小抓包文件体积。抓登录密码时最常用的捕获过滤器是:
tcp port 80意思是只抓 TCP 端口 80 上的数据包,HTTP 流量基本都走这个端口。如果你的测试环境端口是 8080,那就是tcp port 8080。你甚至可以加上主机过滤来进一步缩小范围:
host 192.168.56.101 and tcp port 80这样抓下来的包非常干净,基本只包含浏览器和测试服务器之间的握手、请求和响应。
注意:捕获过滤器不是
http。如果你在捕获过滤器里写http,老的 Wireshark 版本会提示错误或者默默接受但抓不到东西。捕获过滤器走的是 BPF(Berkeley Packet Filter)语法,只能针对 IP、端口、协议号这些底层字段做判断。等到抓完包,再在显示过滤器里写http才不迟。
准备到这个程度,你就可以放心地开始抓包了。
3. 完整实操:从抓包到密码出现的全流程
3.1 抓包并触发一次登录请求
我现在把实际操作完整走一遍。
先打开 Wireshark,选择刚才确认好的虚拟网卡,点开始抓包。然后回到浏览器,访问http://192.168.56.101/index.php。页面出来后,随便填一个测试账号进去,我这次填的是testuser和abc123456,点击登录。等页面返回“login success”之后,回到 Wireshark 点停止抓包的红方块。
这时候你会看到很多数据包。如果之前没有设置捕获过滤器,列表会非常长,包含一堆 ARP、浏览器自动发起的其他请求、系统后台流量等。不用慌,直接在显示过滤器里输入:
http.request.method=="POST"回车。Wireshark 会立刻过滤出所有 POST 请求的报文,数量通常很少,甚至只有一个。我这次的结果是看到一个 POST /index.php 的请求,源地址是我的物理机 IP,目标地址是 192.168.56.101,长度大约 300 多字节。很好,这就是我们要找的包。
3.2 使用“追踪流”直接看完整请求
单选这个 POST 包,右键,选择“追踪流(Follow)”——菜单里叫“追踪 TCP 流”或者“Follow TCP Stream”,不同语言版本叫法略有区别。点了之后会弹出一个新窗口,里面把整个 TCP 连接中客户端发给服务器、服务器返回给客户端的所有原始数据拼在一起,按照发送顺序展示出来。
在这个窗口里,你能直接看到 HTTP 请求的完整面貌。跟我上面讲的理论完全一致:
POST /index.php HTTP/1.1 Host: 192.168.56.101 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Accept: text/html,application/xhtml+xml,... Content-Type: application/x-www-form-urlencoded Content-Length: 36 username=testuser&password=abc123456用户名和密码就在请求体的最后一行,干干净净,完全不需要任何解码。Wireshark 做的事情,本质上就是把这些你“看不见”的流量转换成你可以阅读的文本。
如果你不想用图形界面右键,也可以在过滤栏输入:
tcp.stream eq 0把数字 0 替换成具体的 TCP 流号,同样能定位到指定连接。然后右键任意一个包 -> 追踪流 -> TCP 流,看到的内容是一样的。
这一步就是整个抓取密码流程的“高潮”。没有什么神秘的暴力破解,没有花哨的漏洞利用,只是把明文 HTTP 流量翻开给你看。真正的安全漏洞,往往就藏在最朴素的协议设计里。
3.3 几种常见登录方式的抓包特征对比
我实际测试过好几个不同形态的登录接口,它们的抓包特征各不相同,但都有一个共同点:只要跑在 HTTP 上,密码就藏不住。整理成一张表给各位参考:
| 登录方式 | 请求特征 | 密码出现的位置 | 风险等级 |
|---|---|---|---|
| HTML 表单 POST | Content-Type: application/x-www-form-urlencoded | 请求体末尾,键值对拼接 | 极高,明文 |
| AJAX JSON POST | Content-Type: application/json | 请求体 JSON 字段中 | 极高,明文 |
| HTTP Basic 认证 | 请求头带Authorization字段 | 值是用户名加冒号加密码的 Base64 编码 | 极高,Base64 可瞬间解码 |
| HTTPS 登录 | 请求包为 TLS 密文 | 取决于是不是能解密 TLS | 低,默认安全 |
HTTP Basic 认证这里多说一句。有些老旧系统用的是弹窗式账号密码,浏览器会在请求头里自动加一个Authorization字段。它的格式是Basic base64(username:password)。Base64 不是加密,只是一种编码方式,任何人拿到这串字符,用 Python、命令行甚至在线工具都能秒解出原始用户名和密码。
在 Linux 命令行里直接解:
echo -n "dGVzdHVzZXI6YWJjMTIzNDU2" | base64 -d输出:
testuser:abc123456明白了吗?如果服务端用 HTTP Basic 认证,风险比表单 POST 还高,因为密码每次请求都会跟着走,而且被编码成 Base64 的字符串。千万别把 Base64 当加密。
3.4 不同层面提取信息的技巧
除了追踪流这种“无脑看全文”的方式,实际工作中经常还需要更精准地提取字段。尤其面对生产环境的抓包,流量里夹杂的东西多,不可能每一条都右键看流文件。这时候就要用到 Wireshark 的显示过滤器能支持的 HTTP 字段提取了。
比如,只想看所有 POST 请求的 URI,过滤栏写:
http.request.method=="POST"然后在 Wireshark 的“分组详情”面板展开Hypertext Transfer Protocol层,能看到 Method、URI、Host、Content-Type 等所有字段。想复制某个字段的值,直接右键选择“复制”就可以。这种方式适合手工分析少量报文,效率高、不干扰原始数据。
如果后续还要做批量分析,可以把抓包结果导出为 JSON 或 CSV 文件,然后用脚本去解析。Wireshark 菜单里有“文件 -> 导出分组解析结果”,格式选 JSON,会用 tshark 把每个包的详细信息导出来,包括 HTTP 层。
下面这个命令可以只导出所有 HTTP 请求头里的 User-Agent 和 URI:
tshark -r login.pcapng -Y "http.request" -T fields -e http.host -e http.request.uri -e http.user_agent这是我日常用得很频繁的命令,处理几百兆的抓包文件,也比在图形界面里翻快得多。如果你还没接触过 tshark,建议尽早用起来,它是 Wireshark 的命令行版本,批量处理场景发挥的作用巨大。用好了基本就能把“抓包分析”这件事从点鼠标升级成写脚本。
4. 现代 Web 应用的防护手段与残留风险
4.1 全面 HTTPS 化:最基础也最关键的防线
经过前面几节的演示,你应该已经理解为什么说 HTTP 是明文传输。反过来,HTTPS 能解决传输窃听的问题,核心就是把所有 HTTP 数据装进 TLS 加密隧道里再发出去。
现代互联网的 HTTPS 普及率已经非常高。主流浏览器对 HTTP 站点会直接标记“不安全”,很多第三方 cookie、地理位置、麦克风等敏感权限也默认不给 HTTP 站点用。Google、百度这些搜索引擎给 HTTPS 站点的权重更高,这也在倒逼网站主完成升级。
但这里要提醒一句:HTTPS 不直接等于安全。TLS 加密只保护传输环节,如果用户被引导到一个仿冒域名上,即使用的是 HTTPS,数据照样会送到攻击者手里。HTTPS 解决的是“中间人偷听”的问题,不解决“你把密码交给了谁”的问题。所以完整防线至少包括“HTTPS 传输 + 服务端证书可信 + 用户自身的域名辨别意识”三层。
4.2 服务端密码存储:哈希加盐只是及格线
即使传输环节已经加密了,如果服务端把用户密码明文存在数据库里,一旦数据库泄露,所有密码照样大白天下。业界现在的基本做法是使用加盐哈希存储。
简单解释一下:用户设置密码后,系统生成一个随机字符串(盐),把盐和密码拼在一起做哈希运算,得到的结果存在数据库里。登录时再把用户输入的密码,和数据库里存的那个盐拼在一起,做同样的哈希,比对结果是否一致。这样即使数据库泄露,攻击者拿到的也只是一串哈希值,难以反推出明文密码。
哈希算法选型上,强烈不建议用 MD5 或 SHA-1,它们已经被验证太容易碰撞和暴力破解。现在更推荐的是 bcrypt、scrypt、Argon2 这类专门为密码设计的慢哈希算法。它们的共同特点是计算速度刻意做得很慢,导致攻击者暴力破解的成本大幅上升。比如 bcrypt 默认的 cost factor 调为 10 或 12 时,单次哈希计算需要几十到几百毫秒,但对正常登录体验几乎无感,却能显著提高攻击者批量爆破的代价。
4.3 仍然存在风险的典型场景
即便 HTTPS 已经满天飞,我还是在工作里见到不少能直接抓包看到登录密码的场景,这里列出来,不是为了教谁去测,反而希望这些系统的负责人快点止损。
第一类是老旧的内网应用。很多企业内部的 OA、财务、HR、监控平台,还是十几年前部署的架构,跑在 HTTP 上,甚至登录还是 HTTP Basic 认证。在内网环境下部署方觉得不会有人抓包,但恰恰内网攻击者一旦进入内网,最常见的第一步就是被动抓包,收集各种管理系统的账号密码。
第二类是公共 WiFi 环境下的明文应用。酒店、机场、咖啡厅的 WiFi 本质上就是一个广播网络,如果有网站没有做 HSTS 强制 HTTPS,用户很容易被中间人攻击降级到 HTTP 后抓到密码。
第三类是 IoT 设备的管理后台。不少路由器、摄像头、智能家居网关的 Web 管理页面仍然是 HTTP 或弱加密协议,这几乎等于在门口挂了一把形同虚设的锁。
判断一个系统是否安全,除了看它用没用 HTTPS,还要看它有没有启用 HSTS 强制浏览器必须走 HTTPS、是不是支持 TLS 1.3、证书有没有合法且不过期。这些细节才是真正决定攻击者要不要浪费时间尝试的“第一道门槛”。
5. 常见问题与排查技巧实录
5.1 抓不到 HTTP 请求怎么办
遇到抓不到包的情况,先从下面几个方向排查。最大的坑是选错了接口。以前我用 Wireless 网卡抓包,怎么抓都看不到本地访问虚拟机的流量,后来才发现流量根本没走物理网卡,而是走了虚拟网桥。把接口换成虚拟网卡之后,包立刻出来了。
还有可能是抓包过滤设置得太死。比如捕获过滤写了host 192.168.56.101,但虚拟机 IP 后来变了,那啥也抓不到。建议先清空捕获过滤器,只留tcp port 80试一次。至于权限问题,Linux 下普通用户访问原始套接口默认受限,跑sudo wireshark或者把用户加进 wireshark 组,都能解决大部分抓不到物理接口流量的情况。
如果是抓回环接口(localhost)的请求,注意 Windows 上 Wireshark 传统方式可能看不到回环流量,因为 WinPcap/Npcap 默认不抓 lo。建议直接用浏览器访问虚拟机的 HTTP 服务而不是127.0.0.1,或者抓完再想办法。最稳妥的还是搞一台真正的虚拟机或实机来测。
另外注意浏览器可能会走 HTTP/2,在 Wireshark 里看到的协议是HTTP2而不是HTTP。HTTP/2 同样不提供加密,但它的封装方式不同,显示过滤器要写成http2。如果目标服务端配置了 HTTP/2 over cleartext(h2c),Wireshark 默认也可能识别不出来,需要在 Preferences -> Protocols -> HTTP 里启用相关选项。
5.2 追踪流里看不到明文密码是为什么
最常见的原因是:这个网站用的是 HTTPS,Wireshark 显示过滤器里写http时根本看不到请求包,只看到tls。你点开追踪流,看到的全是密文,自然没有密码。
这种情况下,如果在授权测试环境里、确有必要分析自己系统的 HTTPS 流量,可以通过浏览器导出会话密钥的方式解密。具体操作是:先把浏览器的 SSLKEYLOGFILE 环境变量指到一个文件,比如 Linux 下:
export SSLKEYLOGFILE=/tmp/ssl_keys.log google-chrome --user-data-dir=/tmp/chrome-profile https://192.168.56.101然后在 Wireshark 的 Preferences -> Protocols -> TLS 里,把(Pre)-Master-Secret log filename指向这个文件。重新抓包后,Wireshark 就能解密 TLS 流量,你就能在http2或http过滤下看到明文内容了。
但再强调一次,这个方法只适用于自己拥有密钥或浏览器环境的情况。真实攻击场景里,拿到服务器私钥或浏览器密钥的难度远高于直接抓包,这也就是为什么说 HTTPS 是真的有效。
5.3 在授权测试中最容易踩的几个坑
第一,忘了确认授权的范围。安全测试不是说“我拿到了内网权限就能随便抓”。授权书里通常明确写了哪些 IP、哪些应用、哪些时间段可以测。别仗着自己是运维就去抓同事的密码,这类操作在法律和职业道德上都站不住脚。
第二,抓包文件保存得不规范。抓包文件可能包含敏感信息,比如密码明文、Token、身份证号等。我在测试完以后都会立即对 pcapng 文件做脱敏处理再存档。最简单的做法是只保留自己需要的字段重新导出一份,原始大文件直接加密压缩。别把客户环境的抓包文件随手传到网盘或者群里,出了事很难解释清楚。
第三,忽略了对时间段的控制。长时间抓包会把磁盘撑爆,你如果不设置自动停止条件,过一个小时可能抓出几个 GB 的文件,分析起来也痛苦。Wireshark 的抓包选项里有两个非常实用的设置,一是设置“文件大小自动切割”,比如每 10 MB 切成一个新文件;二是使用“自动停止条件”,比如达到 100 MB 就自动停止。这样既能保证完整记录关键流量,又不会把磁盘塞满。
6. 如何从这次实验里真正学到东西
把整个过程跑通之后,你手里应该有了一份能看清“明文密码如何泄漏”的抓包记录。这个知识不是说让你从此就能去偷谁的账号,而是让你建立一种敏感:每当你面对一个 Web 登录界面,脑子里能自动推演一遍“如果现在抓包,我能看到什么?”——这才是网络安全从业者最需要的基本功。
我自己在带新人的时候经常讲一个道理:攻击者能利用的所有路径,本质上都是防御者没想清楚的地方。Wireshark 抓密码这个实验,技术含量其实不高,但它能让人瞬间理解为什么 HTTPS 是刚需、为什么密码不能明文存、为什么公网 WiFi 有风险。这些认知如果在教科书上读十遍,都不如亲手抓包看一次来得通透。
最后分享一个小技巧:你可以在抓包之后,把那个 POST 请求的请求头里的 User-Agent、Cookie、Content-Type 全部逐行看一遍。你会发现在一次登录请求里,泄露出去的信息远不止用户名和密码。浏览器型号、操作系统版本、过去浏览的站点留下的 Cookie、本机时区、语言偏好……全都整整齐齐摆在请求头里。网络世界的透明程度,远比大多数人感知到的更彻底。理解了这一点,你对待账号安全、密码设置和网络环境的选择,自然就会不一样。