Skip to content
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

I expect an absolute path to the new file, but I get a relative path to the new file #3014

Open
SerhiyProtsenko opened this issue Jan 15, 2024 · 6 comments
Labels
Milestone

Comments

@SerhiyProtsenko
Copy link

SerhiyProtsenko commented Jan 15, 2024

My task is to always have the absolute path to a file that is created, modified, etc. I run Falco version: 0.36.2 (x86_64) in the first Docker container, and in the second Docker container I create and modify the file. And I get the relative path (container path but not the host path). A must receive absolute path (a path host).

I use rule:

- macro: exclude_common_directories
  condition: (not fs.path.name startswith /proc) and 
             (not fs.path.name startswith /sys) and 
             (not fs.path.name startswith /run) and              
- rule: created_files
  desc: Detect file operations indicating a completed download or file creation using fs.path.name.
  condition: evt.type in (openat, open, creat, openat2, open_by_handle_at) and  (evt.arg.flags contains O_CREAT or evt.arg.flags contains O_WRONLY or evt.arg.flags contains O_TRUNC or evt.arg.flags contains O_APPEND) and
             not evt.arg.flags contains O_DIRECTORY and 
             fd.typechar='f' and 
             fd.num>=0 and 
             exclude_common_directories
  output: user=%user.name uid=%user.uid process=%proc.name pid=%proc.pid parent=%proc.pname ppid=%proc.ppid command=%proc.cmdline file=%fs.path.name syscall=%evt.type  container_id=%container.id container_name=%container.name
  priority: WARNING
  tags: [file, write, create]

I've tried using other file path options: file_2=%evt.arg.name or file_3=%fd.name but it didn't work, I always get a relative path to the file in the container, and I need an absolute path to the host file.

Examples of the output of the rule, it can be seen that the path to the file is relative - the path in the container, and not the absolute path of the host:

{
  "hostname": "victim",
  "output": "17:12:18.098829335: Warning file_3=/e123456 user=root uid=0 process=touch pid=83884 parent=bash ppid=83831 command=touch e123456 file=/e123456 file_2=/e123456 syscall=openat  container_id=22afeacb59b8 container_name=<NA>",
  "priority": "Warning",
  "rule": "created_files",
  "source": "syscall",
  "tags": [
    "create",
    "file",
    "write"
  ],
  "time": "2024-01-15T17:12:18.098829335Z",
  "output_fields": {
    "container.id": "22afeacb59b8",
    "container.name": null,
    "evt.arg.name": "/e123456",
    "evt.time": 1705338738098829335,
    "evt.type": "openat",
    "fd.name": "/e123456",
    "fs.path.name": "/e123456",
    "proc.cmdline": "touch e123456",
    "proc.name": "touch",
    "proc.pid": 83884,
    "proc.pname": "bash",
    "proc.ppid": 83831,
    "user.name": "root",
    "user.uid": 0
  }
}

If the file is not created in the container (created on the host) , then everything works as it should with an absolute path:

{
  "hostname": "victim",
  "output": "17:09:25.042825053: Warning file_3=/home/ubuntu/test_cf/w1234 user=<NA> uid=1000 process=touch pid=83692 parent=bash ppid=73475 command=touch w1234 file=/home/ubuntu/test_cf/w1234 file_2=/home/ubuntu/test_cf/w1234 syscall=openat  container_id=host container_name=host",
  "priority": "Warning",
  "rule": "created_files",
  "source": "syscall",
  "tags": [
    "create",
    "file",
    "write"
  ],
  "time": "2024-01-15T17:09:25.042825053Z",
  "output_fields": {
    "container.id": "host",
    "container.name": "host",
    "evt.arg.name": "/home/ubuntu/test_cf/w1234",
    "evt.time": 1705338565042825053,
    "evt.type": "openat",
    "fd.name": "/home/ubuntu/test_cf/w1234",
    "fs.path.name": "/home/ubuntu/test_cf/w1234",
    "proc.cmdline": "touch w1234",
    "proc.name": "touch",
    "proc.pid": 83692,
    "proc.pname": "bash",
    "proc.ppid": 73475,
    "user.name": "<NA>",
    "user.uid": 1000
  }
}

How can I always get the absolute path to the file?

Environment

  • Falco version: 0.36.2 (x86_64)
  • System info:
  • OS: Linux Ubuntu 22
@SerhiyProtsenko SerhiyProtsenko changed the title I expect an absolute path to the new file in but I get a relative path to the new file I expect an absolute path to the new file, but I get a relative path to the new file Jan 15, 2024
@Andreagit97 Andreagit97 modified the milestones: TBD, 0.38.0 Jan 16, 2024
@Andreagit97
Copy link
Member

Thank you for reporting! We will try to take a look ASAP!

@LucaGuerra
Copy link
Contributor

Have you tried evt.abspath? See the docs: https://falco.org/docs/reference/rules/supported-fields/

@fivlao
Copy link

fivlao commented Apr 5, 2024

@LucaGuerra Yes. We ran falco container and ran docker run -it archlinux bash and create file using command touch ss234 in it container

falco return alert with evt.abspath: /ss234
expected: /var/lib/docker/overlay2/b57cdc938ff457f7a9cf845b9319212f3ca38fa6d809142eb2cc7625ac75a5f7/diff/ss234
or: /var/lib/docker/overlay2/b57cdc938ff457f7a9cf845b9319212f3ca38fa6d809142eb2cc7625ac75a5f7/merged/ss234

