mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00

* accessing * across * adding * additional * addresses * afterwards * analyzer * ancillary * answer * associated * attempts * because * belonging * buffer * cleanup * committed * connects * database * destination * destroy * distinguished * encoded * entries * entry * hopefully * image * include * incorrect * information * initial * initiate * interval * into * java * negotiation * nodes * nonexistent * ntlm * occasional * omitted * otherwise * ourselves * paragraphs * particular * perform * received * receiver * referring * release * repetitions * request * responded * retrieval * running * search * separate * separator * should * synchronization * target * that * the * threshold * timeout * transaction * transferred * transmission * triggered * vetoes * virtual Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
112 lines
4.3 KiB
Text
112 lines
4.3 KiB
Text
##! This script sets up the certificate event cache handling of Zeek.
|
|
##!
|
|
##! The Zeek core provided a method to skip certificate processing for known certificates.
|
|
##! For more details about this functionality, see :zeek:see:`x509_set_certificate_cache`.
|
|
##!
|
|
##! This script uses this feature to lower the amount of processing that has to be performed
|
|
##! by Zeek by caching all certificate events for common certificates. For these certificates,
|
|
##! the parsing of certificate information in the core is disabled. Instead, the cached events
|
|
##! and data structures from the previous certificates are used.
|
|
|
|
@load ./main
|
|
|
|
module X509;
|
|
|
|
export {
|
|
## How often do you have to encounter a certificate before
|
|
## caching the events for it. Set to 0 to disable caching of certificates.
|
|
option caching_required_encounters : count = 10;
|
|
|
|
## The timespan over which caching_required_encounters has to be reached
|
|
option caching_required_encounters_interval : interval = 62 secs;
|
|
|
|
## After a certificate has not been encountered for this time, it
|
|
## may be evicted from the certificate event cache.
|
|
option certificate_cache_minimum_eviction_interval : interval = 62 secs;
|
|
|
|
## Maximum size of the certificate event cache
|
|
option certificate_cache_max_entries : count = 10000;
|
|
|
|
## This hook performs event-replays in case a certificate that already
|
|
## is in the cache is encountered.
|
|
##
|
|
## It is possible to change this behavior/skip sending the events by
|
|
## installing a higher priority hook instead.
|
|
global x509_certificate_cache_replay: hook(f: fa_file, e: X509::Info, sha256: string);
|
|
}
|
|
|
|
# Table tracking potential certificates to cache - indexed by the SHA256 of the
|
|
# raw on-the-wire representation (DER).
|
|
global certificates_encountered: table[string] of count &create_expire=caching_required_encounters_interval;
|
|
|
|
# Table caching the output of the X509 analyzer for commonly seen certificates.
|
|
# This is indexed by SHA256 and contains the Info record of the first certificate
|
|
# encountered. We use this info record to re-play the events.
|
|
global certificate_cache: table[string] of X509::Info &read_expire=certificate_cache_minimum_eviction_interval;
|
|
|
|
event zeek_init() &priority=5
|
|
{
|
|
x509_set_certificate_cache(certificate_cache);
|
|
x509_set_certificate_cache_hit_callback(x509_certificate_cache_replay);
|
|
}
|
|
|
|
hook x509_certificate_cache_replay(f: fa_file, e: X509::Info, sha256: string)
|
|
{
|
|
# we encountered a cached cert. The X509 analyzer will skip it. Let's raise all the events that it typically
|
|
# raises by ourselves.
|
|
|
|
# first - let's checked if it already has an x509 record. That would mean that someone raised the file_hash event
|
|
# several times for the certificate - in which case we bail out.
|
|
if ( f$info?$x509 )
|
|
return;
|
|
|
|
event x509_certificate(f, e$handle, e$certificate);
|
|
for ( i in e$extensions_cache )
|
|
{
|
|
local ext = e$extensions_cache[i];
|
|
|
|
if ( ext is X509::Extension )
|
|
event x509_extension(f, (ext as X509::Extension));
|
|
else if ( ext is X509::BasicConstraints )
|
|
event x509_ext_basic_constraints(f, (ext as X509::BasicConstraints));
|
|
else if ( ext is X509::SubjectAlternativeName )
|
|
event x509_ext_subject_alternative_name(f, (ext as X509::SubjectAlternativeName));
|
|
else if ( ext is X509::SctInfo )
|
|
{
|
|
local s = ( ext as X509::SctInfo);
|
|
event x509_ocsp_ext_signed_certificate_timestamp(f, s$version, s$logid, s$timestamp, s$hash_alg, s$sig_alg, s$signature);
|
|
}
|
|
else
|
|
Reporter::error(fmt("Encountered unknown extension while replaying certificate with fuid %s", f$id));
|
|
}
|
|
}
|
|
|
|
event file_state_remove(f: fa_file) &priority=5
|
|
{
|
|
if ( ! f$info?$x509 )
|
|
return;
|
|
|
|
if ( f$info?$sha256 && f$info$sha256 !in certificate_cache &&
|
|
caching_required_encounters > 0 &&
|
|
f$info$sha256 in certificates_encountered &&
|
|
certificates_encountered[f$info$sha256] >= caching_required_encounters &&
|
|
|certificate_cache| < certificate_cache_max_entries )
|
|
{
|
|
delete certificates_encountered[f$info$sha256];
|
|
certificate_cache[f$info$sha256] = f$info$x509;
|
|
}
|
|
}
|
|
|
|
event file_hash(f: fa_file, kind: string, hash: string)
|
|
{
|
|
if ( ! f?$info || "X509" !in f$info$analyzers || kind != "sha256" )
|
|
return;
|
|
|
|
if ( caching_required_encounters == 0 || hash in certificate_cache )
|
|
return;
|
|
|
|
if ( hash !in certificates_encountered )
|
|
certificates_encountered[hash] = 1;
|
|
else
|
|
certificates_encountered[hash] += 1;
|
|
}
|