-
-
Notifications
You must be signed in to change notification settings - Fork 532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Calculate a checksum for each whitelisted executable #413
Comments
hey @wirespecter , This is an interesting feature request. I agree with you in all points. But maybe we could cause some confusion, if as you said, you've whitelisted a binary and it's updated. So an option to enable it should be mandatory. On the other hand, when you allow a new process, you don't know if it's goodware or malware. In any case, at the very least, if the checksum changes we could warn users about it. |
Thanks @gustavo-iniguez-goya ,
As with any other process that we whitelist, it is up to the user to decide.
I agree with this. However, it depends on the default behavior that is going to be implemented after the warning has taken place.
|
I don't really agree with this idea. I mean yeah it can add more protections for user but in my opinion it has some disadvantages:
In my opinion, alternative solution could be create whitelist of protocol that binary can use. Like But i am seeing an interesting point. Let say that, P/s: I think this is a really really interesting topic to increase protections so i would like to discus more and learn from everybody ^^ Thank you @wirespecter for a very interesting topic :D |
Before dumping some thoughts: how often will this scenario occur? I see 3 possible scenarios:
In the later case, the admin should allow binaries specifying the absolute path to the binary.
More than adding protection I see it as a way of letting the user know that something changed since that binary was allowed (or denied). You can't configure it right now, but I think the checksum is just a property of a rule that it's not configurable. If you have allowed However we're implicitly allowing nc, trusting that the binary is goodware in both cases, regardless if it's the same binary or not.
In that case you'd allow your
We wouldn't be acting as an AV here because we wouldn't be classifying the binary as goodware, grayware or malware, nor killing it and nor moving it to a quarantine. But I agree that it adds complexity and probably performance penalty.
In this case, if you have allowed ping, it'll be allowed regardless if it's launched from a terminal or spawned by a different process
I agree. However opensnitch it's not a traditional firewall where you only allow/deny network connections. There's an extra component that is also part of the connection, which is the binary that initiated it. Binaries also have their own properties: path, name, arguments, current working directory (from where it was launched), permissions, ownership, checksum, size, parent pid, etc.
Filtering by checksum is not something urgent right now, as there're many other things to do first. But it doesn't seem to be that crazy to me. Anyway, it'd probably be better to implement it as an addon rather than adding it to the codebase. |
I'm having an idea: Can we create some
|
I wrote a small program inspired by this one a while back with this exact feature as well as the option to upload the checksums to VirusTotal. I recently fixed it up a bit |
@gustavo-iniguez-goya Can't tell how much I'm thankful for this piece of software, thanks for all your work. Since this is networking focused we can adjust this feature accordingly. VirusTotal allows domain validation, so in such case if user supplies VT API key can we add an option to validate domain application tries access (via VirusTotal API) and show validation status Bad\Good\Unknown in Allow\Deny connection dialogue ? This way we're keeping focus on networking, yet improving security. Best regards. |
Hi @sl805 , thank you for the kind words :) I think that making requests to an external url is something that many users would be against with. I created PoC of your idea sometime ago and posted a screenshot somewhere. It's really easy to integrate VT, at least on the GUI, but we need consensus on these new features. |
I'm against using an external service for AV checking. This is an application firewall not an Antivirus... But, as an application firewall, we allow "executables" to connect to the Internet. If we cannot ensure our executable is the one we whitelisted and any malware can replace any executable and ping home, then we are failing our firewall mission since that malicious executable is not whitelisted. Because that executable is not actually our executable. We just actually whitelist paths, not executables. That is why we should implement an optional hashing. I proposed Blake3 because it should be the fastest but safe. |
I'm against too. |
I think that we have to be careful with hashing executables because it can be very annoying if we are asked for new connections after an update of one executables that we have already configured/allowed. |
That's why I say "optional". It can be a type of filtering of a rule. "By executable path" (like now) or "by executable hash" |
There could be a "flexible" solution. On Debian based system, binaries installed by
Cons:
p/s:
That was my point as well but at least with this solution we can have flexible solution for binaries installed by system. |
I think checking the hash is more useful for user owned executables since for system binaries (apt installed) need root for installing and a malware would need to scalate privileges. |
Well i think for malware that has root permission / rootkit is an other scenario and it is more about AV / HIPS solution rather than firewall.
|
@gustavo-iniguez-goya Daemon will:
UI will:
In such case this feature becomes optional and will give people freedom to trigger any kind of automation they like:
This way user-defined code will be responsible for whatever user wants, and OpenSnitch will just invoke it and display status for user to be aware of it before taking final decision. Best regards, sl805. |
@gustavo-iniguez-goya Happy New Year Gustavo. Is there any sense in my idea? |
hey @sl805 , I think that it's quite an elaborated proposal, thank you for taking the time to thing about it. I promise that I'm taking into account all suggestions and ideas. Reading your proposal, the first that comes to my mind is adding it as a plugin 📖 As I said above, for me the checksum is just another property of a binary, so I think I'll end up adding it. Later we can decide what to do with it. I like the idea of start small and simple, and keep adding complexity over time, so we could start with something like this:
If the checksum changes, opensnitch will prompt you to allow or deny the connection (as it already does when a field doesn't match). Regarding the @dmknght ' s idea of using apt checksums, it could be added as rule of type lists, like what we already do with domains, IPs, etc. The rule would load the checksums on the startup, and the user could decide what to do with those checksums: deny or allow connections that matches application's checksum. Adding this feature opens the possibility to create lists of IOCs, that could be used to block known malware/badware (for servers mostly), like we already do with domains, IPs, etc. On the other hand, the user should be able to choose what checksum algorithm to use (md5, sha1, blake3, etc). Mainly because IOCs are created with md5/sha1 algorithm. So for example you could verify firefox's checksums with blake3, and deny everything that matches md5/sha1 checksums from a list. |
Hi @gustavo-iniguez-goya,
To clarify my point of view on the subject a little, I am not against the idea of checking that the binary that we want to block and more particularly to allow is the one we want. |
👍 understood.
That's not possible right now, because we don't have an Alerts module. After you create a rule, it remains static for the rest of its lifetime and we can only apply 3 actions on it (allow, deny, ask) If a connection doesn't match with a rule, right now the only option is to ask the user to allow or deny it. The alerts module could work just like the application rules, a list of rules with fields to check and actions to perform (send desktop notification, send email, colorize a row, etc). I thought about this necessity, because when a list of domains/IPs is reloaded because it has been updated, you don't get any feedback. It'd be cool to configure an alert to display a desktop notification saying: "Ads domains list updated". |
Hello! I checked the checksum db of dpkg and It doesn't have checksum for all binaries. By quick look, I can see it ignores same checksum for different file paths (like |
As far as I can tell on that particular case, on Sid bash is installed under /bin (dpkg -L bash): |
I think, it could be a lot simpler to don't have to checksum every binary the system could have.. |
I agree with @NRGLine4Sec and I will point to: https://en.wikipedia.org/wiki/Unix_philosophy
|
@dmknght you pointed out some interesting points 👍
This will be a problem if we add checksums. I didn't take it into account. This is also true for java, ruby, perl, bash, etc.
The attack vector is interesting. I just tried it and you're right, even creating a rule for a particular command (e.g.: telnet www.google.com 80), one could place a backdoor that used the allowed command (telnet ww.go... etc), and initiate a new connection to another host that would also be allowed (LD_PRELOAD=./backdoor.so telnet www.google.com 80, where backdoor.so opens a connection to attacker.com:9999) However, if you filter by "command line" + host (and port, uid, etc), then we prompt the user to allow/deny the connection to the attacker's .domain/IP, because the properties of the connection doesn't match with any rule (verified ✔️ ). Sometimes filtering by application + dest host is not practical, like with web browsers, but checking the checksum wouldn't help here either. |
No, sorry. I meant that if you have a rule that allow traffic initiated by
For example, instead of ping lets use telnet (or gnome-software, synaptic, whatever):
|
One way of using dpkg's db would be by generating a single file with all the known/installed checksums (md5 or whatever):
Then you'd create a new rule: [x] Enabel, [x] Action: Allow, [x] List of md5sums: /tmp/dpkg-db.txt Internally, if such rule is created and enabled, we would 1) get the md5 of an app that is trying to establish and outbound connection, 2) check the path + md5 against the DB. The generated list could be autoupdated by adding a post-invoke script to apt: On the other hand, a user could also create a DB of checksums with the help of a simple script: This db would work on any system, regardless of the package manager, and could also be integrated with apt and probably others package managers, or be added to a cron task. |
I think no need to check both path and md5. Only md5 is enough. For example
I think it technically works but with issues:
Because you mentioned about .txt file for checksum, i'm wondering is it faster than load everything into memory and compare it in memory? Maybe save all sums in a cache file, and then use iterator to compare each line is better for memory usage but performance is questionable. |
The "db" (a list of md5 checksums + paths) would be generated on each system with a script, via cron or similar, so the list would be specific to that installation.
Nope. the .txt file would be loaded into memory, just like what we do with domains lists. A map of key: hash, value: path |
So I'm thinking about "hook scripts". APT has config to run a script after user install any package. I don't really know much about this. But this is a good method to reload all checksums to memory. |
I've got a PoC working. Some benchmarks: md5: 497.725253ms, /usr/lib/chromium/chromium, hash: fc5b1708gh7a0a848bfc5f477bb9d39b That's a lot of time even for a binary of ~180MB. The bottleneck is not the hash algorithm, but the reading of the file. [edit] Computing chunks of a file (1kb, 4kb, 1mb...) helps to reduce reading times down to µs. With this PoC you get alerted if the checksum differs. It can be due to a malicious activity, an update of the binary or if a process is launched from a different namespace/container with the same path + name. Regarding the concerns about if this functionality is part of a firewall: Some notes:
|
@gustavo-iniguez-goya Thanks for working on this. I agree with all your points above. |
@gustavo-iniguez-goya There's "not very famous" EDR called Falco. It uses eBPF to catch syscall. It has so many features so I'm thinking what if there's an application firewall based on this EDR. I think with rules or custom plugins, developers can create a opensnitch-like UI and ofc calculate checksum is possible. What do you think about it? |
hey @dmknght , I think that type of software is actually really interesting: falco, tracee, redcanary, tetragon, ehids, ... (there're a lot). But I think they're more server oriented, so I don't know how easy would be to add a desktop GUI, or if it's worth the effort. Regarding this feature in particular, if someone is willing to test it and give back some feedback, I can publish a branch with the feature. There're some quirks and corner cases (that may c, but all in all it works fairly well. |
I'm not sure about the other but the |
I agree with the point of delegating this problem (asses if the binary is malicious or not) to a different tool, but being in the flow of establishing new connections and having the UI notification mechanism in place gives OpenSnitch a great position to alert users on this. What about supporting delegating the assessment of the binary to a separate tool? graph LR
newCon(["New connection request"]) --> hashChanged{"Binary hash changed"}
hashChanged -- Yes --> scanBin[["Call binary scan"]]
scanBin --> binSuspicious{"Binary is suspicious"}
binSuspicious -- Yes --> alertUser[["Alert User"]]
hashChanged -- No --> continue(["Continue"])
binSuspicious -- No --> continue
alertUser --> userAccepts{"User accepts risk"}
userAccepts -- Yes --> continue
userAccepts -- No --> block(["Block"])
What I am not clear is how it could be user-friendly setup-wise. |
Some updates on this issue. I've got this feature working and I'm testing and improving it. Hopefully I expect to add it after v1.6.2.
Working on it. Probably processes' hashing will be enable only if there's any rule that requires it. Still thinking about it.
Now the checksum is not recalculated every time a new outbound connection is about to be established. It's cached for the life of the process.
With lists of checksums, like the lists we have for domains or IPs, these rules could work by adding the checksums of each path in the regexp.
Done. And added a workaround for AppImages, which are a little bit special. For a simple usage of a Linux desktop (office suites, image editing, browse the Internet, reading emails...) , it looks like it doesn't penalize much the user experience, but we'll see how it behaves on different machines. On the other hand, the work on this feature will unlock new features, like displaying the process' parents that executed the process or filtering by parent PID. |
Now you can create rules to filter processes by checksum. Only md5 is available at the moment. There's a global configuration option that you can use to enable or disable this feature, from the config file or from the Preferences dialog. As part of this feature there have been more changes: - New proc monitor method (PROCESS CONNECTOR) that listens for exec/exit events from the kernel. This feature depends on CONFIG_PROC_EVENTS kernel option. - Only one cache of active processes for ebpf and proc monitor methods. More info and details: #413.
Added: 7a9bb17 This commit is only one piece of the puzzle, it's WIP.
As part of this feature there has been added new functionality and code reorganization:
Some caveats:
Peculiarities:
Notes:
|
An update on this issue: in general it's working fine. I've only observed a problem with apps that spawn other processes (firejail for example). If you don't know what's going on, the visual warning stating that the checksum has changed can be a bit confusing. On the other hand, is a bit annoying having to update a rule manually whenever a checksum changes due to an update. Not much, but I guess if you're on a rolling release distro it will be a bit more frustrating. WIP to impove user experience of that scenario. And some interesting notes about this issue after watching some Linux Plumbers '23 talks. There're some technologies that we could investigate to replace or complement the current approach (calculate checksums on-demand):
More info: https://lwn.net/Articles/753276/ |
When the checksum of a binary changes, due to an update or something else, you'll be prompted to allow the outbound connection if the previous checksum of the rule doesn't match the new one. Without a visual warning was almost impossible to know what was going on. Besides, you had to dismiss that pop-up, find the rule, and update the checksum. Now there's a warning message, and you can update the rule from the pop-up. Related: #413
- Fixed several leaks. - Cache of events reorganized and improved. * items are added faster. * proc details are rebuilt if needed (checksums, proc tree, etc) * proc's tree is reused if we've got the parent in cache. rel: #413
Hopefully this feature gets into the next release that's pushed to the repos soon. Looking forward to it, especially for user-owned binaries! |
Hi there,
First of all, let me say a big thank you for this awesome program! It seems to be working well and I love it!
I think that it would be greatly improved if it calculates a checksum for each file that is in the whitelist.
Why? Because a malicious application can replace a whitelisted program with itself in order to avoid detection.
For example: Let's say that
/usr/bin/ping
is whitelisted, if a malware overwritesping
the malicious ping that resides in the same path is whitelisted as well.All of this can be avoided if we compare the malicious
ping
's checksum with the checksum of the "good"ping
that we got when it was whitelisted.I know that this may complicate things when an application gets updated (thus the checksum changes), but we can add this as an option in the menu for users that want an additional level of security.
Thanks for reading so far and please let me know your thoughts below :)
The text was updated successfully, but these errors were encountered: