csvtool
csvtool processes CSV files; its call action invokes a command for rows. If sudo delegates unrestricted execution of the binary as root, that callback inherits root. The report demonstrates this permission mistake.
Establish the delegation
id
sudo -l
csvtool --help
Read the exact executable path, allowed arguments, run-as identity and password requirement. A rule restricted to a safe operation does not imply permission to use every subcommand.
Demonstrate with a bounded command
Create a local one-row fixture:
printf 'alpha,beta\n' > lab.csv
csvtool call '/usr/bin/id' lab.csv
# Only where sudo -l allows this binary and action as root:
sudo /usr/bin/csvtool call '/usr/bin/id' lab.csv
The first call establishes ordinary execution; the second establishes the elevated identity. A shell that prints text successfully is not sufficient evidence: compare the reported UID.
Success: a permitted callback reports UID 0. Prefer this short proof over an interactive shell. Restrict the delegated operation and its arguments or replace it with a purpose-built task. Record the rule and command output, then remove the fixture. This is a sudo configuration problem; csvtool need not have a memory-corruption vulnerability.
Understand the callback boundary
call is an intended command-execution feature. Its callback is interpreted through a shell and receives CSV fields as arguments. Even if the input file is harmless, delegating the callback command to an untrusted user delegates execution as the run-as identity.
printf 'first,second\nthird,fourth\n' > lab-two-rows.csv
csvtool call '/usr/bin/id' lab-two-rows.csv
Multiple rows can invoke the callback repeatedly. Keep an identity proof to one row to avoid making repeated changes if a callback later does more than print its identity.
Read sudo rules precisely
| Rule detail | Consequence |
|---|---|
(root) | Permitted command runs as root |
(backup) | Command runs as the backup identity unless another identity is allowed |
NOPASSWD | Sudo does not require a password for that allowed command |
| Absolute executable path | Use that path; a same-named binary is not equivalent |
| Arguments or command regex | Determine whether call is actually permitted |
| Wildcards | May match more argument strings than the author intended |
command -v csvtool
ls -l /usr/bin/csvtool
sudo -l
The executable being readable is expected. The relevant finding is permission to run its command callback under a stronger identity. If the rule grants only a fixed col or head operation, the unrestricted call example does not establish an allowed path.
Minimal reproducible comparison
printf 'alpha,beta\n' > lab.csv
/usr/bin/csvtool call '/usr/bin/id' lab.csv > ordinary-identity.txt
sudo /usr/bin/csvtool call '/usr/bin/id' lab.csv > delegated-identity.txt
cat ordinary-identity.txt delegated-identity.txt
Use the explicit run-as option only if the rule grants that identity, for example sudo -u backup /usr/bin/csvtool .... Record real and effective UID where they differ. A password prompt followed by rejection indicates the delegation was not successfully exercised.
Failure and remediation
| Symptom | Check |
|---|---|
Unknown call action | Which csvtool implementation/version is installed |
| Fixture cannot be opened | File path and read permission under the run-as identity |
| Sudo rejects arguments | Exact rule, executable and argument constraints |
| Output shows your original UID | Whether sudo ran and which run-as identity was selected |
Remove the fixture after recording the result. Replace an unrestricted parser grant with a fixed task that validates its inputs and cannot select a callback command. Changing the CSV file’s permissions alone does not fix a rule that already permits arbitrary callbacks. See Privilege Escalation for other sudo delegates.
Related learning
How attacks work. Examples use fictional lab values; replace placeholders only with values from the system you are testing.