Home Learn Linux Bash security tips: securing your scripts and preventing vulnerabilities

Bash security tips: securing your scripts and preventing vulnerabilities

Learn how to secure your Bash scripts and prevent vulnerabilities with these practical Bash security tips. From updating to the latest Bash version to securely storing credentials, follow these best practices to keep your Bash scripts secure and reliable.

by Arun Kumar
securing your bash scripts

Bash scripting can be a powerful tool for automating tasks and managing system configurations. However, when writing Bash scripts, it’s important to consider the potential security risks that come with this power. Without proper security measures, your scripts could become vulnerable to malicious attacks that could compromise your system or data.

In this article, we’ll explore some of the essential Bash security tips to help you secure your scripts and prevent vulnerabilities. These tips include updating to the latest Bash version, using the “set -e” option, sanitizing input, using trusted sources, setting the PATH variable carefully, using double quotes, using variables for commands, and securely storing credentials. By following these best practices, you can ensure that your Bash scripts are secure and reliable, and that they perform the tasks you need them to without exposing your system to unnecessary risks.

Securing your scripts and preventing vulnerabilities

1. Keep your scripts up to date

Keeping your Bash scripts up to date is an important security practice that can help protect against known vulnerabilities. As new security issues are identified and fixed, updated versions of Bash and related packages are released, and it’s important to ensure that you’re running the latest versions to reduce your risk of being exploited.

To check the version of Bash that you’re currently running, you can use the following command in your terminal on Ubuntu:

bash --version
fetch bash version

Fetch Bash version

This will display the version of Bash that you’re currently running. You can then compare this to the latest version available to see if you’re running the most up-to-date version. Alternatively, you can check the latest version of Bash available for your Ubuntu system by running the following command in your terminal:

apt-cache policy bash
checking bash latest version and installed version

Checking Bash latest version and installed version

This command will display the currently installed version of Bash, as well as the latest version available from the Ubuntu package repository.

To update Bash on Debian-based Linux distros, you can use the built-in package manager, apt. First, update the package manager:

sudo apt update

Then, upgrade the Bash package:

sudo apt upgrade bash

This will download and install the latest version of the Bash package. You may be prompted to confirm that you want to install the updated package and to enter your password to confirm your permissions.

It’s also a good idea to regularly check for updates to other packages that your Bash scripts depend on, such as libraries or other utilities. You can do this by running the following command:

sudo apt update && sudo apt upgrade

This will update all of the packages on your system to the latest versions available.

In addition to keeping your Bash scripts up to date, it’s important to ensure that any Bash scripts that you write are compatible with the latest version of Bash. This can be done by testing your scripts on a system running the latest version of Bash before deploying them to your production environment. By keeping your Bash scripts up to date and testing them thoroughly, you can help prevent vulnerabilities and ensure that your scripts are secure.

2. Use strong passwords

Using strong passwords is an important security practice for any system that requires authentication. If your Bash scripts require users to log in or authenticate in some way, it’s important to ensure that strong passwords are being used to reduce the risk of unauthorized access.

One way to generate strong passwords on Ubuntu is to use the built-in pwgen command. pwgen is a command-line utility that can generate random, secure passwords.

To install pwgen, open a terminal and run the following command:

sudo apt-get update && sudo apt-get install pwgen
installing password generator utility

Installing Password Generator Utility

Once pwgen is installed, you can use it to generate a new password by running the following command:

pwgen -s 16 1
using password generator utility

Using Password Generator Utility

This will generate a 16-character password with a mix of letters, numbers, and symbols. You can adjust the length of the password by changing the number after the -s option.

To use this password for a user account on Ubuntu, you can run the following command:

sudo passwd [username]

Replace [username] with the username for the account that you want to set the password for. You will be prompted to enter the new password twice to confirm.

It’s important to remind users to choose strong passwords and to change them regularly to reduce the risk of unauthorized access. Additionally, consider implementing additional security measures, such as two-factor authentication or password policies, to further enhance the security of your system.

3. Sanitize input

Sanitizing input is an important security practice for any programming language, including Bash. It involves checking user input to ensure that it is safe and does not contain any malicious code that could be executed on the system.

In Bash, it’s important to sanitize user input when writing scripts that accept user input, such as scripts that process user-provided filenames, passwords, or other sensitive data.

To sanitize user input, you should validate it and filter out any characters or commands that could be used to execute malicious code. One way to do this is to use regular expressions to match only known good input patterns.

For example, let’s say you have a Bash script that prompts the user to enter a filename and then performs some operation on that file. To sanitize the user input and prevent potential code injection attacks, you could use the following code to validate the input:

#!/bin/bash

# Prompt the user for a filename
read -p "Enter the filename: " filename

# Sanitize the input using a regular expression
if [[ $filename =~ ^[a-zA-Z0-9_./-]+$ ]]; then
# The input is valid, perform some operation on the file
echo "Performing operation on file: $filename"
else
# The input is invalid, exit the script with an error message
echo "Invalid filename: $filename"
exit 1
fi

In this example, the regular expression ^[a-zA-Z0-9_./-]+$ is used to match only alphanumeric characters, underscores, slashes, dots, and hyphens. This allows the user to enter filenames with standard characters without allowing any special characters that could be used to inject malicious code into the script.

By validating and filtering user input, you can help prevent code injection attacks and keep your Bash scripts secure. It’s important to be careful when processing user input, especially when that input is used to execute commands or perform operations on sensitive data.

4. Use the “set -e” option

Using the set -e option is a simple but effective way to improve the security of your Bash scripts. This option tells Bash to exit immediately if any command in the script fails, making it easier to catch and fix errors that could lead to security vulnerabilities.

When the set -e option is enabled, Bash will terminate the script as soon as any command returns a non-zero exit code. This means that if a command fails, the script will stop running, preventing any further commands from executing.

To enable the set -e option in your Bash script, simply add the following line to the top of your script:

#!/bin/bash
set -e

With this line added, any command that returns a non-zero exit code will cause the script to immediately terminate.

Here’s an example of how this option can improve the security of a Bash script. Consider the following script, which downloads a file from a remote server and then extracts the contents:

#!/bin/bash

# Download the file
wget http://example.com/file.tar.gz

# Extract the contents of the file
tar -zxvf file.tar.gz

# Remove the downloaded file
rm file.tar.gz

While this script may work as intended under normal circumstances, it is vulnerable to failure and potential security risks. For example, if the wget command fails to download the file, the script will still try to extract and remove the non-existent file, which could lead to unintended consequences.

However, by enabling the set -e option, the script can be made more secure and reliable. Here is the updated script with the set -e option enabled:

#!/bin/bash
set -e

# Download the file
wget http://example.com/file.tar.gz

# Extract the contents of the file
tar -zxvf file.tar.gz

# Remove the downloaded file
rm file.tar.gz

With this change, if the wget command fails to download the file, the script will immediately terminate without attempting to extract or remove the file. This can prevent unintended consequences and make the script more reliable and secure.

5. Limit access

Restricting permissions for your Bash scripts is an important security practice that can help prevent unauthorized access and reduce the risk of malicious activities. By limiting who can execute, read, or write to a file, you can help protect sensitive information and prevent attackers from modifying your scripts.

In Ubuntu, file permissions are managed using a set of three numbers that represent the permissions for the owner, group, and other users. Each number represents a set of three permissions: read, write, and execute. The numbers are added up to give the final permission value.

For example, a file with permissions of 755 would give the owner read, write, and execute permissions, while group and other users would have only read and execute permissions.

To view the permissions for a file, you can use the ls command with the -l option, like this:

ls -l [filename]

This will display the permissions for the specified file.

viewing file permissions of fosslinux.sh file

Viewing File Permissions of fosslinux.sh file

To change the permissions for a file, you can use the chmod command, like this:

chmod [permission] [filename]

Replace [permission] with the desired permission value, and [filename] with the name of the file you want to change the permissions for.

For example, to give only the owner execute permissions on a script file called fosslinux.sh, you could run the following command:

chmod 700 fosslinux.sh

This would set the permission to rwx—— for the owner and no permissions for group and other users.

It’s also a good idea to run your Bash scripts with the lowest possible privileges. This means running your scripts as a non-privileged user, rather than as the root user. If your scripts require elevated privileges, consider using sudo to grant temporary privileges only for the necessary parts of the script.

For example, if you need to run a Bash script as a privileged user on Ubuntu, you can use the following command:

sudo ./fosslinux.sh

This will run the fosslinux.sh script with root privileges.

By carefully managing file permissions and running your Bash scripts with the lowest possible privileges, you can help prevent unauthorized access and reduce the risk of malicious activities.

6. Use trusted sources

Using trusted sources is an important security practice that can help prevent the introduction of malicious code into your Bash scripts. When writing Bash scripts, it’s important to use trusted sources for any external code or resources that are used in the script.

A trusted source is a website or repository that is known to provide reliable and secure code. For example, the official Ubuntu repositories are a trusted source for Ubuntu users because they are maintained by the Ubuntu community and are regularly checked for security vulnerabilities.

When using external code or resources in your Bash scripts, it’s important to ensure that they come from a trusted source.

Here are some best practices to follow when using external code or resources in your scripts:

  • Use official repositories: Whenever possible, use official repositories to install software or packages. For example, on Ubuntu, you can use the apt command to install packages from the official Ubuntu repositories.
  • Verify checksums: When downloading files from the internet, verify the checksums to ensure that the files have not been modified or tampered with. Checksums are unique values that are generated from the original file, and can be used to verify that the file has not been modified.
  • Use HTTPS: When downloading files or resources from the internet, use HTTPS to ensure that the data is encrypted and secure. HTTPS is a secure protocol that encrypts data in transit and can help prevent malicious actors from intercepting or modifying the data.

7. Set the PATH variable carefully

The PATH variable is an environment variable that specifies the directories that the shell searches when looking for commands or programs. When writing Bash scripts, it’s important to set the PATH variable carefully to prevent the execution of potentially malicious commands.

