This post is a complete walk-through of the Linux CTF by OffSec club at Dakota State University.
Things to Note
- Read the Disclaimer before reading this post.
- This post assumes that you know a little bit about linux and to use basic commands and some basic programming skills.
Linux OffSec Club at Dakota State University has setup a beginner Linux CTF challenge at linux.offsec.club. Initially you are given the credentials to a Level-0(user1) user (check out the website for the creds), then you login via SSH and start looking around for the password of the next user(user2) and this repeats until user15. Your goal is to reach the end. Alright, let’s start with Level-0.
Visit the url http://linux.offsec.club/, you’ll see the credentials for the user1. Use these credentials to login via SSH. If you are on Windows you can use putty and if you are on Linux or Mac, you can simply use the
- Open Putty.exe
linux.offsec.clubas the host.
- Click open
- Enter username & password
- That’s it!
- Open Terminal
- Enter the password for the user1
- That’s it!
- we use
sshcommand to login to a remote machine to get a shell.
Now that you have a remote shell via SSH, you need to start looking for the password of the next user i.e., user2. First thing that we can do is check where we are in the filesystem.
As you can see, we are in user1’s home directory. Let’s try listing all the files in the current directory.
We see nothing, but If you know a bit about
ls, you’d know that
ls lists all the files except the hidden ones. To view hidden files we can use
Okay, there’s a
.here hidden folder, We can take a look at what’s inside.
There we go, the file
pass had the password to our next user(user2).
- Hidden files start with a
Now we can use the same command from Level-0 and log into user2 with the password
CentsMaybeCarry55. Remember that I won’t be showing you how to connect via SSH with a password in every level, it is assumed that you know how to connect via SSH after reading the Level-0 solution.
Listing all the files in the current directory, we get
We can see the password file there let’s try opening it
What just happened? If you look at the filename, you’ll see that it has some special characters like
$. This means that we need to escape these characters in order to access the file. We can escape these characters using a backslash(
There we go,
WereElseLabor80 is our password, but we can solve this challenge in another easy way and this is cheating in a way, but hey! they never mentioned any rules, did they? Anyways we can use the wildcard(
*) which means everything, so
cat reads all files in the current directory.
- Use backslashes(
\) to escape special characters.
*means wildcard and it matches everything.
Listing all the files in the home directory of user3, we get,
Let’s read what’s inside,
Whoaa what’s this? This is an RSA Private Key(see resources), If you didn’t know, we can use a private key instead of a password to authenticate to an SSH server. It’s more secure this way. The public key is stored on the SSH server, so whenever you try to connect with an SSH private key, the SSH server verifies the key pair and logs you in.
So here’s what we gonna to do, we’ll copy the contents of the
password file to another file
ssh-key.txt on our machine, not the CTF one. Then we can simply use
-i option to specify the private key.
We do the
chmod 600 ssh-key.txt because
ssh will throw us with some errors(Insecure SSH key file permissions).
If you are using
putty, you might wanna look at this
- You can connect to the SSH server with a private key provided that the public key is on the server.
Now, let’s do a complete listing of the files
” Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. “
Alrighty, let’s try to view the logs
What happened? Well, apparently the git folder is corrupted or its just a dummy. Usually, in a typical CTF git challenge, the flag.txt or password or any proof-of-work string/file is commited to the git repo, but later down the road, the file will be deleted. But since git is a version control system, it keeps history of all the commits, you can simply revert back to that commit and extract the password/flag.txt. But in this case, it was not related to commits and history. It’s probably something different, let’s look inside the .git directory
Let’s check out
Ohhkayyy, Let’s go inside with
* wildcard(Refer Level-2)
You see where this is going? we get the brutal directory traversal challenge. But we can use
grep to solve this challenge.
-R recursively checks for the regular expression. Here,
. represents any character in regular expressions, so we recursively check for any character going inside the directory tree.
There we go, we see the password
CloudGiftMalta49 at the end of the output.
There are other ways of solving this challenge like
cd */*/*/*/*/*/*/*/*... or doing something programmatically, but I think grep is the simple one.
grep -Rcan recursively go in a directory tree and search for specifics.
- These kinds of tedious/brutal challenges are all about your programming skills or a program specific skill.
- Never do it manually (maybe sometimes, but rarely).
Onto the next one.
Alright the password is right there
This time there’s something to do with the permissions. Let’s check out the other file
Hmm… This looks like a man page of
sg command. Here’s the thing, the
password.txt can be read by a specific group only and we are not that group, so that’s the reason we are not able to access it. So what’s with the
sg command, you might’ve guessed it or you probably knew about this, this command helps us execute a command as a group that we want, given that you have the password for it.
As you can see, the group asscociated with the
password.txt is password.
Let’s use the
sg command and try reading this
Boom, there’s the password
- You can use
sgcommand to execute a command as a different group.
Listing all the files of user6’s home directory gives us
Okay, let’s check it out
Whaaaat the ffffffffile? Unprintable characters!? This could mean only one thing, it’s probably an executable or some sort of a specific file type that’s not really meant to be read directly.
Raw data, Interesting…
So what we need to do is, get the password out from this data somehow. Since we see all the unprintable characters, let’s check if there are any printable characters inside this data. We can filter that using the
There we go, the password
SaveThanGoes26 was hidden somewhere inside this huge junk of data.
- Use file command to check what kind of file you’re dealing with.
- Use string to extract printable characters.
Let’s see what we are dealing with this time
Nope? what does Nope mean? It should either give us the contents of the file or give us an error message, not Nope, unless Nope is the content of this file which seems skeptical. There’s one other possiblity, The
cat command (which is actually an executable file) resides in
/usr/bin/cat or maybe someplace else which is quite common. Now let’s check where does
cat exist in filesystem using
Ahaaa, there it is, it’s some kind of a broke version of
cat and the
PATH environment variable is overwritten by this new cat path location so that if you use
cat command it executes a broke one instead of the original one. You can also check if the broke
cat is really broke by
So lets see if the original
cat exists in
Oh, it’s not here, let’s check
There you go, now let’s use this cat by specifying the entire path to it like
Alternatively you can use grep
EachPeaceLand64 is our password. Sweeeeeeeeet :) Onto the next one.
- Never trust something blindly, always test the theory.
What do we have this time?
There’s a clear hint “go here => cyberchef”. CyberChef is a Cyber Swiss Army Knife tool for encoding/decoding and hash calculations. This tool is basically an html file, you can download it from the github repo or you can use the online version, I’ll use the online version.
go here => https://gchq.github.io/CyberChef/
Now let’s read what’s inside
First line looks like Base64 encoding. You might recognize this, you might not, but remember if you see ASCII characters which mean nothing and
= is being padded at the end, it might probably be a Base64 encoded string. The
= is padded so that the smaller bits can round up to a whole. Base64 Also has a character set
A-Za-z0-9+/= which translates to
These are the only characters used in Base64 Now we know that this is Base64, let’s decode this. We can do this in commandline, but let’s try out CyberChef because you’ll learn to use a new tool.
Follow these steps
- Visit CyberChef
- From the left panel, expand Data format
- Drag From Base64 to the Recipe window
- In the Input window Enter the first line of the
- Click on BAKE! button, you’ll see the first part of the password in the output window.
Similarly we do it for Base32 and Base58, because
- Base32 has the character set
K5XXK3DEmatches this set.
- Base58 has the character set
3ro2uVYXCbmatches this set.
So now, remove the From Base64 from the Recipe window by clicking on the delete button on the top right corner of the Recipe window.
Perform the same steps for Base32 (
K5XXK3DE) and Base58 (
3ro2uVYXCb) and you’ll end up with
- From Base64(‘V2Vhcg==’) : Wear
- From Base32(‘K5XXK3DE’) : Would
- From Base58(‘3ro2uVYXCb’) : Known80
So the final password is
- Get yourself familiar with different encoding types and it will help you detecting them in the future.
- CyberChef is a handy tool for encoding/decoding and calculating hashes, so learn to use it.
Alright, let’s see what do we have this time
Okay, this time it looks like a hash. What are hashes? They are one-way encryptions, this means you cannot reverse em back or decrypt em. So how are we suppose to extract the password? We can convert a password into it’s hash form and check if the hash matches the hash in
password.txt file. If it does, then that’s the password. Simple right? Not really, There are a lot of combinations from available characters on the keyboard
- All symbols
When we calculate the combinations, it’s going to be a huge number, which takes a lot of time and computing power. Instead we can use an online Hash Lookup Table. These are basically stored calculations of words and hashes. We’ll use crackstation.net
- Visit crackstation.net
- Enter the hash found in the
- Complete the Google captcha and click on Crack Hashes
- We get a result
sharkbait is our password.
- Learn to identify hashes.
- If you can’t crack it, use online resources like crackstation for cracking fairly common/easy-to-crack passwords.
What do we have?
let’s check out
Looks like we have some random words, let’s check out
wordcloud.txt for any clues.
in order… That’s a useful hint, because we have words and we have to do a wordcloud, which is basically a nice visual way of representing different words based on their frequency of occurance. So if we find the frequencies of all the words and sort them by count, we’ll find the password. We can solve this in a number of ways, you can use an online tool like TagCrowd or write a python script. Let’s not use the online tool, because it’ll be too easy, let’s use python for calculating the frequency and picking the top 3. Follow the steps
- Create a file called
words.txtwith all the words from
pythonand hit enter
As you can see “angry”, “major” and “watch” has top 3 frequencies and from
wordcloud.txt we know that they are “in order”.
So the password must be
angrymajorwatch and it is.
You can also use online word frequency counter to extract top 3 and put em in order, you’ll have the password.
- wordcloud = word frequency
- Always use automation (Python or online or anything you like)
Reading the contents of
password.txt gives us
We have some sort of a book. First time when I encountered this challenge, I thought this might be something to do with the book itself, so I researched online but ended up finding nothing. The real deal was to extract the password from the book using
grep. Yes, it is that simple, but the position of this challenge as Level-11 in the CTF game will throw off people like me into a rabbit hole while this entire challenge was too easy.
grep -i is for case insensitive matching and
EarlyHersCase97 is our password.
Onto the next one.
- Sometimes, the answer is right in front if your eyes and it’s simple, you try to ignore it by thinking too fast. Slow down and try everything. You’ll defintely figure it out. Time & Imagination are your only constraints.
grep -iis the case insensitive flag for regular expression matching.
It ends with
==(double equals - due to the font, it looks a bit wierd), If you remember from Level-8, this looks similar. YES, It’s Base64, but huge.
We can use
base64 command in linux to extract the password. Let’s try that
Okayy, it’s again Base64, let’s decode it again
I think we get it, It encoded a lot of times, so we need to decode it recursively. I’ll use python for this, you can do it with just shell scripting, but I love python. First thing to do is to copy the file to
/tmp/whatever_directory because you are not allowed to write to files in home directory.
We get 41, so maybe till 40, It was a valid Base64 string. Let’s check out the new file we generated
It’s not a normal file for sure, so let’s use
Well, would you look at that? It’s a gzip compressed data. It’s an archive. So let’s uncompress this file. I created a new directory called
new so that the extracted files will be seperate from the other ones like my python script. I also renamed
QuickHourEver20 is our password.
- Repetitive tasks are not meant for humans, use automation scripts, let the computer help you.
- Always use
filefor confirming the file type, don’t be deceived by the file extensions.
Just 2 more levels, keep going!
Listing home directory gives us
lets do a
file on each file
challengeis a 64-bit ELF executable
challenge.clooks like the source code of the executable in C
password.txtis a regular text file
If we try to access password.txt we get
so let’s check the permissions of all the files
root group has the ablity to read
challenge is interesting because it has a SETUID bit. That means it can read the password.txt for us.
let’s run that
After executing the program, it waited for some input I typed “ASD”, but it gave us a error message
Fail 4 != 1. We might have to reverse engineer this executable, but there’s the
challenge.c source code right there, so we can just look at it.
Basically this program loops for 1000 times. In every loop, it takes the input and stores it in a variable called
buff and checks if the length of the input i.e.,
buff is same as the loop index
c. If it’s not then it’ll give us the error.
The table illustrates each loop from the above example
|“\n”||1||1||1 == 1||true|
|“1\n”||2||2||2 == 2||true|
|“12\n”||3||3||3 == 3||true|
|“555\n”||4||4||4 == 4||true|
|“3232\n”||5||5||5 == 5||true|
|“333333\n”||7||6||7 == 6||false|
Since 7 != 6, we get the “Fail” message for the last case.
So the input length has to be same as the variable
c. We can do this by hand like a thousand times. But it’s insane, one small mistake, you are done, you have to start all over again. So we write a simple python one liner.
We can use
-c option to write python code like the above, making it a single liner. All it does is that it prints number ‘1’ in increasing order like the program
challenge needs. Now we just have to change the number
1000 and pipe it to the
There it is,
BookVerbLeast61 is our password. Sweeeeeet :)
- Repetitive tasks = computer’s job
- Understand the source of a program completely before trying to attack it.
What do we get now?
Same? ofcourse not, let’s look at
challenge.c, because we know what’s up with the other 2 files(
password.txt is not readable by us, but since
challenge has a setuid bit, it can read the password but we need to complete the challenge).
We can see the password right there, but there’s more to it.
Basically this checks if the entered input is equal to the value of (int *) of the character in the password char array and also the variable
c increments by 4 that means it loops 3 times.
All we gonna do is copy the source code, modify it a bit and make it spit out the right values. The final source is down below, Instead of stepping through the debugger to find out the values, we can just simply remove the
if statement with the
scanf and simply print the value of
*(int *)&password[c] in each iteration.
Now we can run the program
challenge and simply enter these values
ClassPlacePress16 is our password.
- If the challenge is hardcoded, modify the source and make it spit results for you.
You should be able to log into the last user, that’s user15.
We’ve completed the CTF, we are now the user15. The “last user” right? or is it not?
That’s all for now folks. Thank you for reading. Have a great day :)