Sysadmin bread and butter

 Publ .

 Mins 18 (3687 words).

 Edit .

Sysadmin bread and butter

The next few levels take a dive into two essential tools that every aspiring system administrator must master. System Daemons and Shell scripting.

Daemons are not Demons. A peek to the etymology of both words reveals that their meaning is orthogonal. A Demon is an evil personality, whereas a Daemon is some sort of angel guardian that helps form the character of the people he assists. For our context, it is worthwhile to understand that a system daemon is a process that runs in the background, sometimes even outside of the control of the user. Most daemons come alive at init, a system Script which executes as the last step of the kernel boot sequence. They are specialized programs that take care of very specific tasks in order to keep the OS running smoothly.

Scripts are … well, you guessed it! Scripts! They can be totally though of as analogs to a writing or a document for a play. As any play, scripts must be interpreted by an artist. For bash scripts, the performer is the shell. It is worth noting that the shell is, in addition to an insulating layer between the operating system and the kernel, a fairly powerful programming language. A shell program or script is a tool that we can use to build applications.
They make possible to leverage virtually all system commands, utilities and tools. Scripts offer a point of entry to automate many tasks.

We should mention that on Level 2 we were pointed to an extensive guide regarding Scripts. The document is very detailed, keeping it at hand for future references may be a good idea.

Index


LEVEL 21 -> LEVEL 22

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

Commands you may need to solve this level
cron, crontab, crontab(5) (use man 5 crontab to access this)

You have to deal with a program that is described as the classic sysadmin tool. cron is used mostly for automation of tasks. But in combination with scripts, programs and some imagination the possible uses are endless.

After a thoroughly inspection of the manuals, you should learn that cron is a software utility that executes scheduled tasks. It runs as a daemon and is started automatically as a service by init.d.

The scheduled tasks driving this daemon are stored in files. They are located by default in /var/spool/cron/crontabs but they are not intended to be edited directly. crontab is the program that should be used to manage these files. Users may have their own individual cron tables, and there is often a global table located at /etc for system administrator’s management. As you have been prompted, look inside the directory /etc/cron.d. Is in this folder is where cronjobs are waiting to be called and executed by the system daemon cron.

The d letter aims to avoid confusion, since there can possibly be a file named /etc/cron as system-wide crontab. In this particular system there is such a file but its called /etc/crontab. There is in this file a detailed explanation of the common syntax that is used to define jobs.

$ cat /etc/crontab 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

In the directory you’ve been told to inspect, there are several cronjobs, from various users. Some appear to be related to different levels of the game, while others seem non-game-related.

$ ls /etc/cron.d/
cronjob_bandit15_root  cronjob_bandit23       e2scrub_all            sysstat
cronjob_bandit17_root  cronjob_bandit24       otw-tmp-dir
cronjob_bandit22       cronjob_bandit25_root  .placeholder

The file that should be of our interest is cronjob_bandit22.

$ cat /etc/cron.d/cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null

Comparing this output to the description in /etc/crontab is easy to infer that there is a script running at system reboot but also at every minute. >& is an unknown construct. It is a redirection operator that sends both stdout(the output) and stderr(any message errors that may occur) of the command executed to the null device, to make its output ‘disappear’.

The next logical step is to check the contents of the script that is being executed.

$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

Lets look at this script statement by statement:

  • #!/bin/bash

The first line is a Shebang, its purpose is telling the system that this file is composed of a set of commands that need to be fed to the command interpreter indicated. All scripts start with a shebang.

  • chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

This runs the program chmod to change access permission of the file t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv. It gives the owner write/read access and read permission to group/others.

  • cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

The last line redirects the content of the file containing the password for level 22 to the file the on /tmp.

Given the permissions the script set on this file, you should be able to get the password for the next level by reading it:

$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
WdDozAdTM2z9DiFEQ2mGlwngMfj4EZff

LEVEL 22 -> LEVEL 23

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

NOTE: Looking at shell scripts written by other people is a very useful skill. The script for this level is intentionally made easy to read. If you are having problems understanding what it does, try executing it to see the debug information it prints.

Commands you may need to solve this level
cron, crontab, crontab(5) (use man 5 crontab to access this)

In similar fashion to the previous level, you deal with an automated task.

$ cat /etc/cron.d/cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null