Falco alert:

{
  "hostname": "humirova2",
  "output": "10:27:01.754891360: Warning fd_dev=3E fd_dev_major=0 fd_dev_minor=62 evt_abspath=/ss234 evt_abspath_src=/ss234 evt_abspath_dst=/ss234 user=root uid=0 user_loginuid=-1 process=touch executable=/usr/bin/touch pid=52122 parent=bash ppid=52084 sid=1 command=touch ss234 file=/ss234 syscall=openat container_id=2ea6a1cb02f1 container_name=<NA>",
  "priority": "Warning",
  "rule": "created_files",
  "source": "syscall",
  "tags": [
    "create",
    "file",
    "write"
  ],
  "time": "2024-04-05T10:27:01.754891360Z",
  "output_fields": {
    "container.id": "2ea6a1cb02f1",
    "container.name": null,
    "evt.abspath": "/ss234",
    "evt.abspath.dst": "/ss234",
    "evt.abspath.src": "/ss234",
    "evt.time": 1712312821754891360,
    "evt.type": "openat",
    "fd.dev": "3E",
    "fd.dev.major": 0,
    "fd.dev.minor": 62,
    "fs.path.name": "/ss234",
    "proc.cmdline": "touch ss234",
    "proc.exepath": "/usr/bin/touch",
    "proc.name": "touch",
    "proc.pid": 52122,
    "proc.pname": "bash",
    "proc.ppid": 52084,
    "proc.sid": 1,
    "user.loginuid": -1,
    "user.name": "root",
    "user.uid": 0
  }
}

Falco rule:

- macro: exclude_common_directories
  condition: (not fs.path.name startswith /proc) and
    (not fs.path.name startswith /sys) and
    (not fs.path.name startswith /run) and
    (not fs.path.name startswith /dev/shm/elb) and
    (not fs.path.name startswith /usr/local/elb) and
    (not fs.path.name startswith /usr/bin/node-agent/athena) and
    (not fs.path.name startswith /usr/bin/node-agent/ml-inference) and
    (not fs.path.name startswith /usr/bin/node-agent/sensor) and
    (not fs.path.name = /dev/null) and
    (not fs.path.name = /dev/kmsg) and
    (not fs.path.name startswith /var/log/journal)

- rule: created_files
  desc: Detect file operations indicating a completed download or file creation using fd.name.
  condition:
    evt.type in (openat, open, creat, openat2, open_by_handle_at) and  (evt.arg.flags contains O_CREAT or evt.arg.flags contains O_WRONLY or evt.arg.flags contains O_TRUNC or evt.arg.flags contains O_APP>
    not evt.arg.flags contains O_DIRECTORY and
    fd.typechar='f' and
    fd.num>=0 and
    exclude_common_directories
  output:
    fd_dev=%fd.dev
    fd_dev_major=%fd.dev.major
    fd_dev_minor=%fd.dev.minor
    evt_abspath=%evt.abspath
    evt_abspath_src=%evt.abspath.src
    evt_abspath_dst=%evt.abspath.dst
    user=%user.name
    uid=%user.uid
    user_loginuid=%user.loginuid
    process=%proc.name
    executable=%proc.exepath
    pid=%proc.pid
    parent=%proc.pname
    ppid=%proc.ppid
    sid=%proc.sid
    command=%proc.cmdline
    file=%fs.path.name
    syscall=%evt.type
    container_id=%container.id
    container_name=%container.name
  priority: WARNING
  tags: [file, write, create]

@LucaGuerra
Copy link
Contributor

Thanks, now I think I understand the request. Falco always considers the path inside the container and currently does not show any other paths (from any other mountpoints if any). This is what adopters normally want as it makes it easier to understand what is going on.

This AFAICT is not a feature that was ever planned; in order to better understand this what would be the use case? Is it just for inspecting where overlayfs of containers are mounted or for every potential chrooted and pivot_root environment?

@SerhiyProtsenko
Copy link
Author

The main idea using "rule": "created_files" we want to get absolute paths to all files that are created or modified. Next, we scan these files using Yara rules and hashes. This functionality is important because we are able to detect known malware and ransomware

@LucaGuerra
Copy link
Contributor

Got it. I believe that at this point it would be hard for Falco to retrieve absolute paths inside the underlying directories of an overlayfs for every access, mostly because we attempt to inspect overlay data only in very specific cases (is_exe_upper_layer) and Falco normally works by examining syscalls and their arguments and return values rather than hooking inside the filesystem implementation.

Among the things we want to work on in the future there are improvements for our container engine metadata, we can keep in mind and investigate if it will be doable.

However, I would like to offer a potential workaround for your specific use case because I may understand what you are trying to do. First of all, I believe that your created_files rule triggers upon successful file creation or opening with creation. Note that it can not tell you if the content is modified so if you want to run yara rules or hashing you may need to check after the file is closed. Once you have the path of the file and the container ID you can open the file by doing something like (if using Docker containers and as long as the container is alive):

$ sudo cat /proc/$(docker container inspect $CONTAINER_ID | jq '. [0].State.Pid')/$FILE_PATH_INSIDE_CONTAINER

You can get both the container ID and the file path from the Falco rule. You could also use the PID of the process that has triggered the rule or one of its ancestors inside the container but it may be risky because processes can be short lived.

Hope this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants