Hello.
If you can hear me well.
Thanks.
My name is Arne.
I work for a company called Corelight.
I work on the seek project.
Quick information, who of you is using seek?
Anyone?
Three, maybe.
I want to talk about JavaScript support in seek.
But first, if you, well, there are not many people that have maybe heard of seek.
It's a passive network security monitor.
It's existence, well, a long time, 95, was development started.
It's open source and BST.
It was called Bro until 2018.
Bro isn't really a name that you should use for a project anymore.
So it was changed.
And if you look at it from a high level, you sort of feed it packets at the bottom,
either from a live network traffic, like live interface or from a PCAP file.
And what you get out at the top is sort of a set of logs that describes what kind of activity is in your network traffic.
If you look under the hood, there are a few more details.
So it's an event-driven system.
It has a custom scripting language.
We have some, we call it broker.
It's a messaging interface to talk between separate processes.
Yeah.
To give you a flavor of the logs that were at the top, sort of, those are single entries for single connections.
So on the right-hand side, there's the con log, which is the most central log.
And, well, there's the identifying five-tuple.
We also support IPv6, but that's an IPv4 example.
The service field indicates what kind of protocols Seek was able to discover within that connection.
And then the bottom is sort of statistical information, like packet counts and duration.
On the left-hand side, you see more protocol-specific log, in this case the quick log, which has been recently added.
And for example, there's the, so you can see the server name in the client protocol.
And if Seek is able to decrypt the initial packet of a quick connection, it forwards the crypto payload to the TLS analyzer,
which can then extract that kind of information, and we put it in a log field as you see.
That is sort of the data that you would push to elastic search or Splunk and then do your analysis there.
That's sort of not Seek jobs, we just produce logs.
Okay.
It's a fairly old system.
It has a custom scripting language, and it looks sort of, that's just a sketch.
It's not actually going to work like this, but it sketches how the quick log entries created.
So there are two event handlers, one for initial packets, so whenever there's an initial packet, that event is raised,
and we create a info record, which represents the quick log entry in the end.
And then there's another event that is the SSL extension server name that is raised whenever there's an SNI extension in the client Hello.
And you can handle it and basically enrich that quick log entry with the server name or with the first name.
That's just a heuristic here.
The bottom is a sort of log write call where we actually then produce that JSON entry.
So yeah, but it might look a bit unusual in the beginning.
It's a fairly powerful language that has some network domain specific features that also allow you to write detections with Seek and sort of build advanced analysis also within that scripting language.
What's not so great is sort of interaction with the outside world that log write, for example, is the thin layer above the whole C++ logging framework.
So that is not implemented in Seek script, but then you have to do that in C++.
And usually any extension that you want to do, you have to resort to writing a plugin in C++.
Yeah, we do have so if you don't go to C++ route, we do have support for asynchronous HTTP requests.
And if you look a bit under the hood, then the thing is spawning is read and it's launching for writing stuff into temp directory and into a file still and then it reads them and gives them back to the script.
So it's a really scary implementation of an HTTP request.
So the idea was to, well, why don't we use a language that maybe does provide all that stuff and sort of has a rich ecosystem and has is well known as well.
And particularly the Node.js, because of the libraries and the NPM system, so that there was sort of the idea.
And as a twist, we are doing this as a plugin and not by patching Seek source code base.
We just want to build something external to add support to Seek to also use JavaScript.
So quickly about plugins. They're basically shared libraries that seek loads at startup and within that plugin you can access Seek's C++ API or also hook into certain execution paths.
For example, whenever a new connection is, so new connection state is created, you can implement the hook set up analyzer tree and attach something to that connection usually analyzers, a protocol analyzer we would say.
They also really made components where basically implemented against an interface. There's no component for a whole scripting language, so we sort of resort to the first two to implement the JavaScript support.
Okay.
So that top hopefully doesn't look too unfamiliar if you have some JavaScript. There's an event object on the left that is called Seek, sort of a global object.
There's a well known on function where you register that an additional function for a certain event in M. So that that looks more usual problem in the Seek script example.
And as an addition, there's the there's the HDT module from our HDPS module from Node and there's also an example how you could put how you could post the connection you had the end those SSR server names mentioned before to an HDP endpoint just from within Seek script.
So we want to get there. And the first step is to, as you prevent Seek from interpreting .js files as Seek script, which it would do with default.
And you can implement hook load file and basically check if the if the file name that Seek is attempting to load is ending with .js and return one basically says well don't bother about it I'm taking over and we are stashing away those JavaScript files.
And that works for files in the command line or also those with directives loaded. So the add load directive.
Step two is sort of to initialize the whole JavaScript engine, sort of the V8 engine and the Node.js environment. There's documentation about that. There's a link here. This is sort of a sketch.
It's a bit complicated but I have good documentation about it. What is happening at that point is also that we are loading the JavaScript files and so the top level Seek on calls are actually executed.
So we need to provide this Seek on call already. So I'll say this is just step three.
I need to slow down a bit. Just for myself. So step three is the call to Seek on is basically getting an event handler name and listener function.
And with that event handler name we can use C++ APIs to look at the event handler object which is a Seek specific object representing that, well, belonging to that event name.
From that we can get a script function which usually has a list of bodies and each of the bodies contains a statement list and then there are further statements.
So usually the script execution is interpreted. So it just runs down all those statements and executes them.
What the plugin can do is add another body into that list of bodies and provide the custom statement subclass which when executed really just calls into JavaScript and executes a V8 function.
So when this first happened it was really exciting. You see a hello printer from Seek and a hello printer from console.
It was nice to get done. What was not so nice is that you need to map types between those two languages.
So there's different types on the Seek side and JavaScript has other types.
For example the address or subnet type on the Seek side we currently just mapped to strings in readable form.
It's not the most performant but it was nice to have Jason stringify and have IP addresses like that.
I'm not going to talk much more about this.
The last step was to integrate both of the IO loops.
Seek has its own IO loop that is KQ based and Node.js has also an IO loop which is libUV based.
Usually the Seek IO loop is blocking on an event call waiting for a packet to be served or a block of packets or a timer has expired or something else happening and an act on it.
What the plugin can do is register something called an IO source and in the case of libUV the plugin takes the backend file descriptor of the libUV IO loop
and installs it into the Seek IO loop which means that whenever something has to be done on the Node.js side like a client is connecting on a listening socket
then the backend file descriptor of the libUV loop becomes ready and the Seek IO loop is waking up.
Recognizing this is Node.js file descriptor that became ready.
I need to transfer control over to that loop and the plugin runs the Node.js loop non-blocking until there's nothing left to be done and control is then transferred over back to Seek.
Yeah, that was the most tricky part of the whole plugin.
I didn't talk much about the picture before, the architecture, but where I would position that is sort of, it's not completely technical to correct,
but if we have extended the event engine a bit with Node.js event engine down there and then also the Seek script language, so we have extended everything with being able to also use JavaScript instead of the Seek script language.
As a summary, I find it really impressive that we could do that without actually patching Seek.
Everything was in place to pull this off which is testament to how Seek was built over the years really.
We're not going to replace the Seek scripts that are existing with JavaScript, that is not sort of the plan.
The integrations you wanted to build or maybe just wanted to have proof of concepts of things that you previously needed to quickly use C++ and find some C++ library to do whatever.
You can now tap into NPR ecosystem or JavaScript and try it with that.
That plugin is sort of coming with Seek 6.0 by default, so if you have LIT node installed and you compile Seek it will just be supported really.
And our container images also have it built in by default as well.
Any questions about that?
Any questions?
Hi, Armin.
Have you evaluated the performance of this? Does it impact performance a lot?
I would say it runs slower than just Seek and interpreted scripting, mostly because we need to translate between those two types.
I would also currently position it to not necessarily run JavaScript in the packet path unless you are really adventurous.
We have also Seek processes like the proxy and the manager that don't do packet processing.
They have a lot more cycles there.
If you run JavaScript there and do sort of pulling in IOC information, that's one use case, that you can do in a node that is not in the packet path.
We would be interested in performance numbers.
Thanks.
Have you explored other languages as well, apart from JavaScript?
Not explored, I sort of have in my mind as a proof of concept Python, but JavaScript was sort of asynchronous, it's non-blocking.
That's a paradigm there and that's what we needed as a replacement for Seek script.
Thanks.
Any more questions?
Thank you very much.