0xc0rvu5.github.io

View on GitHub

Debian Startup_Scripts

Scripts can be found at :

Below will be a technical overview of what the script does. Following this, I will explain in more detail what and why the script does what it does. Alright! Lets begin,

What it does:

1.sh
	- Updates system
	- Installs necessary packages
		- apt-transport-https curl wget git xclip mlocate vim-gtk3 terminator zsh fish \
		bat tldr

- Installs unecessary packages
	- toilet figlet cowsay fortune lolcat boxes

- Adds iptables ruleset and creates a copy at ../configs/iptables.sh

- Installs brave-browser
	- Adds files
		~ /usr/share/keyrings/brave-browser-archive-keyring.gpg 
	 	~ /etc/apt/sources.list.d/brave-browser-release.list

- Installs VSCode
	- Adds files
		~ /usr/share/keyrings/packages.microsoft.gpg
		~ /etc/apt/source.list.d/vscode.list

- Installs additional packages
	- libpam-tmpdir apt-listchanges debsums apt-show-versions sysstat auditd chkrootkit \
	rkhunter unhide fail2ban unattended-upgrades acct arpwatch shellcheck vlc xpad tor \
	sqlite3 sqlitebrowser python3-pip python3-virtualenv iptables-persistent

- Activates unattended-upgrades
	- Creates a local file for /etc/apt/apt.conf.d/50unattended-upgrades here:
		~ /etc/apt/apt.conf.d/52unattended-upgrades-local
	- Copies ../config/02periodic to:
		~ /etc/apt/apt.conf.d/02periodic

- Starts services on reboot:
	- arpwatch auditd fail2ban sysstat unattended-upgrades

- Disables services on reboot:
	- cups cups-browsed ufw

- Starts services immediately:
	- auditd fail2ban sysstat unattended-upgrades

- Disables services immediately:
	- cups cups-browsed ufw

- Adds a single arpwatch interface to monitor and adds ruleset to:
	~ /etc/arpwatch/your_interface.iface
		
	- Starts service on reboot and immediately after creating file

- Adds auditctl ruleset to:
	~ /etc/audit/rules.d/audit.rules 

- Adds banners to:
	~ /etc/motd
	~ /etc/issue
	~ /etc/issue.net

- Installs zsh/fish shell across all users
	- Based on choice:
		- For zsh installs:
			- oh-my-zsh
		- For fish installs:
			- oh-my-fish

2.sh
	- Installs rust
		- Installs rustscan
		- Installs feroxbuster

- Installs zsh/fish shell across all users
	- Based on choice:
		- For zsh installs:
			- oh-my-zsh
		- For fish installs:
			- oh-my-fish

3.sh
	- Updates `tldr` for root and any user(s) with the binary

- Creates directories at:
	~ /root/.local/bin
	~ /root/.local/share
	~ /root/.config/terminator
	~ /home/user/.local/bin
	~ /home/user/.config/terminator

- Creates files at:
	~ /root/.config/terminator/config
	~ /home/user/.config/terminator/config

- Creates syslinks for `batcat`:
	~ ln -s /usr/bin/batcat /root/.local/bin/bat
	~ ln -s /usr/bin/batcat /home/user/.local/bin/bat

	- If Distribution ID is `Debian`:
		~ ln -s /usr/bin/batcat /usr/local/bin/bat

- If the root and current user have a bash/zsh/fish shell then these paths will be appended to
utilize ~/.cargo/bin ~/.local/bin binaries:
	~ export PATH="$HOME/.local/bin:$PATH"
	~ export PATH="/home/user/.cargo/bin:$PATH"

- If the following files/directories are present in the root/user ~/ directories:
	~ ~/.bashrc
	~ ~/.oh-my-zsh
	~ ~/.config/fish

	- Create the relevant alias files for the user here:
		~ ~/.bash_aliases
		~ ~/.oh-my-zsh/custom/aliases.zsh
		~ ~/.config/fish/functions
		
