Malicious scripts: cron, bash programming, brute-forcing
Welcome back to my 10th iteration of this blog series. In this series we’re growing our cybersecurity knowledge starting from the very basics using the overthewire.org challenges as a guide. First, I’d like to thank everyone for their feedback based on the last post! I’ll do my best to implement it and as always, more feedback is always welcome. Now let’s start!
Picking up where we left off with bandit21, we’re told to look at the cron job scheduler. So what is cron? Cron and crontab are unix job schedulers: you can set jobs to start at certain times or events. The power of cron lies in its simplicity in that it is essentially a script that executes. Because it’s a script, we can essentially set it to do anything that we can do through the CLI (which is practically everything).
So let’s start by checking the directory:

There’s a few in there but given that we’re aiming to get into bandit22, let’s take a look at the relevant one:

In this cron job, we see that there’s two very similar commands. The first one is pretty easy to understand the timing off “@reboot”. But what do the asterisks mean? The asterisks are wild cards for “all” (as we’ve seen before with regex) and the positions of them represent times at which this job should run. They syntax for assigning the times is “every minutes:hours:day of the month:month:day of the week”. For example, if the assignment was 00 * * * * it would mean that the job would run at every “00” minutes of every hour, of every day, of every month, of every day of the week; essentially hourly. In our case, the script will run every minute.
Notice the “&> /dev/null”? Last week we figured out that the & runs a job in the background, and we already know that “> /dev/null” silences a program’s output. So let’s take a look at the script that the cron script is executing:

Well, this is nice! The password is simply being saved in another directory. Could we have perhaps read this from bandit0 and skipped all the way here? The script creates the directory and sets its permissions to 644 which would mean read and write for the owner, read for the group, and read for everyone. We can double-check this:

Although the read permissions for this file are open to everyone, reading the script that creates is only accessible to bandit22 and bandit21. As such, given the non-descriptive file name, it would have been quite the challenge to find this file (again coupled with the read permissions of the tmp directory).
Moving on to bandit22, we’re directed once again to examine the cron configurations. Let’s examine the cronjob_bandit23.sh file and the script it points to:

Can you figure out what the script does? We’ve been working with most of the commands used in this script so it should look familiar. This is our first interaction with a program so let’s take a minute to break things down. Programs are a set of instructions that the computer can understand to perform a certain function or set of functions. In fact, every command we’ve issued to shell in the CLI has been a program; those programs are usually stored in the /bin directory. Programming or coding is the process of figuring out the necessary logic behind a task that needs to be accomplished and then writing it out in a language that the computer can understand. bash is an implementation of shell along with dash and zsh and all use the same or very similar syntax.
A program that is written in bash syntax is essentially a prewritten sequence of commands. We can very simply take each line and write into the CLI and we’d get the same response as if we ran the prewritten script. Starting at the top of the script, the “#!/bin/bash” specifies to the machine where the program that can understand this file is located. Running the script is essentially starting the program located at /bin/bash and then feeding it the lines in the script in order of top to bottom. Since the script is written for bash and we’re already running bash, we can just manually run the same commands.
Before we do that let’s try to understand what the script is doing first, this is very basic reverse engineering. The program starts with the 3rd line of the file at “myname=$(whoami)”. In bash, assigning variables is as simple as giving it a name and setting it as equal to whatever value you want. The “$” is also part of the syntax and refers to another variable, in this case, “(whoami)”. This line is then setting the variable of “myname” to be equal to the value of “(whoami)”. whoami is a bash command and if we run it, it’ll tell us what user we are and we’re bandit22. The parenthesis around “whoami” works in the same way as it does in PEMDAS for math. The computer will first evaluate what whoami is before doing anything else. Thus, myname would be equal to the name of the user who runs the script.
The 4th line of the script is setting another variable called “mytarget”. Once again we see the “$” and parenthesis enclosing a command. Reading through it, the command is echoing “I am user” followed by the value stored in the variable of “myname”, piping the result to md5sum and piping that again to cut. Notice here that “myname” is not enclosed in parenthesis. This tells the computer that “myname” is a simple variable and it just needs to remember what is stored inside of it without further evaluation. Beyond this the script announces what it’s doing and then copies the password of the user running the script to the file by the name assigned to the variable stored in “mytarget”.
Given that this a cron job that runs every minute, the file with the password is already in existence and we just need to figure out what it’s called. We can go through the whole file and follow it exactly to find the output where it tells us “Copying passwordfile …. to …”. Or we can just take the line that actually generates the name of the file and echo that back to us:

