Unable to commit detection

I’m trying to write a custom script to specifically look for SMB/CIFS enumeration. Do understand that ExtraHop has a OOB detector for such enumeration however not all our IP are classified as proper assets, hence, we had to write a custom script for this. Script in general is looking for a single Source IP that is enumerating over 200 different resource in 5 minutes. I’m able to output the debug logs prior to the commitDetection function, so i reckon the logic is working as expected but the commitDetection function does not seem to be working just for this

Would appreciate if i can get some assistance on this.

const KEY_NAMESPACE = “SMBCIFS”;
const PERIOD_SEC = 300;

if(event == “CIFS_RESPONSE”){

//defensive
if(CIFS.resource == null || CIFS.resource == "" || CIFS.resource == undefined || CIFS.share == null)
    return;

if(CIFS.resource.endsWith("\gpt.ini") || CIFS.resource.endsWith("fdeploy.ini") || CIFS.resource.endsWith("Registry.xml") || CIFS.resource.includes("\IPC$") 
|| CIFS.resource.endsWith("comment.cmtx") || CIFS.resource.endsWith("GptTmpl.inf") || CIFS.resource.endsWith("Registry.pol"))
    return;

if(CIFS.method.toLowerCase().includes("read")){
    const liveEntry = updateSessionEntry(new IPAddress(Flow.client.ipaddr.toString()), new IPAddress(Flow.server.ipaddr.toString()), CIFS.share, CIFS.resource);
    processDetection(liveEntry);
    processEntry(liveEntry);
}else
    return;

}

function updateSessionEntry(src_ip, dst_ip, share, resource){
const blankEntry = {
src_ip: src_ip,
dst_ip: dst_ip,
share: share,
resource: resource,
resource_array: [],
};

//debug("src: " +blankEntry.src_ip+ ", dst: " +blankEntry.dst_ip+ ", share: " +blankEntry.share+ ", resource: " +blankEntry.resource+ ", resource_array length: " +blankEntry.resource_array.length);
const key_name = KEY_NAMESPACE + md5(blankEntry.src_ip + blankEntry.dst_ip + blankEntry.share);
const sessionEntry = Session.add(key_name, blankEntry);

sessionEntry.resource_array.push(resource);

Session.replace(key_name, sessionEntry, {
    expire: PERIOD_SEC

});
return sessionEntry;

}

function processEntry(entry){

let unique_resource_array = entry.resource_array.reduce(function(a,b) {
if (a.indexOf(b) < 0 ) {
    a.push(b);
}
return a;
},[]);

//debug("A Src ip: " +entry.src_ip+ ", Length: " +unique_resource_array.length);


var smbcifsmon = Application("SMB/CIFS Monitoring");

//smbcifsmon.metricAddDetailCount("Teams client IP count", Flow.client.ipaddr.toString(), 1);
smbcifsmon.metricAddDetailDataset("SMB/CIFS Counter", Flow.client.ipaddr.toString(), unique_resource_array.length);

smbcifsmon.commit();

}

function processDetection(entry){

let unique_resource_array = entry.resource_array.reduce(function(a,b) {
if (a.indexOf(b) < 0 ) {
    a.push(b);
}
return a;
},[]);

//debug("D Src ip: " +entry.src_ip+ ", Length: " +unique_resource_array.length);


if(unique_resource_array.length > 200){

    debug("Sus SMB/CIFS ~Source IP:" + entry.src_ip + "~Dest IP: " + entry.dst_ip + "~Share: " + entry.share + "~E.g. of resource accessed: " +entry.resource+ "~Est. no. of resource accessed: " +unique_resource_array.length); + "\n"
    
    commitDetection('Potential_High_SMBCIFS_Enum_v1', {
        categories: ['sec', 'sec.command'],
        title: 'Potential_High_SMBCIFS_Enum_v1',
        description: [
            "This client is doing SMB/CIFS enumeration over the same server and CIFS share over a short period of time. " + "\n" +
            "Investigate the client IP for potential SMB/CIFS enumeration." + "\n" +
            "- **Client IP:** " + entry.src_ip,
            "- **Server IP:** " + entry.dst_ip,
            "- **Share:** " + entry.share.toString(),
            "- **Estimated  no. of resource accessed:** " + unique_resource_array.length,
        ].join('\n'),
        participants: [
            { role: 'offender', object: entry.src_ip },
            { role: 'victim', object: entry.dst_ip }
        ],
        identityKey: [
            entry.src_ip.toString(),
            entry.dst_ip.toString(),
            entry.share.toString()
        ].join('~~'),
        identityTtl: 'hour',
        riskScore: 49,
    });
}

}

Hi Bryan, I’m looking into getting some time with our local PS team to assist with this. I’ll get back to you directly with the next steps as to how we can assist with this custom detection. Thanks!

Curious why you are converting Flow.client.ipaddr from an IPAddress object, to a string, and then back into an IPAddress object?

As far as the call to commitDetection(), have you ever gotten a detection created? If this activity is happening with regularity, you might be running into the deduplication of new detections. Detections are deduplicated based on the value of identityKey, and each time one hits, it will extend an existing detection out N time, based on the value of identityTtl.

Hi,

Thanks a lot for the response.

Believe the conversion of an ip object to string then back to an object was due to a bug that was found when i posted this thread.

As for the commitDetection function, i dont have a existing detection because my identityKey is leveraging on the CIFS share information (unless there is some backend cache/processing that i’m not aware of). Not sure if ExtraHop OOB rule for SMB/CIFS enumeration might interfere with this.

Yes, that was fixed in 8.7.2 and 8.8.0, so you should no longer to need to perform this step if you are on a somewhat recent release

The value of the string is what is used for deduplication – in your case that is <src_ip>~~<dst_ip>~~<share name>, so if you see a lot of activity to that tuple, then you won’t get distinct detections for it unless the time-to-live expires.

In my debug logs, there is a particular group of source ip, destination ip, and sharename. However, i did not find any corresponding detection with even the source IP for the last 5 days. I have shared some screenshot for reference. Is there any way i can retrieve more information to figure this out?