Log file at:
	~ log
	
	- Color coated:
		- Blue:
			- Content of file configurations
			
		- Green:
			- Installed packages
			
		- Green Background:
			- Time stamps at the beginning and end of each script
			
		- Red:
			- System service changes
			
		- Yellow:
			- File configurations

1.sh

First off we’ll be updating the system. Generic Debian based system updates can be accomplished with: sudo apt autoclean -y; sudo apt update -y; sudo apt upgrade -y; sudo apt autoremove -y

This will update the system and ensure all packages are up-to-date. Depending on whether you installed a fresh ISO image alongside the amount of resources you have allotted to your machine will differentiate the time this step will take. Generally, with more that 4GB of ram and enough CPU core processors this will take a minute or two tops. If you have 4GB or less expect it to take quite some time.

After upgrading the system, in order to ensure the script runs without any issues we are going to want to install the necessary packages required for the script:

apt-transport-https curl wget git xclip mlocate vim-gtk3 terminator zsh fish bat tldr

Let’s break these down one by one:

These are some of my favorite packages. If you also enjoy these packages now or later don’t hesistate to reach out to me and determine other packages that I enjoy using. I am more than happy to share.

Moving on, next order of business would be the unnecessary packages that are installed during this script. I named the function within the script this because they are just that, unnecessary, but they do add some flare to the script! These packages will be listed below:

toilet figlet cowsay fortune lolcat boxes

These packages are strictly for aesthetics. These is nothing more uneventful than a script that has no ASCII art and text banners! Well, I suppose if works as expected then it doesn’t matter, but anyways moving on. These packages are all command line tools that can be used to create ASCII art and text banners.

Let’s also break these down one by one:

If someone really did not have the storage spaces for these packages then the function could easily be disabled by prepending a # prior to the function call within the updates function and this would ensure the unnecessary packages were not installed. This shouldn’t effect the script with the exception of some additional error messages and the lack of ASCII art and color within the script itself.

To put the package sizes into perspective I took a snapshot below of the following:

Keep in mind that if you are ever on a Linux system and want to utilize the power of both the man pages and grep without actually going into the file and typing /-f, for example, if you wanted to hone in on what -f flag was meant to do instead you can type:

man dpkg-query | grep -- -W

This will display in the terminal what the -W flag does.

Sometimes it may cut off a line or two of relevant information, if so run the following command to your desired needs:

man dpkg-query | grep -A 5 -B 5 -- -W

This time the output will display 5 lines above -A and 5 lines below -B the -W flag.

In the below photo we can see that there are roughly 1921 packages in a fresh Ubuntu 22.04 install. Furthermore, we see the smallest packages and the largest packages on the system. We also see where the previously mentions unnecessary packages fit on this spectrum. I wanted to illistrate that the packages really do not hog too much room on your filesystem, but nonetheless, I included a function that is presented on the main options menu which allows you to uninstall these packages with ease. If all else failed, you can reference the log file which has the packages listed together and a simple sudo apt remove --purge with the list of the unnecessary packages following would remove them.

image

Next up would be the installation of Brave and VSCode.

These are relatively straight-forward. I personally enjoy using Brave after using it explicitly when following Michael Taggart’s PWST (Practical Web Application Security and Testing) course on the TCM Security platform. If you are into that kind of stuff I highly recommend the course, 10/10, from someone with a general good understanding of web application testing after running through the 200 something modules on Portswigger.

VSCode is a wonderful tool if you are into coding/programming. It is my preferred tool of choice due the high level of granularity or the level of detail and control it provides over different aspects of the development process.

The script adds the following files post installation:

~ /usr/share/keyrings/brave-browser-archive-keyring.gpg 
~ /etc/apt/sources.list.d/brave-browser-release.list
~ /usr/share/keyrings/packages.microsoft.gpg
~ /etc/apt/source.list.d/vscode.list

Once the following gpg keys are properly integrated into the system:

Alongside the repositories:

The packages will be included whenever your system is updated. If an update or security patch is passed along within the repository you will have it immediately versus, say, directly installed the code binary. I included the locations of where the files are located in the log file in case the full removal of either of the packages are required. If so, I recommend deleting each file as there will be no purpose to have the repository pulling updates if there is no package(s) to update.

The last set of packages installed within this script are contained within the additional_packages function. These packages include:

libpam-tmpdir apt-listchanges debsums apt-show-versions sysstat auditd chkrootkit rkhunter unhide fail2ban unattended-upgrades acct arpwatch shellcheck vlc xpad tor sqlite3 sqlitebrowser python3-pip python3-virtualenv iptables-persistent

If you want a description of a package and don’t want to use your GoogleFu skills you can always run:

apt show libpam-tmpdir

Though the list is lengthy compared to the other two let’s break them down:

These are packages I find to be useful hence the reason I included them within the script. I will go into more detail on some of these packages within this blog post. I may create an additional post which goes into much more detail on the purposes and use cases of each individual package. The packages I will cover today within this blog post include unattended-upgrades, arpwatch, auditd, fail2ban, rkhunter and unhide.

Let’s get started!

unattended-upgrades

File #1 created for unattended-upgrades:

File #2 will be located in the /configs directory:

// Control parameters for cron jobs by /etc/cron.daily/apt-compat //

// Enable the update/upgrade script (0=disable)
APT::Periodic::Enable "1";

// Do "apt-get update" automatically every n-days (0=disable)
APT::Periodic::Update-Package-Lists "1";

// Do "apt-get upgrade --download-only" every n-days (0=disable)
APT::Periodic::Download-Upgradeable-Packages "1";

// Run the "unattended-upgrade" security upgrade script
// every n-days (0=disabled)
// Requires the package "unattended-upgrades" and will write
// a log in /var/log/unattended-upgrades
APT::Periodic::Unattended-Upgrade "1";

// Do "apt-get autoclean" every n-days (0=disable)
APT::Periodic::AutocleanInterval "21";

// Send report mail to root
//     0:  no report             (or null string)
//     1:  progress report       (actually any string)
//     2:  + command outputs     (remove -qq, remove 2>/dev/null, add -d)
//     3:  + trace on
APT::Periodic::Verbose "2";

If for some reason the previous file mentioned is excluded then unattended-upgrades will not automatically start. If this is the case, where /etc/apt/apt.conf.d/52unattended-upgrades-local is present, but /etc/apt/apt.conf.d/02periodic is not then I recommend running the following command:

This will output: image

Within the script I included the non-interactive way of accomplishing this:

echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections
dpkg-reconfigure -f noninteractive unattended-upgrades

The above code was added for safe-keeping. I say this because when we add /etc/apt/apt.conf.d/02periodic we automatically initiate unattended-upgrades with the exception of actually enabling the service on reboot. We will do that in the service section. I will attach a link that explains unatteded-upgrades in more detail if you are interested.

Services

In order to use various packages installed we will need to ensure they are enabled on reboot. The following packages will be enabled on reboot within the script:

arpwatch auditd fail2ban sysstat unattended-upgrades

To enable the packages on reboot we will use the systemctl command. Here is an example:

sudo systemctl enable arpwatch

We will disable various services on reboot:

cups cups-browsed ufw

Arpwatch

In order to monitor any changes to our IP or MAC address we will dynamically update the interface to watch. Here is the code to accomplish this:

conn=$(ip -4 -o a | cut -d ' ' -f 2,7 | cut -d '/' -f 1 | awk '{print $1}' | tail -1)

Here the command is step-by-step in visual form:

Now keep in mind this will grab all the current interfaces on your system and take the last interface. I did this to avoid the loop-back interface i.e. lo. If you have a vpn on it will take the VPN interface tun0 or whatever it may be so keep that in mind. Alternatively, you can use the following code:

ip -br -c a | grep -i up | awk '{print $1}'

Here the command is step-by-step in visual form: image

Shout-out to Matt Kiely the creator of PMAT (Practical Malware Analysis & Triage) for TCM Security. If it wasn’t for following him on one of his videos (outside of the PMAT) then I wouldn’t have this lovely highlighted ip syntax to use.

