linux-application-whitelisting / fapolicyd

File Access Policy Daemon
GNU General Public License v3.0
193 stars 55 forks source link

fapolicyd-cli --ftype should also be able to print out the filename #292

Open berndfinger opened 6 months ago

berndfinger commented 6 months ago

For finding out which files in a directory tree are candidates to be included in the fapolicyd trust file, the fapolicyd-cli command with the option -t or --ftype can be used. The problem is that the output only contains the file type but not the file name so it requires additional processing to construct the command fapolicyd-cli --file add <FILE> --trust-file <TRUSTFILE>.

One way of adding only executables to the fapolicyd trust file is shown in this task.

A command sequence for constructing the necessary fapolicyd-cli --file add commands would require joining each two output lines from a find command (the lines with odd line numbers displaying the file type and the even ones displaying the file name), like:

# find ${PWD} -type f -executable -exec fapolicyd-cli -t {} \; -print |\
     awk '/\/x-executable/||
     /\/x-sharedlib/||
     /\/x-shellscript/||
     /\/x-python/{a=1; b=NR}
     {
         if(a==1 && b==(NR-1)){
             print("fapolicyd-cli --file add "$0" --trust-file _trust_file"); a=0; b=0
         }
     }'

If the command fapolicyd-cli was able to also display the file name in the same line as the file type, similar to the file command, the processing of the output for constructing the fapolicyd-cli --file add commands could be simplified to:

# find ${PWD} -type f -executable -exec fapolicyd-cli -t {} \; |\
     awk '/\/x-executable/||
     /\/x-sharedlib/||
     /\/x-shellscript/||
     /\/x-python/{
        gsub (":$", "", $1);
    print("fapolicyd-cli --file add "$1" --trust-file _trust_file")
     }'

Maybe identifying candidates for adding to the fapolicyd trust file and actually adding them could also be done inside the fapolicyd command (e.g. using a command option for adding all executables in a directory tree) but maybe this needs to be discussed in depth elsewhere.

stevegrubb commented 6 months ago

I personally would not want automatic insertion without review. What I do is something more like (where $d is the directory to descend):

touch $tempfile
find $d -type f -print | grep -Ev 'example|/doc/|sample' >> $tempfile 2>/dev/null
while read f
do
    testf=`fapolicyd-cli --ftype $f 2>/dev/null | grep -E 'application/x-bytecode.ocaml|application/x-bytecode.python|application/java-archive|text/x-java|application/x-java-applet|application/javascript|text/javascript|text/x-awk|text/x-gawk|text/x-lisp|application/x-elc|text/x-lua|text/x-m4|text/x-nftables|text/x-perl|text/x-php|text/x-python|text/x-R|text/x-ruby|text/x-script.guile|text/x-tcl|text/x-luatex|text/x-systemtap'`
    if [ x"$testf" != x ] ; then
        echo -e "$testf\t$f"
    fi
done < $tempfile

The output of this can be further processed to compare the list against the trust database. The point is, fapolicyd-cli --ftype has to be passed the full path to the file. The information should be readily available if you write the script in a way that makes it available.

berndfinger commented 6 months ago

@stevegrubb - Right, my main point here is to make it easier to add new files into the fapolicyd trust file. The automatic insertion is just one (valid) use case, see below.

A usual way for displaying file information would be to display the file name along with the required additional information in one line - just like the commands ls -l, file or stat --terse. I actually would even prefer not to print a colon character at the end of the file name (here deviating from the file command).

Then the output of fapolicyd-cli [ftype option] can be directly, maybe after some filtering for file types, used for one or more of:

berndfinger commented 6 months ago

Displaying the file name along with the file type should rather be the default when displaying the file type, but this would be a breaking change. This was the only reason why I am proposing a new option to fapolicyd-cli in https://github.com/linux-application-whitelisting/fapolicyd/pull/293.

Or we provide a new command, like fapolicyfile or fapolicyd-file. The rpmfile command might also serve as an example in addition to the above mentioned commands fileor stat --terse. And it doesn't display the colon at the end of the file name either (however the difference is that it displays information about the members contained in a file and not the file itself).

berndfinger commented 6 months ago

We could also just search for the pattern /x- instead of a number of different patterns like e.g. /x-executable or /x-shellscript. In the case of a sample 3rd party software installation which I am looking at, this results in 971 instead of 881 files.

In this case, the list of executable files reported by fapolicyd-cli -t and the list of files reported by the file --mime-type command is identical. So I'd rather use file --mime-type instead of fapolicyd-cli -t (or fapolicyd-cli -T). Except if there was a specific reason for preferring the fapolicyd-cli command over the file command. The run times of the two commands are nearly identical.

Note: There are some differences in the outputs when checking for detailed patterns. For example, on a RHEL 9.2 test system, for a binary file, the two commands display the following: file --mime-type: application/x-pie-executable fapolicyd-cli -t: application/x-executable

And for a Python file, the two commands display the following: file --mime-type: text/x-script.python fapolicyd-cli -t: text/x-python

radosroka commented 6 months ago

Just a note that fapolicyd-cli should be preferred over file because it shows you how the daemon will detect the file. Although they use the same magic database there are multiple differences there like overrides in python detection and .elf parser implementation.

stevegrubb commented 6 months ago

Yes, there are differences where fapolicyd-cli should be preferred. When "file" suddenly added x-pie-executable when the same file was reported as x-executable in the previous release, it was decided that for consistency across a range of "file" releases, we need to do our own detection so that there are no surprises where types change on upgrade and now it doesn't work.

We also do whole system scans looking for things reported as text/plain and application/octet-stream to see if they need some logic for detection. If so, we send the patch to upstream "file" and patch our database. Therefore, on older systems, we have the better detection since the upstream patch won't be available until some future "file" release.