Fedora Account System
Red Hat Associate
Red Hat Customer
Overview ======== An unprivileged local user can supply a custom incron configuration to the setuid-root /usr/bin/incrontab program. Although incrontab prints: "insufficient privileges to use custom configuration (will use default)" it does not actually reset the configuration path to the default. It proceeds to load the attacker-controlled configuration. By making the user-table path a symbolic link to a root-owned file, incrontab follows the link while running with effective UID 0, writes the supplied table through it, and then calls chown() on the resulting path. This gives us an arbitrary root-file overwrite primitive. I demonstrated local privilege escalation by targeting /etc/passwd. This works on the stock Fedora ISO installed into a qemu VM with the only change being the installation of incron, SELinux was left enabled. * Fedora release 45 (Forty Five) * incron-0.5.12-30.fc45.x86_64 * selinux-policy-targeted-45.23-1.fc45.noarch * selinux-policy-45.23-1.fc45.noarch Root cause ========== In ict-main.cpp, the config option is initialized to the system configuration: std::string cfg(INCRON_CONFIG); When -f/--config is supplied, AppArgs::GetOption() replaces cfg with the attacker-provided path. For a non-root real UID, the code only prints a warning: if (uid != 0) { fprintf(stderr, "insufficient privileges to use custom configuration " "(will use default)\n"); } It does not return an error and does not restore cfg to INCRON_CONFIG. IncronCfg::Load(cfg) consequently loads the attacker-provided file. The attacker-controlled user_table_dir is later used to construct the output path in copy_from_file(). The setuid process saves the table to that path and then performs: chown(out.c_str(), ppwd->pw_uid, -1) Both operations follow a symbolic link placed at the attacker-selected output path. Reproducible: Always Steps to Reproduce: Reproduction ============ As root 1. Install incron. As an ordinary user: 1. Create an attacker-owned directory containing a spool directory. 2. Create a custom configuration setting user_table_dir to that spool directory and allowed_users to an attacker-controlled allow file. 3. Add the current username to the allow file. 4. Create a symbolic link named after the current user inside the spool directory, pointing to /etc/passwd. 5. Execute /usr/bin/incrontab -f ATTACKER_CONFIG TABLE_FILE Despite reporting that the custom configuration cannot be used, incrontab loads it. /etc/passwd is overwritten through the symbolic link and its owner is changed to the attacking user's UID. --- Details of PoC/steps to reproduce: mkdir /tmp/repro mkdir /tmp/repro/spool ln -s /etc/passwd /tmp/repro/spool/riv /tmp/repro/config: user_table_dir = /tmp/repro/spool allowed_users = /tmp/repro/allow /tmp/repro/allow: riv /tmp/repro/table riv:x:1001:1001::/home/riv:/bin/bash 1 placeholder /usr/bin/incrontab -f /tmp/repro/config /tmp/repro/table Expected Results: If the software is launched by a low privilege user, it should not be able to overwrite arbitrary files.