Detecting Duplicate Entries in TLS Certs

Hello all. I am fairly new to Suricata. Is there a way to write a rule to detect self-signed TLS certs?

Specifically, I would like to write a rule that looks at the Issuer Organization Name, as well as the Subject Organization Name, and then compares the entries, looking for strings that match between the two. We have a scenario where certs whose strings match between these two fields are invalid, and I want to alert on these types of certs.

I don’t know the what the content for these fields will be beforehand. However, I do know that the names in the two will match precisely.

Example:
IssuerOrganizationName=Cummings LLC
SubjectOrganizationName=Cummings LLC

Example:

IssuerOrganizationName=Sawianawski, Hand, and Keith
SubjectOrganizationName=Sawianawski, Hand, and Keith

Did you try to match (not compare yet) those cases with the tls keyword (6.15. SSL/TLS Keywords — Suricata 6.0.3 documentation)?

Hello, thank you for your reply. I read these rules, however each example given pre-supposes that the rule author knows something about what the pattern is going to be, and matches on that pattern. E.g.

Due to the fact that the strings in question could be anything, I don’t not have a pre-set pattern to match against. However, what I do need to match against is whatever the pattern is going to be between two fields. I need a rule where (A) matches (B), where (A) could be any string roughly 6 characters in length or more.

In the example given from the Rules page you linked, content is pre-defined:

tls.cert_subject; content:"CN=*.googleusercontent.com"; isdataat:!1,relative;
tls.cert_subject; content:"google.com"; nocase; pcre:"/google.com$/";

I don’t know what the content of SubjectName is going to be, so I can’t match it on IssuerName, e.g. I cannot enter that beforehand, as in the example from the rules page.

However, I need to be able to extract IssuerName, save that content as a variable, and then match subject name to that.

You could use aa Lua script to detect this:

function init (args)
    local needs = {}
    needs["tls"] = true
    return needs
end

function match(args)
    version, subject, issuer, fingerprint = TlsGetCertInfo()
    if subject == nil or issuer == nil then
        return 0
    else
      if subject == issuer then
        return 1
      end
    end
    return 0
end

and then use that in a rule to check:

alert tls any any <> any any (msg:"CUSTOM TLS duplicate value"; lua:tls-duplicate.lua; sid:1000001;)

Might be quite computationally expensive though, since it would check each and every TLS flow. If you have any other constraints you could add to the rule, it might help reduce the load.

3 Likes

This is perfect! I do not / have not coded Lua before, and it would have taken me a little while to figure this out. There are, in fact, 3 other fields which will never change, so I can use those combined with this in order to make the detection more performant.

This is perfect, thank you!