⚠️ Important security notice
Be careful when writing regexes. Try to ensure no malicious input could be injected in your regexes. It's better if your actions are direct commands, and not inline shell scripts.
If you use products of regexes in shell scripts, double-check that all user input is correctly escaped. Make use of tools like shellcheck to analyze your code.
Avoid using this kind of commands that mix code and user input:
['sh', '-c', 'mycommand <pattern>']
Example of a configuration permitting remote execution:
insecure.jsonnet
{
patterns: {
user: {
regex: @'.*',
},
},
streams: {
myservice: {
cmd: ['tail', '-f', '/tmp/reaction-example'],
filters: {
myfilter: {
regex: [
@'Connection of <user> failed',
],
// [...]
actions: {
myaction: {
cmd: ['sh', '-c', 'echo "<user>"'],
},
},
},
},
},
},
}
Let's launch reaction in one terminal:
$ touch /tmp/reaction-example
$ reaction start -c insecure.jsonnet
Then let's append malicious data to the tail
ed file in another terminal:
$ echo 'Connection of "; mkdir malicious-directory" failed' >> /tmp/reaction-example
We simulated an attacker supplying "; mkdir malicious-directory"
as a username in a random service
which doesn't check for non-alphanumeric characters in its usernames.
reaction will then launch the command:
myaction: {
cmd: ['sh', '-c', 'echo "<user>"'],
},
Substituting <user>
with the malicious input:
['sh', '-c', 'echo ""; mkdir malicious-directory""']
Of course, here it's a mkdir
but it can be anything.
IP pattern
Starting with reaction v2.2.0, patterns of type ip
, can be specified. The regex is provided by reaction and is guaranteed to contain only those characters: 0123456789.:
.
Those characters have no special meaning in sh
, so having an sh -c ... <ip>
should be safe.
Example
Let's take a common example: Appending a line to a file.
Problematic command
actions: {
problematic: {
cmd: [ 'sh', '-c', 'echo "<name>" >> /tmp/file' ],
},
}
actions:
problematic:
cmd: [ 'sh', '-c', 'echo "<name>" >> /tmp/file' ]
Bash solution
actions: {
bash: {
cmd: [ 'sh', '/append.sh', '<name>' ],
},
}
actions:
bash:
cmd: [ 'sh', '/append.sh', '<name>' ]
/append.sh
:
echo "$1" >> /tmp/file
Python inline solution
Python supports inline scripts separated from user input.
actions: {
python: {
cmd: [
'python',
'-c',
'import sys; open("/tmp/file", "a+").write(sys.argv[1] + "\n")',
'<name>'
],
},
}
actions:
python:
cmd:
- 'python'
- '-c'
- 'import sys; open("/tmp/file", "a+").write(sys.argv[1] + "\n")'
- '<name>'
Summary
Regexes are powerful, and need to be carefully written. Avoid having too permissive regexes capturing user input.
When executing scripts in actions, code and user input must be clearly separated.
Save scripts in files and call them
['bash', '/path/to/script', 'arg1', '...']
instead of having inline
['bash', '-c', 'command arg1 && command arg2']
when dealing with user input.