Again, ou have a script running at system reboot and at every minute, redirecting file descriptors 1 and 2 to the null device. Let’s look at the contents of the script to work out its purpose.

$ cat /usr/bin/cronjob_bandit23.sh
#!/bin/bash

myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)

echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"

cat /etc/bandit_pass/$myname > /tmp/$mytarget

Given the procedural nature of scripts, they should be analyzed carefully. You need to understand each and every statement precisely. You might test the commands on the terminal, read the manpages for them, perform web searches, etc. You never should move from a line until you fully understand its meaning.

  • Shebang
    Pointing the system to feed this file to the bash interpreter.

  • Variable declaration and assignment
    myname should hold the contents of the output of the command whoami, the string bandit23.

  • Variable declaration and assignment
    mytarget holds the output of the echo command. This string is the result of piping the literal "I am user bandit23" to md5sum. This calculates a cryptographic checksum. The resulting checksum is piped to cut. All contents after the first occurrence of a blank space are discarded.

  • Print
    echo prints the given arguments, all variables that are preceded by the dollar sign are expanded and show its literal content. $myname gets replaced by bandit23, and $mytarget the checksum previously calculated.

  • Concatenation
    cat concatenates the contents of the password for the next level, which is stored in /etc/bandit_pass/bandit23 and redirects it to the file /tmp/$mytarget.

All this given, the only thing your are left to do to is to find out is the name of the file that contains our password. Let’s run the command on the left hand side of $mytarget with the same parameters as in the script:

echo "I am user bandit23" | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349

Finally, read the contents of the file in /tmp/ that goes by that name:

$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
QYw0Y2aiA672PsMmh9puTQuhoz8SyR2G

LEVEL 23 -> LEVEL 24

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

NOTE: This level requires you to create your own first shell-script. This is a very big step and you should be proud of yourself when you beat this level! NOTE 2: Keep in mind that your shell script is removed once executed, so you may want to keep a copy around…

Commands you may need to solve this level
cron, crontab, crontab(5) (use man 5 crontab to access this)

You have at hand a system automated task, let’s firs check the command being executed:

$ cat /etc/cron.d/cronjob_bandit24
@reboot bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
* * * * * bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null

A script is being executed at every minute and at reboot. Its output is redirected to the null device as in the previous level. A logical first step is executing the script to see its output. There are several ways to run a script on the terminal, one of them is specifying the full path of the executable, the system will take care of calling an interpreter to run it.

$ /usr/bin/cronjob_bandit24.sh
/usr/bin/cronjob_bandit24.sh: line 5: cd: /var/spool/bandit23/foo: No such file or directory
Executing and deleting all scripts in /var/spool/bandit23/foo:
Handling *
stat: cannot statx './*': No such file or directory
Handling .bash_logout
rm: cannot remove './.bash_logout': Permission denied
Handling .bashrc
rm: cannot remove './.bashrc': Permission denied
Handling .profile
rm: cannot remove './.profile': Permission denied

This program appears to be deleting all script located in the folder /var/spool/bandit23/foo. The rest of the output seems to be some error messages from the rm program. Let’s fully analyze its procedure line by line:

 1#!/bin/bash
 2
 3myname=$(whoami)
 4
 5cd /var/spool/$myname/foo
 6echo "Executing and deleting all scripts in /var/spool/$myname/foo:"
 7for i in * .*;
 8do
 9    if [ "$i" != "." -a "$i" != ".." ];