There it is. On to the next.
Again it’s a cronjob:

This script looks much more complex and is our first exposure (in these challenges) to programming loops and conditional statements. First things first, let’s break it down: it’s a bash program like the previous one, it uses the same “myname” variable, and then supposedly executes all scripts it finds in the /var/spool/$myname directory. Give that it executes scripts as bandit24, we can write a script that copies bandit24’s password into a file that we know the location of; we’re using the same method that was done in the previous level. In fact, we can use that same script from the previous level to achieve this objective, but where is the fun in that? Let’s write our own, it’ll be a script anyway.
Let’s first determine what it is that we need to do by writing it out, this is called pseudocode:
First, we need to create a file or directory that we can write the password in and we should know the name of this file and directory. Then we need to copy the password into that file and directory.
Let’s start a text editor, nano is an easy one to use but vim is great too:

The “#” sign is called a comment, the computer will pretend that everyting after the # is empty and will not try to read or execute any commands beyond it. It’s good practice to use comments to mark your code and make it easy for others (or future you) to decipher and understand what things do. Our code is very simple, so let’s save it (ctrl+O in nano then ctrl+x to exit or :wq in vim) and copy it into /var/spool/bandit24 (since that’s the one we’re trying to get into, we want bandit24 to execute it), then check our directory for the password:

Voila! Our first script successfully was written and executed. Keep in mind that since we’ve abused a “normal” task on the machine to gain access to it, we’ve essentially written a program that would classify as malware.
For this level, the difficulty has risen sharply: we have to crack a 4 digit pin. We can just sit at the keyboard and manually send every single one of the 10,000 combinations but we can automate that in a script. First, we need to understand how the server will respond to us:

Alright, so it works as the hint said it would and it maintains the connection if we get the pin combination wrong. At this point, I recommend looking up a quick introduction to programming languages and specifically bash if you’re not at all familiar.
Now we just have to write a script to do the guessing for us, again I’ll use nano:

Following our pseudocode, our script does exactly that. I like bash’s human readbility: it’ll start at 1 (since we already tried 0000) and execute that code for every digit including 9999. So our program will “do” “echo <bandit24’s password> <pin of our current attempt>”. This is called a “for loop” and is a way to repeat a code execution a certain number of times. For loops allow you to use its own internal way of counting as well by using the variable you specify to it. In our case, we are using “i”. The part that follows with “ if then” is called conditional statements. They execute only if the condition specified is met. In our case, I’m telling the code that if the numerical value of our pin is less than 1000, we need to add a 0 to the front of it to make sure we have 4 digits to send. It’s important to note that code execution is top to bottom and in the case of conditionals, the order is very important. Since if statements will stop checking as soon as one condition is met, we need to order the conditionals in an incremental way.
Now let’s run our code by passing it to nc and storing the output in a file to keep things manageable (it’ll “hang” for a few seconds while it processes):

Success! Did you notice how quickly the computer tried the possible combinations? As computers get faster and better, security keys will also need to get longer and more difficult to “guess”. This method of “guessing” by trying every single combination is called the brute force method. As an extra challenge for yourself, try modifying your code to tell you the correct pin code (if you haven’t done that already).
Although coding and programming are not a particular requirement for cybersecurity, a familiarity with the fundamentals of coding is necessary. In most cases, malware is obfuscated and it is rarely as simple as just reading the source code to figure out how it works and defend against it.
We explored brute-forcing today and we saw how fast it is to guess 4 digit passwords. This time it takes to guess gets longer the more combinations become possible and the longer the passwords are. Still, if a malicious actor is motivated or well funded enough they’ll put together computing resources to crack more difficult passwords. The real protection lies in using multifactor authentication and attempt lockouts. They are not foolproof, however, and there are examples of bypassing lockouts and MFA. In the words of the wise, “a breach is inevitable” but we can mitigate the damage.