microsoft / ebpf-for-windows

eBPF implementation that runs on top of Windows
MIT License
2.75k stars 211 forks source link

Antimalware Callout... #182

Open magicalo opened 3 years ago

magicalo commented 3 years ago

Will the eBPF Loader support an AM Callout to allow scanning of bytecode before loading in kernel, or do we need to write our own eBPF hook to do this?

dthaler commented 3 years ago

@magicalo The job of the Verifier is to ensure that code is safe. Can you provide more information on what antimalware might do with such bytecode given the checks the verifier already does? I'm not sure whether Linux has such a capability today, does it? But if it makes sense across platforms then such a hook could certainly be added in the future.

magicalo commented 3 years ago

Does the Verifier have an ecosystem in place for signature updates of know malicious eBPF payloads?
This will eventually be an exploit vector for malware and APTs (independent of whether eBPF on other platforms provide these protections today).

jedwardsol commented 3 years ago

The job of the Verifier is to ensure that code is safe

Safety here means unable to crash or hang the kernel. A well-behaved BPF program can be unsafe in other ways, for example blocking a security product's access to the network.

magicalo commented 3 years ago

The job of the Verifier is to ensure that code is safe

Safety here means unable to crash or hang the kernel. A well-behaved BPF program can be unsafe in other ways, for example blocking a security product's access to the network.

Agree.
I think a AM callback hook would be warranted here for this exact scenario and also to ensure the BPF payload is not an APT. The verifier would not provide these capabilities and likely would lack the ecosystem to provide an ongoing sustainable model as malware authors create BPF APTs

jedwardsol commented 3 years ago

AMSI is a good choice here.

Referring to the architecture diagram, bytecode goes from an untrusted process to the PPL verifier/compiler. Then native code goes from there to the kernel.

If the bytecode is passed to AMSI from the untrusted process, then the AMSI handler has full context about that process which is useful from an anti-malware point of view. But AMSI in untrusted processes is vulnerable to attack.

If bytecode or native code is passed to AMSI from the PPL then some context is lost, and the 3rd party's AMSI handler DLLs will need to be PPL signed. But it is safe from the untrusted process.

dthaler commented 3 years ago

The Linux work related to #181 might have some of this too? @qmonnet Can you check if Linux has anything here?

Alan-Jowett commented 3 years ago

AMSI is the Microsoft Anti-Malware Scan Interface.

qmonnet commented 3 years ago

On Linux, the verifier makes sure that the program is safe and terminates, but it has no mechanism to check its signature against known malware signatures.

Note that at the moment, it is somewhat tricky to get a signature at all for an eBPF program, because of the relocation steps happening at load time, in particular the insertion of file descriptors for maps (replaced in the kernel by their address) which is not stable across multiple loads. This is being addressed with the patchset that I linked in #181, and further work in progress.

However, assuming signature can be computed, Linux has a LSM hook on program load (bpf_prog), so it is easy to hook on loads, examinate the program, and decide to accept or reject it before the user gets a chance to attach it. This can be done through the various existing LSM modules (or now even with eBPF attaching to LSM hooks).

During the triage meeting, we mentioned the possibility of checking JIT-ed programs. On Linux at least, I don't think this would make much sense, because 1) JIT-compiling occurs in the kernel, so once loaded the program cannot be tampered with before being JIT-ed, 2) this would mean re-writing checks for all architectures, and 3) kernel's verifier applies some minor transformations to the program, and they might vary from one kernel versions to the other, breaking the signature of the programs.

Ideally, the verifier should ensure the program is secure, that it does not leak sensitive kernel memory and so on. Out of curiosity, what is the threat model here?