mirror of
https://github.com/affaan-m/ECC.git
synced 2026-11-07 16:45:53 +00:00
fix(gateguard): read the command line su runs, and unwrap taskset
`su postgres -c "psql -c 'drop table users'"` resolved to `su`, so the SQL-client check never saw psql. The value of su's -c/--command (or of a short-option cluster ending in c, as in -lc) is now scanned as a command line of its own, like the value of sh -c. The scan continues past `--`, since su hands the arguments after it to the target shell, which runs a -c there too. taskset joins the runners: its -c is a flag and the CPU mask is one positional, so `taskset -c 0 psql ...` resolves to psql.
This commit is contained in:
2 files changed
+32
No files matched your search
@@ -359,6 +359,25 @@ function quoteAwareSegments(input) {
|
||||
|
||||
const SHELL_WRAPPERS = new Set(['sh', 'bash', 'zsh', 'dash', 'ksh']);
|
||||
|
||||
/**
|
||||
* The command line `su` runs through the target user's shell: the value of
|
||||
* `-c`/`--command`, or of a short-option cluster ending in `c` (`-lc`). `su`
|
||||
* passes the arguments after `--` to that shell, which runs a `-c` there too,
|
||||
* so the scan does not stop at `--`.
|
||||
*
|
||||
* @param {string[]} tokens dequoted tokens for one segment
|
||||
* @param {number} start index of the `su` token
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function suCommandLine(tokens, start) {
|
||||
for (let i = start + 1; i < tokens.length; i += 1) {
|
||||
const arg = tokens[i];
|
||||
if (arg.startsWith('--command=')) return arg.slice('--command='.length);
|
||||
if (arg === '--command' || /^-[A-Za-z]*c$/.test(arg)) return i + 1 < tokens.length ? tokens[i + 1] : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL clients whose `-c`/`-e`/positional arguments carry SQL statements.
|
||||
* Quoted SQL (e.g. `psql -c "drop table users"`) is invisible to the
|
||||
@@ -432,6 +451,7 @@ const RUNNER_PREFIXES = {
|
||||
nohup: {},
|
||||
setsid: {},
|
||||
stdbuf: { valueOptions: ['-i', '-o', '-e', '--input', '--output', '--error'] },
|
||||
taskset: { positionals: 1 },
|
||||
time: { valueOptions: ['-f', '--format', '-o', '--output'] },
|
||||
timeout: { valueOptions: ['-s', '--signal', '-k', '--kill-after'], positionals: 1 }
|
||||
};
|
||||
@@ -616,6 +636,10 @@ function isDestructiveQuoteAware(raw, depth = 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (base === 'su') {
|
||||
const commandLine = suCommandLine(tokens, wi);
|
||||
if (commandLine && isDestructiveQuoteAware(commandLine, depth + 1)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1551,6 +1551,12 @@ function runTests() {
|
||||
expectDestructiveDeny('timeout 30 psql -c "drop table users"', 'timeout psql');
|
||||
expectDestructiveDeny('nohup mysql -e "delete from sessions"', 'nohup mysql');
|
||||
expectDestructiveDeny('sudo nice -n 5 timeout -s KILL 30 psql -c "drop table users"', 'stacked runners psql');
|
||||
expectDestructiveDeny('sudo su postgres -c "psql -c \'drop table users\'"', 'sudo su -c psql');
|
||||
expectDestructiveDeny('su - postgres -c "psql -c \'drop table users\'"', 'su - user -c psql');
|
||||
expectDestructiveDeny('su -lc "psql -c \'drop table users\'" postgres', 'su -lc psql');
|
||||
expectDestructiveDeny('su --command="psql -c \'drop table users\'" postgres', 'su --command= psql');
|
||||
expectDestructiveDeny('su postgres -- -c "psql -c \'drop table users\'"', 'su -c after --');
|
||||
expectDestructiveDeny('taskset -c 0 psql -c "drop table users"', 'taskset -c psql');
|
||||
})
|
||||
)
|
||||
passed++;
|
||||
@@ -1573,6 +1579,8 @@ function runTests() {
|
||||
expectAllow('bash -lc "psql -c \'select count(*) from users\'"', 'bash -lc select');
|
||||
expectAllow('nice -n 10 psql -c "select 1"', 'nice select');
|
||||
expectAllow('timeout 30 git status', 'timeout git status');
|
||||
expectAllow('su postgres -c "psql -c \'select 1\'"', 'su -c select');
|
||||
expectAllow('taskset -c 0 git status', 'taskset git status');
|
||||
expectAllow('env -S \'psql -c "select 1"\'', 'env -S select');
|
||||
expectAllow('env -S \'echo\' \'; psql -c "drop table users"\'', 'env -S echo with a literal argument');
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user