For some strange reason when I used the above code it would include the interface, but what seemed to be ASCII colors that were merging with the interface name. Back to the focus, that being the added dynamic arpwatch interface. A file will be added to:

Following this file creation the service for your_interface will be enabled on reboot and the service will start immediately. Here is an example:

systemctl daemon-reload
systemctl enable arpwatch@enp0s3
systemctl start arpwatch@enp0s3

Verify the service is active:

ps aux | grep arp

Locate the relevant log files here:

In my example the log file will be located here: /var/lib/arpwatch/enp0s3.dat

Here is a reference and a more in-depth guide:

Auditd

Persistent audit rules will be added to:

Upon reboot these rules will be active within your auditctl list. You can verify with:

sudo auditctl -l

To investigate the audit logs for a certain file use ausearch:

sudo ausearch -i -k gshadow_access

For a more comprehensive list of rules I recommend: [[https://www.daemon.be/maarten/auditd.html]]

Grub Password Related

A simple backup is created for the following file:

The sole purpose of this backup is in the off-chance you decide to put a password on your grub boot-loader. I recommend having this backup file. I won’t go into details on this process, but you can find more information in the below link.

Fail2ban

A copy of the fail2ban jail configuration file occurs within the script:

 cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

If this isn’t done you may have issues with fail2ban actually starting. After it is complete and the service is enabled expect a basic setup with no other than a sshd jail. Note, that if you use ssh on a separate port you will need to configure the configuration files accordingly. I may cover that another time. Here is an example of an active fail2ban service: image

Rkhunter and Unhide

In the script /etc/rkhunter.conf will have 3 lines changed. On line #107:

Following this change rkhunter will update if there are available updates using the following command:

sudo rkhunter --update

This command will be ran within the script followed by:

sudo rkhunter --propupd

This sets a baseline of your system. Ideally, this should be performed prior to the system being online, but this does not happen within the script. This will remove many of the initial false positives that are present due to binary changes over time.

unhide gives more functionality to rkhunter and should be treated as an extension of it.

Updatedb

updatedb will be initiated which will update the current database within your file-system. Later if you want to search something on your system you can run:

locate random_file

This will search your entire file-system and output anything that has the input string random_file.

Finally, within the cleanup function there will be the last package installs. I put these here since needrestart would periodically inform you that you need to restart your system. Also, debsecan was added for safe-keeping on the off-chance there was some user input required. If you are automating system maintenance I don’t see any harm in installing these towards the end to avoid the burdensome user input queries.

Let’s break down these two packages:

Banners

Banners are added to the following files:

If you sign into your device via ssh take notice of the banner being displayed. It will look like this:

+----------------------------------------------------+
  | This is a controlled access system. The activities |
  | on this system are monitored.                      |
  | Evidence of unauthorised activities may be         |
  | disclosed to the appropriate authorities.          |
  +----------------------------------------------------+

Zsh or Fish

To end off 1.sh the user will be asked whether they want a zsh or fish shell. Once a selection is made all users whether it be root or any user with a /home directory will have their shells changed.

If zsh is selected:

If fish is selected”

  ~~ Installing oh-my-fish ~~
  
 ~~ Upon completion of oh-my-fish run ~~
 
 ~ omf install bobthefish
 
 ~~ If xclip is installed use SHIFT + CTRL + V ~~ 

Make sure you run:

Alternatively, you can chose any of the other fish and oh-my-fish themes.

2.sh

This script will not be ran as root. The reasoning behind this is to ensure the user has access to the rust binaries located at ~/.cargo/bin without the need to prepend sudo to the rust binary.

Rust

If rust is not installed it will be installed. If rustscan is not installed it will be installed. If feroxbuster is not installed it will be installed.

Rustscan is an extremely fast port scanner. When using HackTheBox or TryHackMe I always make sure I run this prior to the more in depth nmap scans that follow.

Feroxbuster is a go to subdomain discovery tool!

Zsh or Fish

To end off 1.sh the user will be asked whether they want a zsh or fish shell. Once a selection is made all users whether it be root or any user with a /home directory will have their shells changed.

If zsh is selected:

If fish is selected”

  ~~ Installing oh-my-fish ~~
  
 ~~ Upon completion of oh-my-fish run ~~
 
 ~ omf install bobthefish
 
 ~~ If xclip is installed use SHIFT + CTRL + V ~~ 

Make sure you run:

Alternatively, you can chose any of the other fish and oh-my-fish themes.

3.sh

~/.local/bin

First off, the following directory will be created:

The purpose of this directory is to store local binaries. In our case this is where we will store the symbolic bat binary we will get to here in a moment. For some strange reason the bat installation is installed as batcat. I find this mildly irritating not to be able to use it out-of-the-box as is, but nothing like a quick fix to solve the problem! If the binary batcat exists on the file-system a symbolic link will be created to point the batcat binary to ~/.local/bin/bat like so:

ln -s /usr/bin/batcat ~/.local/bin/bat

The ~ representing the home directory of the current user. In the actual script is will be written as the absolute path:

ln -s /usr/bin/batcat /home/user/.local/bin/bat
ln -s /usr/bin/batcat /root/.local/bin/bat

If the following files/directories are present:

If the ~/.bashrc and/or ~/.zshrc files are present the following content will be appended to them:

export PATH="${HOME}/.local/bin:${PATH}"

If the directory ~/.config/fish is present then the following will be appended to the ~/.config/fish/config.fish file:

set -x PATH $PATH $HOME/.local/bin

This will allow for the ~/.local/bin binaries to be accessible to the current shell whether it be bash/zsh/fish.

Alternatively, for fish you can manually set paths with the following command:

fish_add_path ~/.local/bin

Tldr

If tldr is present on the current system then a directory for root will be created at:

After this update is complete feel free to type in tldr followed by any command/binary. This is one of my favorite tools! Check it out in action: image

tldr is extremely useful for quick command references!

~/.cargo/bin

Since rust should be installed at this point if the following files/directories are present:

If the ~/.bashrc and/or ~/.zshrc files are present the following content will be appended to them:

export PATH="${HOME}/.cargo/bin:${PATH}"

If the directory ~/.config/fish is present then the following will be appended to the ~/.config/fish/config.fish file:

set -x PATH $PATH $HOME/.cargo/bin

This will allow for the ~/.cargo/bin binaries to be accessible to the current shell whether it be bash/zsh/fish. Take note of the user binaries being available to root. This allows for the user to use the rust binaries without sudo, root to have access to the binaries and only a single install of rust. Here is what the root ~/.config/fish/config.fish file will look like: image

Additionally, you can manually add them with fish_add_path like so: image

image

This is a super convenient way to add paths! Keep in mind that if your paths are located in ~/.config/fish/config.fish then the paths will be accessible in the shell, but they will not be visible when you run echo $fish_user_paths.

Test out tldr to determine what nl is accomplishing in the previous screenshot. Here is a hint 😉: image

Terminator Configurations

Similar to the previous directory installation of ~/.local/bin if the ~/.config/terminator directory is not currently present on the file-system then it will be created based off of the same criteria:

Once there is a ~/.config/terminator directory the configuration file located within the /configs directory of the GitHub repository will be added. The following file structures will be created based off of the /configs/terminatorconfigs file:

~/.config/terminator/config

I included the configurations I use for laptop settings at:

Aliases

To finish things off right all alias files will be dynamically updated. I incorporated two files with generic aliases that I commonly use. Once script 3.sh is ran then you will have access to these aliases. Bear in mind that in order to add the alias files automatically you need to have previously opted in to selecting the zsh shell, fish shell and/or both. Alternatively, you can find the alias files in the /aliases directory and manually run them this way to get their respective files which will dynamically update the alias files to include whatever the current active user’s name is. To find out you can run:

echo $USER

image

Checkout the GitHub repository for some example output of the aliases!

Now this long and arduous blog post is complete!

Happy hacking!