By default, the PATH variable includes several directories, such as /bin, /usr/bin, and /usr/local/bin. When a command is entered into the terminal or a script, the shell searches these directories (in order) for the command or program to execute. If a program or command with the same name as a malicious command is located in one of these directories, it could be executed instead.

To prevent the execution of potentially malicious commands, it’s important to set the PATH variable carefully in your Bash scripts.

Here are some best practices to follow when setting the PATH variable:

  • Avoid adding directories to the PATH variable that are not necessary for your script to function.
  • Use absolute paths when specifying directories in the PATH variable. This ensures that the shell searches only the specified directory and not any subdirectories.
  • If you need to add a directory to the PATH variable, consider adding it temporarily for the duration of the script and removing it when the script is finished.

8. Use double quotes

When writing Bash scripts, it’s important to use double quotes around variables and command substitutions. This helps prevent errors and vulnerabilities that can arise from unexpected word splitting and globbing.

Word splitting is the process by which the shell separates a string into separate words based on spaces, tabs, and other delimiters. Globbing is the process by which the shell expands wildcard characters like * and ? into a list of matching files in the current directory.

If a variable or command substitution is not enclosed in double quotes, the resulting string may be subject to word splitting and globbing, which can lead to unexpected and potentially dangerous behavior. For example, consider the following script:

#!/bin/bash
set -e

MY_VAR="Hello FOSSLinux!"
echo $MY_VAR

In this script, the variable MY_VAR is assigned the value “Hello FOSSLinux!”. When the echo command is executed, the variable is not enclosed in double quotes. As a result, the shell performs word splitting on the string “Hello FOSSLinux!” and treats it as two separate arguments, resulting in the output:

using bash profile my var alias

Using Bash Profile MY_VAR alias

Hello FOSSLinux!

If Hello and FOSSLinux! were separate commands, this could have serious security implications. To prevent this, you should always enclose variables and command substitutions in double quotes.

9. Use variables for commands

In Bash scripting, it’s a good practice to use variables to store commands instead of hard-coding them directly into your script. This helps make your code more readable and maintainable, and can also help prevent security vulnerabilities.

Using variables for commands makes it easier to update or change the command later, without having to find and modify it in multiple places in your script. It can also help prevent errors and vulnerabilities that can arise from executing commands with user input or untrusted data.

Here’s an example of using variables for commands in a Bash script:

#!/bin/bash
set -e

# Set the command to be executed
CMD="ls -l /var/log"

# Run the command
$CMD

In this example, the CMD variable is used to store the command that will be executed. Instead of typing the command directly into the script, it is stored in the variable for easier modification later. The ls -l /var/log command will list the files in the /var/log directory in a detailed format.

By using a variable for the command, we can easily change the command later, without having to modify it in multiple places in our script. For example, if we decide to list the contents of a different directory, we can simply modify the CMD variable to reflect the new command:

CMD="ls -l /home/user"

10. Securely store credentials

If your Bash scripts require credentials, it’s important to store them securely. Never store credentials in plaintext within your scripts, as they can be easily accessed by attackers. Instead, consider using environment variables or a secure key store to store your credentials.

Conclusion

The tips we covered include updating to the latest Bash version, using the “set -e” option to detect errors, sanitizing input to prevent malicious code injection, using trusted sources for software and libraries, setting the PATH variable carefully to avoid unintended command execution, using double quotes to prevent word splitting and globbing, using variables instead of hard-coding commands, and securely storing credentials.

These tips are just the starting point, and there may be other security considerations that are specific to your environment or use case. However, by following these best practices, you can help to ensure that your Bash scripts are secure and reliable, and that they perform the tasks you need them to without exposing your system to unnecessary risks.

You may also like

1 comment

Uwe Filbrandt February 23, 2023 - 9:27 AM

Example of point 4. (set -e)
#!/bin/bash
# Download the file
wget http://example.com/file.tar.gz
# Extract the contents of the file
tar -zxvf file.tar.gz
# Remove the downloaded file
rm file.tar.gz

Is not very realistic, because the tar, as well as the rm command are very trustful!
If they don’t find their input, they never perform “unintended” activities! Thay just give an error message and that’s it.
But you could suggest (like I would do):
if [ -e file.tar.gz ]; then
# Extract the contents of the file
tar -zxvf file.tar.gz
# Remove the downloaded file
rm file.tar.gz
else
echo “Failed to download file ‘file.tar.gz’, exit now …”
exit (or return something)
fi

Reply

Leave a Comment

fl_logo_v3_footer

ENHANCE YOUR LINUX EXPERIENCE.



FOSS Linux is a leading resource for Linux enthusiasts and professionals alike. With a focus on providing the best Linux tutorials, open-source apps, news, and reviews written by team of expert authors. FOSS Linux is the go-to source for all things Linux.

Whether you’re a beginner or an experienced user, FOSS Linux has something for everyone.

Follow Us

Subscribe

©2016-2023 FOSS LINUX

A PART OF VIBRANT LEAF MEDIA COMPANY.

ALL RIGHTS RESERVED.

“Linux” is the registered trademark by Linus Torvalds in the U.S. and other countries.