10    then
11        echo "Handling $i"
12        owner="$(stat --format "%U" ./$i)"
13        if [ "${owner}" = "bandit23" ]; then
14            timeout -s 9 60 ./$i
15        fi
16        rm -f ./$i
17    fi
18done
  • Shebang Point the system to feed this file to the bash interpreter.

  • Variable declaration and assignment myname holds the contents of the output of the command whoami, which is the user name of whoever executes the script. This is verifiable by observing our execution of the file.

    Executing and deleting all scripts in /var/spool/_bandit23_/foo was the first line because you are user bandit23. If this is correct, the variable should hold bandit24 when cron runs the script.

  • Change directory Move prompt to /var/spool/$myname/foo. The variable myname is preceded by a dollar sign, so it gets expanded to its literal meaning. Thus the command changes the current working directory to cd /var/spool/bandit24/foo.

  • For loop
    This is the main control structure of the script. A loop is a block of code that iterates a list of commands as long as the control condition is true.
    The syntax of the loop is composed of several keywords, and the statements that may be executed are those indented and placed between the keywords do and done.

    The general syntax for declaring a for loop is:
    for argument in [list] do statements done. The list this script’s’ loop is going to iterate over is the expansion of the wildcard * .* which represents all files in the current folder. For each iteration the argument i will get assigned the element of the list that is being iterated over.

  • If statement Another flow control statement, its general syntax is: if condition then statements fi. The block of code between the keywords then and fi is executed when condition evaluates to true.

    The condition is the string between square brackets. It is composed of two statements united by the logical AND operator -a. Both operations are of the form e1 != e2, which evaluates to true if and only if expression-1 is not equal to expression-2.

    Thus the whole condition is true only if both != comparisons evaluate to true. Finally, you should also bear in mind that the dollar sign expands the variables to the values they hold and that all string between double quotes preserve they literal values.

    Given this facts, the condition evaluation in plain english is if the name of the file we are iterating over is neither . (dot) nor .. (dot dot) then.

  • echo
    Print the given argument.

  • Variable declaration and assignment
    owner holds the output of the command stat --format "%U" ./$i. Because $i gets expanded to some filename under each iteration of the for loop, stat evaluates to a string that is the username of the owner of the file.

  • If statement
    the inner comparison operation e1 = e2 asserts that the variable owner holds the string literal “bandit23”.

  • timeout
    Run a command with a time limit. Run the file to which the variable i expands to for at most 60 seconds. -s 9 means send signal 9 after timeout. Also named SIGKILL, signal 9 is a type of communication used by the system to indicate that a process and its running threads must be terminated right away. This may be the layout of the command for safety reasons, or to stop execution of infinite loops. This file seems to be intended to run a script that we will craft right away.

  • rm
    Remove the the variable i expands to.

In summary, the script that cron runs will execute for at most sixty seconds all scripts owned by user bandit23 that are located in the folder /var/spool/bandit24/foo deleting them afterwards.

You should write a script to make user bandit24 copy the contents of the password file stored in /etc to a location where our permissions allow access.

Let’s make a temporary folder and touch two files. One for our script, giving it the necessary permissions for execution and another with open permssions, where bandit24 will store our password.

mkdir /var/tmp/foobarbaz
touch script.sh lvl24pass.txt
chmod +x script.sh
chmod 666 lvl24pass.txt

Now write our script with a text editor. nano and vim are available on the server, these are the contents of script.sh:

#!/bin/bash
cat /etc/bandit_pass/bandit24 >> /var/tmp/foobarbaz/lvl24pass.txt

Finally, you should copy the script file to the target location and wait a few seconds until cron picks it up and executes it.

$ cp /var/tmp/foobarbaz/script.sh /var/spool/bandit24/foo/
$ sleep 60; cat lvl24pass.txt
[1]+  Done                    sleep 60
VAfGXJ1PBSsPSnvsjI8p759leLZ9GGar

LEVEL 24 -> LEVEL 25

A daemon is listening on port 30002 and will give you the password for bandit25 if given the password for bandit24 and a secret numeric 4-digit pincode. There is no way to retrieve the pincode except by going through all of the 10000 combinations, called brute-forcing.

You do not need to create new connections each time.

By leveraging previously learned concepts you should be able to overcome this challenge.

First let’s analyze the behavior of the daemon, connecting to the specified port using netcat, and typing input to test it.

$ nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
input
Fail! You did not supply enough data. Try again.
this_string_should_be_the_password 1234
Wrong! Please enter the correct pincode. Try again.
this_string_should_be_the_password 0000
Wrong! Please enter the correct pincode. Try again.

Let’s use a for loop on the shell to generate a file containing all possible input combinations.

$ mkdir /tmp/foobarbaz
$ cd /tmp/foobarbaz
$ for i in {0..9999}; do echo "VAfGXJ1PBSsPSnvsjI8p759leLZ9GGar $i" >> pincodes; done

Now run nc using our pincodes file as input and writing the response to another file.

$ nc localhost 30002 < pincodes >> output

The output file should contain a line with the password for the next level.

$ tail output
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Correct!
The password of user bandit25 is p7TaowMYrmu23Ol8hiZh9UvD0O9hpx8d

