1. 先说结论:3DES漏洞修起来不难,但别急着动手
最近内网做安全基线核查,RTSP视频传输平台EasyNVR被某漏洞扫描器标记为高危,报告里写着“SSL/TLS 3DES Encryption Supported”。刚开始我以为是误报,毕竟这个平台在线上稳定跑了两年多,怎么突然冒出个密码学漏洞。后来仔细看了扫描详情才发现,平台Web管理端口的TLS握手过程中确实协商出了3DES加密套件,也就是TLS_RSA_WITH_3DES_EDE_CBC_SHA。
这里先给不熟悉的人说下背景:3DES是上世纪DES算法的改进版,用三把56位密钥做三次加密,密钥长度看着有168位,实际有效强度只有112位左右。2016年有个SWEET32攻击研究,指出3DES在长时间加密会话中可以通过生日攻击方式逐步破解出明文。虽然实际利用条件比较苛刻,需要攻击者能观察到大量加密数据,但安全扫描和等保测评里早就不允许服务器再支持3DES了。这件事本质上不是你“用了”3DES,而是你的TLS服务在握手时“允许”客户端选择3DES,所以修复目标就是让它彻底协商不到。
这个漏洞会影响到视频平台的核心使用吗?说实话,日常拉流、回放、云台控制基本感觉不到。但如果你的平台管理端口暴露在办公网甚至公网,攻击者抓包之后理论上存在数据被破解的隐患,长期来看是对整个视频系统会话信息安全的一个威胁。所以修复有必要,但更关键的是要搞清楚平台底层到底是什么组件在提供Web服务,再动手改配置。我见过不少同事上来就搜“禁用3DES”,然后改了nginx配置发现根本不生效,就是因为平台压根没用nginx,白折腾一场。
这篇文章我会把这次完整的修复过程、踩到的坑、还有验证手段都写出来,包括如何判断平台Web服务组件、不同组件下怎么改、改完怎么验证扫描结果、以及修复后对视频业务的影响测试。不管你是等保整改,还是被扫描报告催着交差,按这个思路走基本都能一次性搞定。
2. 修复前必须做的三件事:摸组件、找端口、留后路
2.1 先判断Web服务到底是nginx、Tomcat还是自研应用
EasyNVR这类视频接入平台,一般会有自己的Web管理界面,但底层HTTP服务可能是nginx反代,可能是内嵌的Tomcat/Jetty,也可能是Go或者Java写的小型HTTP服务。不同组件修改TLS配置的位置完全不同,所以第一步是识别。
最直接的办法是用浏览器打开平台的HTTPS页面,按F12看响应头里的Server字段。如果是nginx,通常会看到“Server: nginx/1.18.0”之类;如果是Tomcat,会看到“Server: Apache-Coyote/1.1”;如果是自研服务,可能没有Server头,或者显示一个自定义的名字。这个信息是判断的基础。
如果HTTPS页面没有暴露Server头,也可以用系统管理员权限登录平台所在服务器,查看监听端口的进程。Linux下执行:
netstat -tlnp | grep 443或者用ss命令:
ss -tlnp | grep LISTEN找到占用443/8443端口的进程名和PID,再通过ps -ef | grep PID看完整启动路径,基本就能判断是哪类服务了。注意needs root权限,还有生产环境上执行命令要提前确认好操作窗口,别在业务高峰期瞎折腾。
2.2 扫描器报的端口不一定是所有TLS端口
还有一点容易踩坑:扫描器可能只扫了某个特定的HTTPS端口,比如EasyNVR默认的管理端口是8080(HTTP),如果开了HTTPS通常是443或者自定义的8443。但有的人会把RTSP over TLS也暴露出来,扫描器如果做了全端口扫描,可能还会标记554端口的TLS问题。
这里就要区分开:视频流走的是RTSP协议,端口是554,一般不会被日常Web漏洞扫描器当成HTTP服务去检测TLS套件。但如果你用全端口TCP扫描加TLS检测,554上如果启用了RTSPS,同样会检查3DES。所以修复时不要只盯着Web管理端口,建议把服务器上所有监听TCP的端口都列出来,识别哪些端口走的是TLS,然后逐个检查。
我当时就是把平台的IP全端口扫了一遍,发现只有8443端口存在3DES,其他端口要么是纯RTSP,要么是HTTP明文,不涉及TLS加密套件。这样范围就清晰了。
2.3 备份配置和快照永远是第一步
无论改的是nginx、Tomcat还是其他服务,动手前一定要备份原配置文件,并记录当前版本号和运行状态。我习惯先执行:
cp nginx.conf nginx.conf.bak-$(date +%Y%m%d)同时拍一张虚拟机快照,或者至少导出一份当前配置目录的tar包。这样做不是为了形式,而是因为TLS配置一旦改错,最容易出现的后果是HTTPS端口直接起不来,所有平台用户突然无法访问管理界面。有备份在手,随时可以秒级回滚。
另外建议在低峰期操作,并且准备好测试账号,改完后立即验证登录功能和视频拉流,尤其是对接了大量IPC摄像头的生产环境,千万别在下班前改,出了问题没人帮你填坑。
3. 不同组件的3DES禁用实操方案
3.1 如果用的是nginx反向代理,这样改ssl_ciphers
很多视频平台为了统一入口,会把Web管理端放在nginx后面,甚至在nginx层终结TLS。这种情况下,扫描器检测到的就是nginx配置的加密套件。打开nginx的主配置文件,找到监听HTTPS端口的server块,通常里面有这样一段:
server { listen 8443 ssl; server_name example.local; ssl_certificate /opt/ssl/server.crt; ssl_certificate_key /opt/ssl/server.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; }问题就出在ssl_ciphers HIGH:!aNULL:!MD5这行。HIGH这个关键字会把所有被认为是高强度的套件都包含进去,而OpenSSL历史版本中3DES虽然强度不高,但可能仍被包含在HIGH里。所以我建议直接显式地列出现代安全的加密套件集合,彻底排除DES系列。
比较稳妥的配置如下:
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on;如果nginx版本较新(1.20以上),还支持TLSv1.3的套件,但TLSv1.3的套件名是固定的,不需要在ssl_ciphers里写,ssl_protocols TLSv1.3开启后会自动使用TLS_AES_128_GCM_SHA256等套件。上面的配置里没有3DES、没有RC4、没有CBC模式的套件,安全性足够。
改完后先测试配置:
nginx -t如果提示配置正确,再平滑重载:
nginx -s reload这里要说明一下为什么选择GCM而不是CBC。3DES漏洞的根因就是CBC模式配合较短分组大小带来的碰撞风险,而AES-GCM是AEAD加密方式,能同时保证机密性和完整性,扫描器对这类套件默认就是放行的。我测试过,用上面的配置重载后,再用扫描器复查,3DES套件直接消失,其他弱套件也没了。
3.2 如果是Tomcat或Jetty内嵌服务,改server.xml
有些视频平台没有额外部署nginx,所有请求直接由Java应用的内嵌Web容器处理。这种情况扫描器看到的是JSSE的TLS配置。以Tomcat为例,它的SSL连接器配置在conf/server.xml中,大概长这样:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" scheme="https" secure="true" SSLEnabled="true" keystoreFile="/opt/tomcat/conf/keystore.jks" keystorePass="changeit" clientAuth="false" sslProtocol="TLS"/>默认情况下,Tomcat会使用Java运行时支持的加密套件,其中就包括3DES套件。要禁用它们,需要在Connector上显式指定ciphers属性:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="/opt/tomcat/conf/keystore.jks" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"/>注意,Tomcat 8.5/9.0之后推荐使用sslEnabledProtocols控制协议版本,同时建议加上sslProtocol="TLS"。ciphers属性里写的是JSSE的套件名称,不是OpenSSL的名称,千万别把nginx里的长短横线格式粘贴进来。
改完重启Tomcat:
/opt/tomcat/bin/shutdown.sh /opt/tomcat/bin/startup.sh重启后检查catalina.out有没有报错,如果某条套件名写错,Tomcat会直接启动失败,日志里会提示找不到指定的密码套件。
Jetty的情况类似,在jetty-ssl.xml或者sslContextFactory里配置setExcludeCipherSuites(".*3DES.*")就比Tomcat更简单。如果你手头是Spring Boot项目内嵌Tomcat,也可以通过配置类去掉3DES,但一般EasyNVR这类已编译好的平台没有直接改代码的入口,优先改XML配置。
3.3 如果是Go或C++自研的Web服务,需要从代码层面禁用
有一类视频平台的服务端是Go写的,Web管理界面直接由Go的net/http提供TLS服务。Go 1.17之后默认的CipherSuites里已经不包含3DES,但如果代码里手动自定义了tls.Config.CipherSuites,并且把3DES套件加进去了,扫描器就会报。
这种场景下,唯一的正规方式是修改代码,重新编译。定位到初始化tls.Config的地方,把CipherSuites字段里的TLS_RSA_WITH_3DES_EDE_CBC_SHA这条删掉。还要注意不要把TLS_RSA_WITH_RC4_128_SHA之类的老套件留进去。
如果没有源码,只能通过系统层面的TLS策略来约束。比如在Linux上使用openssl 1.1.1以上的版本,可以通过配置文件/etc/ssl/openssl.cnf的CipherString设置全局值,但前提是目标服务调用了系统OpenSSL库而不是自带BoringSSL。实际操作中我发现很多Go服务并不受这个文件影响,这是个坑。
所以这类平台最好还是联系厂商要一个更新版本,或者看平台是否提供配置文件来设置加密套件。如果都没办法,临时方案是在前面再套一层nginx做TLS终结,把自研服务的TLS关掉,让nginx来接管加密,然后修改nginx的密码套件。这样虽然多了一层转发,但安全扫描就能过关,视频流管理功能也不受影响。
4. 修复后的验证方法:命令行、扫描器、业务回归一个都不能少
4.1 用OpenSSL快速验证3DES是否被禁用
修改完配置,别急着提交给安全组复查,先自己在命令行验证一下。最容易用的就是openssl s_client连接目标端口,指定密码套件为3DES,看看能不能协商成功。
验证3DES是否被禁用:
openssl s_client -connect 127.0.0.1:8443 -cipher '3DES' 2>&1 | grep -E "Cipher|error"如果配置生效,你会看到类似no cipher match或sslv3 alert handshake failure的结果,说明服务器不再接受3DES。如果看到Cipher : ECDHE-RSA-AES128-GCM-SHA256之类的结果,说明服务器还是协商成功了,很可能是TLS库的CipherString没配置对,或者改的配置没加载。
再验证AES-GCM是否正常工作:
openssl s_client -connect 127.0.0.1:8443 -cipher 'ECDHE-RSA-AES128-GCM-SHA256' 2>&1 | grep "Cipher :"正常情况下应该能协商成功。这个方法比直接跑扫描器快得多,适合快速迭代。
还要注意一个问题:有些服务如果同时监听IPv6地址,你用127.0.0.1测不出来,可以改用[::1]或者服务器的实际IP。我碰到过一台服务器同时监听IPv4和IPv6,只改了IPv4的配置文件忘了IPv6,最后扫描还是报了3DES。
4.2 用漏洞扫描器复查时,注意策略和端口配置
复查时不要直接拿默认策略扫,最好进一步确认扫描任务的SSL/TLS策略里包含“3DES cipher suites”检测项。有些扫描器默认只检测SSLv3或者TLS1.0,即使你3DES没封住,它也可能不报。所以复查报告显示通过后,建议再用openssl手动验证一遍,以免扫描器漏检。
还有一点,扫描器可能扫描的是域名解析到的所有IP,如果你配置了负载均衡或者双网卡,扫描请求不一定落在你改了的那台服务器上。我当时就是改了主节点的nginx,扫描器却扫到了备节点的IP,导致报告一直报漏洞。后来把两台服务器的配置都统一改了,才彻底清干净。
4.3 视频业务回归:不只是能打开网页就行
修复完成后,一定要测试视频平台的核心链路。不能只盯着HTTPS页面能打开,还要验证:
- 用平台管理账号登录、退出是否正常;
- 摄像头通道列表能否正常加载;
- 实时预览是否流畅,能否正常回放;
- 如果有云台控制,试试PTZ操作;
- 如果有H5播放或者微信播放,用Chrome和Edge各打开一遍。
之所以强调这个,是因为我见过一个案例:有同事把TLS协议直接改成了“仅TLSv1.3”,导致一部分旧版浏览器连不上,平台管理页面白屏,但用户反馈说是“视频看不了”。实际上视频流走的是RTSP,没受影响,但管理页面打不开也会被当成事故。所以协议版本不要一下提到TLSv1.3,保持TLSv1.2及以上就足够,兼容性最好。
我自己的回归清单通常是下面这样的:
| 功能模块 | 测试内容 | 预期结果 |
|---|---|---|
| Web登录 | 用户名密码认证、验证码刷新 | 正常跳转,无明显延迟 |
| 通道列表 | 加载所有接入的IPC设备 | 设备全部在线显示 |
| 实时预览 | 直播画面播放、拖动无花屏 | 画面流畅,声音同步 |
| 录像回放 | 选择时间段回放 | 进度条可拖动,录像可播放 |
| 云台控制 | 上下左右转动、变倍 | 指令响应正常 |
| HTTPS证书 | 浏览器访问无警告 | 证书链完整,日期有效 |
这一套走下来,我才会把修复结果反馈给安全组。
5. 常见问题与排查技巧实录
5.1 改了nginx配置,扫描器还是报3DES
这个情况我遇到好几次,排查思路是确认你扫描的目标端口是不是真的由nginx提供服务。用ss -tlnp看端口对应的进程,如果发现8443端口是tomcat在监听,改了nginx当然没用。还有一种可能是后端Tomcat也被直接暴露了,或者负载均衡器上有独立的SSL卸载配置,需要把链路中所有TLS节点都检查一遍。
5.2 配置文件语法正确但nginx重载失败
如果nginx -t提示[emerg]错误,最常见的原因是ssl_ciphers里写了nginx不认识的名字。比如把OpenSSL的ECDHE-ECDSA-AES128-GCM-SHA256错写成了ECDHE-ECDSA-AES128-GCM,少了一截,nginx就会报错。解决方法是先用命令查看当前OpenSSL支持的套件名:
openssl ciphers -v | grep GCM然后把列出来的标准名抄进去。
5.3 修改后旧设备无法推流或拉流
如果用户反馈部分老摄像头或老播放器不能正常连接RTSPS,先确认这些设备是否强制要求3DES。说实话,市面上绝大多数摄像头默认使用的是AES加密或者不加密的RTSP,很少有必须3DES才能工作的。如果真遇到,那就要走升级设备固件的路线,而不是在服务器上放一个弱加密套件来迁就它。安全漏洞整改的底线不能因为兼容旧设备而放弃。
5.4 扫描报告里除了3DES还报了RC4和TLSv1.0
既然改了TLS配置,就顺带看看扫描报告里是否还有其他弱项。常见的还包括RC4加密套件、TLSv1.0协议、TLSv1.1协议。处理方式类似:在ssl_ciphers里去掉了RC4相关套件,在ssl_protocols里只保留TLSv1.2及以上。注意,有些视频监控大屏的老设备还在用TLSv1.0,这种情况下要提前和业务方确认,最好推动设备更新,而不是继续开放有风险的协议。
5.5 平台自带反向代理和内置服务同时开启
某些版本EasyNVR允许用户在后台选择“使用自带Web服务”还是“使用外部nginx代理”,如果平台同时支持两种模式,并且两个服务都监听了TLS端口,漏扫就会显示两条记录。修复时要两个都处理,否则只改一个,另一条漏洞记录仍然存在。
6. 实际操作中的几点体会
这套3DES修复流程做完,让我对视频平台的TLS配置有了更深的认识。以前总觉得安全扫描报告就交给运维改改配置文件就行,但真正动手才会发现,很多视频平台的部署方式非常灵活,单一某篇文章里的命令不一定适用你手头的环境。
我的建议是,拿到扫描报告后,第一件事不是搜“如何禁用3DES”,而是花十分钟搞清楚平台架构:Web服务是什么、TLS在哪一层终结、还有哪些端口暴露了TLS。架构搞清楚了,改动就变得很简单。
另外,如果你们单位有多个环境,建议写一个配置脚本或者Ansible角色,统一管理所有服务器的TLS配置。这样以后再做安全基线复查,只需要执行一次脚本就能批量保持一致,省心很多。
最后提一点:安全升级不是一次性的,操作系统升级、OpenSSL版本升级、平台版本迭代都可能重置配置。每次升级之后都要重新跑一遍全端口TLS扫描,不要等到季度考核了再发现漏洞又回来了。
这个项目做完之后,我顺手把平台的TLS配置导出了一份基线文档,里面记录了每个端口对应的服务、证书路径、支持的协议和套件列表。后续再有同事接手,照着文档就能快速定位问题,不用再从头摸一遍。安全整改这件事,修好一个端口不算完,把排查的方法沉淀下来才是长期收益。