This post is more like a note to myself, but this may help if you are looking at How Disable Spesific Linux Command using Shellfirm.
Question: How to prevent a given user from being able to run a specific command?
This technique uses Shellfirm to prevent unwanted access.
About
Intercept any risky patterns (default or defined by you) and prompt you a small challenge for double verification.
How does it Work?
shellfirm
will evaluate all the shell commands behind the scenes. If a risky pattern is detected, you will immediately get a prompt with the relevant warning to verify your command.
Risky commands
The predefined a baseline of risky groups command that will be enabled by default, these are risky commands that might be destructive.
Group | Enabled By Default |
---|---|
base | true |
git | true |
fs | true |
fs-strict | false |
kubernetes | false |
kubernetes-strict | false |
heroku | false |
terraform | false |
Installation
- Clone Git Repository
sudo apt install make cargo git -y
git clone https://github.com/kaplanelad/shellfirm.git
cd shellfirm
2. Build Shellfirm
sudo make build
sudo mv target/debug/shellfirm /usr/local/bin/
3. Add to Shell (Bash)
For every user that use Shellfirm, login and exec :
# Download bash-preexec hook functions.
curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
# Source our file at the end of our bash profile (e.g. ~/.bashrc, ~/.profile, or ~/.bash_profile)
echo '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' >> ~/.bashrc
# Download shellfirm pre-exec function
curl https://raw.githubusercontent.com/kaplanelad/shellfirm/main/shell-plugins/shellfirm.plugin.sh -o ~/.shellfirm-plugin.sh
# Load pre-exec command on shell initialized
echo 'source ~/.shellfirm-plugin.sh' >> ~/.bashrc
If using Shell other than Bash, we can follow docs: https://github.com/kaplanelad/shellfirm/tree/v0.2.6#setup-your-shell
4. Create settings directory
For every user that use Shellfirm, login and exec :
mkdir ~/.shellfirm
source ~/.bashrc
shellfirm-config
--output--
Manage app config
USAGE:
shellfirm config [SUBCOMMAND]
OPTIONS:
-h, --help Print help information
SUBCOMMANDS:
challenge Reset configuration
deny Deny command pattern
help Print this message or the help of the given subcommand(s)
ignore Ignore command pattern
reset Reset configuration
update-groups enable check group
5. Verify using risky command
shellfirm
will intercept any risky patterns and immediately prompt a small challenge that will double verify your action, think of it as a captcha for your terminal.
git reset --hard
#######################
# RISKY COMMAND FOUND #
#######################
* This command going to reset all your local changes.
Solve the challenge:: 8 + 7 = ? ^C to cancel
Change Challenge
- Change the Challenge
shellfirm config challenge
? change shellfirm challenge ›
Math
Enter
❯ Yes
✔ change shellfirm challenge · Yes
2. Verify
sudo rm -rf /
#######################
# RISKY COMMAND FOUND #
#######################
* You are going to delete everything in the path.
Type `yes` to continue ^C to cancel
Deny Commands
- Deny the command Patterns
shellfirm config deny
? select checks (Press <space> to select, <a> to toggle all, <i> to invert selection)
2. Verify
sudo reboot
##################
# COMMAND DENIED #
##################
* You are going to reboot your machine.
The command is not allowed. type ^C to cancel
Create Custom Command Patterns
Command patterns are built in Shellfirm binary file so in order to create new/custom commands, we need to compile our own Shellfirm binary file.
- Create new group & patterns
To create new pattern, we need to add new group to shellfirm/shellfirm/checks/
then add our new command regex into it. Different command pattern should be grouped separately.
Templates:
- from: "Group name, same with file name"
test: "Regular Expression for command"
description: "Command description to display"
id: "id/label, must be unique per command"
For Example, I want to create pattern commands for Openstack
vim shellfirm/shellfirm/checks/openstack.yaml
---
- from: openstack
test: \s*openstack\s*compute\s*agent\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Compute Agent in OpenStack"
id: openstack:delete_compute_agent
- from: openstack
test: \s*openstack\s*compute\s*service\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Compute Service in OpenStack"
id: openstack:delete_compute_service
- from: openstack
test: \s*openstack\s*project\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Project in OpenStack"
id: openstack:delete_project
- from: openstack
test: \s*openstack\s*network\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Network or Network Agent in OpenStack"
id: openstack:delete_network
- from: openstack
test: \s*openstack\s*network\s*agent\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Network or Network Agent in OpenStack"
id: openstack:delete_network_agent
- from: openstack
test: \s*openstack\s*subnet\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Subnet in OpenStack"
id: openstack:delete_subnet
- from: openstack
test: \s*openstack\s*user\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge User in OpenStack"
id: openstack:delete_user
- from: openstack
test: \s*openstack\s*floating\s*ip\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Floatin IP in OpenStack"
id: openstack:delete_floating_ip
- from: openstack
test: \s*openstack\s*volume\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Volume in OpenStack"
id: openstack:delete_volume
- from: openstack
test: \s*openstack\s*security\s*group\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Security Group in OpenStack"
id: openstack:delete_security_group
- from: openstack
test: \s*openstack\s*security\s*group\s*rule\s*(delete|unset|remove|purge)\s*
description: "You are going to delete/unset/remove/purge Security Group Rule in OpenStack"
id: openstack:delete_security_group_rule
- from: openstack
test: \s*openstack\s*server\s*(delete|lock|pause|reboot|rebuild|remove|stop|suspend|unset)\s*
description: "You are going to delete/lock/pause/reboot/rebuild/remove/stop/suspend/unset Server in OpenStack"
id: openstack:server_command
2. Create test file
Create a test file for every command pattern available
cd ~/shellfirm/shellfirm/tests/checks/
Filename format: group-pattern_id.yaml
Content of test files :
- test: command to test
description: description about test
Example for openstack-server_command.yaml
- test: openstack server delete
description: delete instance
- test: sudo openstack server delete
description: match command
- test: sudo openstack server delete
description: match command
Execute test
cd ~/shellfirm
# Install Cargo Insta
cargo install cargo-insta --locked
export PATH=$PATH:~/.cargo/bin
# Create new snapshot for all test
cargo insta test
# Update & verify new snapshot created
cargo insta review
# Running test
cargo test
After test completed without error, we can proceed to build the binary file.
3. Build New Shellfirm Binary File
cd ~/shellfirm
make build
sudo mv target/debug/shellfirm /usr/local/bin/
4. Verify Shellfirm Update
shellfirm --version
shellfirm config reset
shellfirm config update-groups
--output--
? select checks (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ terraform
❯ ✔ openstack
✔ kubernetes-strict
✔ git-strict
✔ fs-strict
✔ heroku
✔ kubernetes
✔ base
✔ fs
✔ git
New groups for new command patterns appear
5. Operational Test
openstack server list
+--------------------------------------+----------------------------------+--------+------------------------------------+--------------+-----------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+----------------------------------+--------+------------------------------------+--------------+-----------+
| 6db53ecd-f99e-4faf-88f5-96ff1df691e5 | cirros-test | ACTIVE | int-net=10.0.0.74 | Cirros-0.6.0 | m1.small |
+--------------------------------------+----------------------------------+--------+------------------------------------+--------------+-----------+
openstack server delete cirros-test
#######################
# RISKY COMMAND FOUND #
#######################
* You are going to delete/lock/pause/reboot/rebuild/remove/stop/suspend/unset Server in OpenStack
Solve the challenge:: 4 + 3 = ? ^C to cancel
Deny the command
shellfirm config deny
? select checks (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ base:bash_fork_bomb
✔ base:delete_all_cron_tasks
✔ base:execute_all_history_commands
✔ base:reboot_machine
✔ base:shutdown_machine
✔ openstack:delete_compute_agent
✔ openstack:delete_compute_service
✔ openstack:delete_project
✔ openstack:delete_network
✔ openstack:delete_network_agent
✔ openstack:delete_subnet
✔ openstack:delete_user
✔ openstack:delete_floating_ip
✔ openstack:delete_volume
✔ openstack:delete_security_group
✔ openstack:delete_security_group_rule
❯ ✔ openstack:server_command
✔ git:reset
✔ git:delete_all
✔ fs:recursively_delete
✔ fs:move_to_dev_null
✔ fs:flush_file_content
✔ fs:recursively_chmod
✔ fs:delete_find_files
Verify Command
openstack server delete cirros-test
##################
# COMMAND DENIED #
##################
* You are going to delete/lock/pause/reboot/rebuild/remove/stop/suspend/unset Server in OpenStack
The command is not allowed. type ^C to cancel