Exiting

LEVEL 25 -> LEVEL 26

Logging in to bandit26 from bandit25 should be fairly easy… The shell for user bandit26 is not /bin/bash, but something else. Find out what it is, how it works and how to break out of it.

Commands you may need to solve this level
ssh, cat, more, vi, ls, id, pwd

First inspect the home folder using ls

$ ls
bandit26.sshkey

If using this keyfile to login as user bandit26, you are immediately kicked out of the server.

$ ssh -i bandit26.sshkey bandit26@localhost -p 2220
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
....
....
  Enjoy your stay!

  _                     _ _ _   ___   __  
 | |                   | (_) | |__ \ / /  
 | |__   __ _ _ __   __| |_| |_   ) / /_  
 | '_ \ / _` | '_ \ / _` | | __| / / '_ \ 
 | |_) | (_| | | | | (_| | | |_ / /| (_) |
 |_.__/ \__,_|_| |_|\__,_|_|\__|____\___/
Connection to localhost closed.

How to find out user bandit26’s current shell? A web search yields a list of methods that may help. Many of the commands suggested only output the shell of the current user. But there is a mention of the existence of a plain text file containing user account information. The location is /etc/passwd/. man 5 passwd will help you better comprehend the structure and purpose of the file.

Concatenation of the contents of it and the yields an output that is quite long. By piping it through grep you catch only the information regarding user bandit26.

$ cat /etc/passwd | grep bandit26
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext

As the manual describes, the line has seven fields delimited by colons. The last field is the user’s command interpreter. Let’s proceed by exploring the contents of the file that is specified as shell for user bandit26.

$ cat /usr/bin/showtext 
#!/bin/sh

export TERM=linux

exec more ~/text.txt
exit 0

It is a simple script executing in place of the default shell spawning. The interpreter the script uses is sh. The line export TERM= modifies the default terminal emulator to linux. Then it executes the command more (a primitive pager) on the file ~/text.txt. Finally, the script finishes execution with exit 0, terminating our connection.

You have to find a way to avoid the script executing its final line. The manual page for the more program describes it as a filter for paging one screenful at a time. This means more should not exit if the data it has to show is large enough to not fit in one screen. You do not have permissions to modify the file text.txt, but you can make your screen smaller. This should trigger the script to ‘hang’ on more, before reaching exit.

Using the screen terminal multiplexer locally, first create one more region to allow resizing using C-a S. Then shrink our current region to 6 lines with C-a :resize -v 6 and re run the ssh login command:

  _                     _ _ _   ___   __  
 | |                   | (_) | |__ \ / /  
 | |__   __ _ _ __   __| |_| |_   ) / /_  
 | '_ \ / _` | '_ \ / _` | | __| / / '_ \ 
--More--(66%)

Now you are logged in as user bandit26 but are not in a command interpreter yet, you are inside the program more. Lets enlarge our window to its default size issuing C-a :resize -v 20.

In man more you find a list of interactive commands. The command v starts the default editor at the current line. When pressing v, vim spans for edition of the current file.

A web search helps at figuring out that the command :shell or :sh can be used inside the editor to spawn a shell within vim itself. But issuing the command does not work!

The problem is that the default shell for vim is also /usr/bin/showtext. You might check this with :set shell?.
Let’s change it to bash!

After issuing :set shell=/bin/bash, :sh spawns a shell for user bandit26.

:sh
bandit26@bandit:~$

You are now able to read the password for the level on the default server location:

bandit26@bandit:~$ cat /etc/bandit_pass/bandit26
c7GvcKlw9mC7aUQaPx7nwFstuAIBw1o1

LEVEL 26 -> LEVEL 27

Good job getting a shell! Now hurry and grab the password for bandit27!

Commands you may need to solve this level
ls

Listing the files on bandit26’s home directory, you have as in level 19->20 a setuid binary. Let’s execute it to see its default output.

$ ls
bandit27-do  text.txt

$ ./bandit27-do 
Run a command as another user.
  Example: ./bandit27-do id

In the same fashion as in level 19 -> 20, you can make user bandit27 cat its own password for you:

$ ./bandit27-do cat /etc/bandit_pass/bandit27
YnQpBuifNMas1hcUFk70ZmqkhUU2EuaS