Disable Spesific Linux Command using Shellfirm

· 6 min read
Disable Spesific Linux Command using Shellfirm

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.

GroupEnabled By Default
basetrue
gittrue
fstrue
fs-strictfalse
kubernetesfalse
kubernetes-strictfalse
herokufalse
terraformfalse

Installation

  1. 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

  1. 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

  1. 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.

  1. 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

Reference

GitHub - kaplanelad/shellfirm: Intercept any risky patterns (default or defined by you) and prompt you a small challenge for double verification
Intercept any risky patterns (default or defined by you) and prompt you a small challenge for double verification - GitHub - kaplanelad/shellfirm: Intercept any risky patterns (default or defined b...