4、SIP注册劫持:注册流程分析、伪造REGISTER请求、会话劫持、防御策略
4.1 先聊聊SIP注册到底是怎么回事
说实话,SIP注册劫持是我在IMS安全评估中遇到最多的问题之一。很多团队把精力都放在信令加密上,却忽略了注册流程本身的设计缺陷。
SIP注册,说白了就是用户告诉网络:「嘿,我在这里,这是我的联系地址」。UAC(用户代理客户端)发送REGISTER请求,Registrar服务器把AOR(地址-of-记录)和Contact地址绑定起来。嗯,这里要注意——这个绑定是有时效的,通常用Expires头域控制。
我见过不少开发人员以为注册成功就万事大吉了。其实不然。注册流程中最脆弱的地方,恰恰是身份验证环节。如果验证不严,攻击者就能伪造REGISTER请求,把自己的设备注册成你的号码。
核心问题: 注册服务器如何确认「你就是你声称的那个人」?如果这个信任链断了,整个通信安全就崩塌了。
4.2 注册流程深度拆解
一个标准的SIP注册流程,我习惯把它分成三个阶段:
- 发现阶段: UAC通过DHCP、DNS SRV或手动配置找到Registrar地址
- 认证阶段: 服务器返回401/407质询,要求客户端提供凭证
- 注册阶段: 客户端携带认证信息重新发送REGISTER
我在项目中遇到过一种情况:某个厂商为了「优化用户体验」,跳过了401质询,直接接受第一次REGISTER请求。你想想看,这等于把大门敞开了。攻击者只需要知道你的SIP URI,就能轻松完成注册劫持。
正常的REGISTER请求长这样:
REGISTER sip:ims.example.com SIP/2.0
Via: SIP/2.0/UDP 192.168.1.100:5060
From: <sip:alice@example.com>;tag=abc123
To: <sip:alice@example.com>
Call-ID: 123456@192.168.1.100
CSeq: 1 REGISTER
Contact: <sip:alice@192.168.1.100:5060>;expires=3600
Authorization: Digest username="alice", realm="ims.example.com",
nonce="xyz789", uri="sip:ims.example.com",
response="a1b2c3d4"
Content-Length: 0
注意那个Authorization头域。如果它缺失或者可以被绕过,劫持就开始了。
4.3 伪造REGISTER请求——攻击者是怎么干的
伪造REGISTER请求,说白了就是攻击者冒充合法用户向Registrar发送注册消息。我把它分为三种常见手法:
| 攻击手法 | 原理 | 我见过的真实案例 |
|---|---|---|
| 无认证注册 | 服务器配置不当,允许未认证的REGISTER | 某运营商测试环境直接暴露在公网,任何人都能注册任意号码 |
| 重放攻击 | 捕获合法REGISTER请求,修改Contact地址后重放 | 攻击者用Wireshark抓包,改了IP地址就完成了劫持 |
| 密码破解 | 暴力破解或字典攻击获取共享密钥 | 弱密码「123456」导致整个企业分机被劫持 |
伪造请求的代码示例(仅用于教学目的):
# 简化版伪造REGISTER请求
import socket
def forge_register(target_ip, target_port, victim_uri, attacker_contact):
request = f"""REGISTER sip:{target_ip} SIP/2.0\r
Via: SIP/2.0/UDP {attacker_contact.split('@')[1].split(':')[0]}:5060\r
From: <sip:{victim_uri}>;tag=forged123\r
To: <sip:{victim_uri}>\r
Call-ID: forged@{attacker_contact.split('@')[1]}\r
CSeq: 1 REGISTER\r
Contact: <sip:{attacker_contact}>;expires=3600\r
Content-Length: 0\r
\r"""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(request.encode(), (target_ip, target_port))
sock.close()
# 攻击者把alice的注册地址改成自己的
forge_register("192.168.1.1", 5060, "alice@example.com", "attacker@10.0.0.5:5060")
⚠️ 警告: 这段代码仅供理解攻击原理。未经授权使用可能违反法律法规。我在做红队演练时才会用到类似技术。
4.4 会话劫持——注册劫持的最终目的
注册劫持不是终点,而是起点。攻击者完成注册劫持后,能做什么?
- 来电拦截: 所有打给alice的电话,都路由到攻击者的设备上
- 去电冒充: 攻击者以alice的身份发起呼叫,被叫方看到的是alice的号码
- 语音/视频窃听: 如果媒体流没有加密,攻击者可以录制通话内容
- 短信劫持: 在IMS中,SIP也承载即时消息,注册劫持意味着短信也被劫持
我曾经参与过一个事件响应:某公司CEO的号码被劫持,攻击者冒充他向财务总监发了一条「紧急转账」的即时消息。嗯,后果你可以想象。这就是注册劫持的杀伤力——它不只是技术问题,更是业务安全问题。
4.5 防御策略——我总结的实战经验
防御注册劫持,我建议从三个层面入手:
4.5.1 认证强化
- 强制使用Digest认证: 永远不要接受未认证的REGISTER请求
- 启用IP白名单: 对已知的注册IP进行限制,减少攻击面
- 使用TLS传输: 防止REGISTER请求在传输过程中被篡改
💡 我的小技巧: 在Registrar上配置「注册频率限制」。我曾经遇到过攻击者每秒发送上千个伪造REGISTER请求,频率限制能有效阻断这种暴力注册。
4.5.2 注册验证
- Contact地址验证: 检查Contact地址是否与注册来源IP匹配
- 多因子注册: 结合IP、User-Agent、地理位置等信息做综合判断
- 注册冲突检测: 如果同一个AOR突然从不同IP注册,触发告警
4.5.3 监控与响应
- 注册日志审计: 记录每次REGISTER请求的源IP、User-Agent、时间戳
- 异常行为告警: 短时间内大量REGISTER请求、频繁更换Contact地址等
- 自动回滚机制: 检测到劫持后,自动恢复为上一次合法注册
下面这张图是我自己整理的注册劫持攻击链与防御点:
4.6 避坑指南——我踩过的坑
最后分享几个我亲身经历过的教训:
- 别信「内网安全」: 我曾经以为内网环境不需要TLS,结果内部员工用ARP欺骗就完成了注册劫持。内网不等于安全网。
- Expires时间别设太长: 有些厂商把注册有效期设为24小时。你想想看,如果被劫持了,要等24小时才能自动恢复?我建议设成300-600秒。
- 别忘了注销处理: 攻击者可能会发送Expires=0的REGISTER来注销合法用户。一定要验证注销请求的合法性。
- 日志要保留原始包: 出事后排查时,只有摘要日志根本不够用。我习惯保留完整的SIP消息体,方便回溯。
总结一句话: SIP注册劫持的核心问题不是技术有多难,而是「信任」被滥用。防御的关键在于——不要信任任何未经验证的注册请求。
公众号:蓝海资料掘金营,微信deep3321