IsInCidrRanges

Determines whether an IPv4 or IPv6 address is contained in at least one of the comma-delimited CIDR ranges. Multiple IPv4/IPv6 addresses can be passed comma-delimited and each will be tested. A mix of IPv4 and IPv6 addresses will always return false.

javascript · Filters And Transformers

Source

// NOTE: A copy of the code below is in IsNotInCidrRanges script, they should be kept identical

function isIPv6(ip) {
  return ip.indexOf(':') !== -1;
}

function ipv6ToBinary(ipv6) {
  // Split the IPv6 address into its components
  var components = ipv6.split(':');

  // Handle zero compression (::)
  var zeroCompressionIndex = components.indexOf('');
  if (zeroCompressionIndex !== -1) {
      var zeroCount = 8 - components.length + 1; // Calculate the number of missing components
      components.splice(zeroCompressionIndex, 1);
      for (var i = 0; i < zeroCount; i++) {
          components.splice(zeroCompressionIndex, 0, '0000'); // Replace :: with zero components
      }
  }

  // Convert each component to binary and pad to 16 bits
  var binaryComponents = components.map(function (component) {
      // Handle the case when the component is an empty string
      if (component === '') {
          return '0000000000000000'; // 16 zeros for an empty component
      }

      var binary = parseInt(component, 16).toString(2);
      return Array(17 - binary.length).join('0') + binary;
  });

  // Concatenate the binary components
  var binaryString = binaryComponents.join('');

  return binaryString;
}


function ipToBinary(ip) {
if (isIPv6(ip)) {
  // IPv6
  return ipv6ToBinary(ip);
} else {
  // IPv4
  return ip.split('.').map(octet => ('00000000' + parseInt(octet, 10).toString(2)).slice(-8)).join('');
}
}

function validateCIDR(cidrRange) {
  var cidrRegex = /^([0-9a-f:.]+)\/([0-9]{1,3})$/i; // Regex for IPv4 and IPv6 CIDR notation

  var match = cidrRange.match(cidrRegex);

  if (!match) {
      return false; // CIDR range is not well-formed
  }

  var subnetMask = parseInt(match[2], 10);

  if (match[1].indexOf(':') !== -1) {
      // IPv6 CIDR
      if (subnetMask < 0 || subnetMask > 128) {
          return false; // Invalid subnet mask for IPv6
      }
  } else {
      // IPv4 CIDR
      if (subnetMask < 0 || subnetMask > 32) {
          return false; // Invalid subnet mask for IPv4
      }
  }

  return true; // CIDR range is well-formed
}

function getCIDRNetworkAddress(cidrRange) {
  return cidrRange.split('/')[0]
}

function getCIDRSubnetMask(cidrRange) {
  return cidrRange.split('/')[1]
}

function isIPInCIDR(ipAddress, cidrRange) {
  if (!validateCIDR(cidrRange)) {
      return false;
  }

  var networkAddress = getCIDRNetworkAddress(cidrRange);
  var cidrSubnetMask = getCIDRSubnetMask(cidrRange);

  // Convert IP address and network address to binary
  var ipBinary = ipToBinary(ipAddress);
  var networkBinary = ipToBinary(networkAddress);

  // Get the network part of the IP address based on the subnet mask
  var networkPart = ipBinary.slice(0, parseInt(cidrSubnetMask, 10));

  // Check if the network parts match
  return networkPart === networkBinary.slice(0, parseInt(cidrSubnetMask, 10));
}

function isIPInAnyCIDR(ipAddresses, cidrRanges) {
results = new Array(ipAddresses.length);

for (let i = 0; i < ipAddresses.length; i++) {
  isInRange = false;

  for (let j = 0; j < cidrRanges.length; j++) {

    // Mismatches are always false
    if ((!isIPv6(ipAddresses[i]) &&  isIPv6(getCIDRNetworkAddress(cidrRanges[j])))
     || ( isIPv6(ipAddresses[i]) && !isIPv6(getCIDRNetworkAddress(cidrRanges[j])))) {
      results[i] = 'False';
    } else if (isIPInCIDR(ipAddresses[i], cidrRanges[j])) {
      isInRange = true;
      results[i] = 'True';
      break;
    }
  }

  if (!isInRange) {
    results[i] = 'False';
  }
}

return results;
}

ipAddresses = argToList(args.left)
cidrRanges = argToList(args.right)

// NOTE: A copy of the code above is in IsNotInCidrRanges script, they should be kept identical
return isIPInAnyCIDR(ipAddresses, cidrRanges);

README

Determines whether an IPv4 or IPv6 address is in part of at least one of the comma-delimited CIDR ranges given. Multiple IPv4/IPv6
addresses can be passed as comma-delimited list to be checked. A mix of IPv4 and IPv6 addresses will always return false.

Script Data


Name Description
Script Type python3
Tags filter
Cortex XSOAR Version 5.0.0

Inputs


Argument Name Description
left The IPv4 or IPv6 address to search for.
right A comma-separated list of IPv4 or IPv6 ranges in CIDR notation against which to match.