Robots
A (small) tribute to I. Asimov. - by shamollash
Last updated
Was this helpful?
A (small) tribute to I. Asimov. - by shamollash
Last updated
Was this helpful?
The following post by 0xb0b is licensed under CC BY 4.0
We start with an Nmap scan and find three open ports. On port 22
we have SSH and on port 80
and 9000
we have web servers. We get the robots.txt
entries directly from the default script scan.
We have some interesting directories from the robots.txt
:
We visit the index page of the site on port 80
, but only get a Forbidden.
On port 9000
we only have the Apache2 default page in front of us.
We visit the directories of the robots txt
, but we only get a login page on the path /harm/to/self
. For the others we also only get a Forbidden.
We visit the login page and see that it is a PHP page. Unfortunately, the login does not provide any feedback, for example to enumerate usernames.
We use gobuster to look for other directories and PHP pages in /harm/to/self
. Among other things, we have an admin.php
page there. Which we cannot access without authorisation.
We continue and register a user. To do this, we enter a username and date of birth. We are informed that the initial password is the MD5 hash of the username concatenated with the day and month of the date of birth.
If we had feedback when registering or logging in, we could certainly have enumerated usernames and passwords using FFuF. But this is not the case.
We calculate our hash with CyberChef...
... log in ...
... And see the index page of /harm/to/self
. Our username is reflected here, but we also see that there is probably an Admin user. At the top left we have a link called server info.
This link reveals the PHP info page. We'll explain how useful this can be for us in a moment.
Since our username is reflected, we use a simple XSS payload as the username. We register a user with the following username, log in and receive our alert.
So if the admin also interacts with the page and would also see a list of usernames, we could steal the admin cookie. This would allow us to enter the admin session and interact via admin.php
, which we found in the gobuster scan.
Unfortunately, the HttpOnly
flag is set. The HttpOnly
flag prevents JavaScript from accessing the cookie, making it accessible only through HTTP requests to protect against XSS attacks.
But we have different access to the cookie, as the following article shows us and as already mentioned the PHP info page could become important for us.
We can steal the cookie from the PHP info page.
We use the following script from Hacktricks for this. And provide it with a web server from us.
The username can then look like the following. If something does not work, we can simply adapt our script on our web server and reload the page after logging in to execute the adapted script again.
We register the user...
... log in...
... and are unable to retrieve the full page because the content is too large to fit into a URI.
We adapt the script to only steal the cookie content...
... and reload the index page and have the admin cookie exfiltrated later.
We replace the cookie.
Reload the index page again, and it seems like we are now Admin
, since we can see all users created so far.
As Admin
, we now access the admin.php
and see that we can test for urls.
We provide our webserver address...
And see a directory listing rendered.
We test, if we can inject PHP pages...
We provide the page the same as the other content with a simple http server using python.
Next we access the whoami.php
page on our server.
And see that our page gets resolved.
Next, we provide a pentestmonkey PHP reverse shell and set up a listener.
We then submit the URI to our pentestmonkey PHP page...
... and get a connection back to our listener. Next, we upgrade our shell with the following resource.
We are www-data
.
As www-data
we find the database credentials in the config.php
of the webserver. Unfortunately, there is no database service running on the server itself and the availability of simple tools / binaries is limited.
In the root directory we find a .dockerenv
file...
The /etc/hosts
with the entry for robots.thm
also indicates that we are in a Docker container. Maybe we have more containers available on 172.18.0.0/24
. Perhaps including one on which the database is running.
For the subsequent phases, we use ligolo to relay traffic between the docker container and our attacker machine to make the internal and external services of the docker container accessible from the container to our attacker machine.
Ligolo-ng is a simple, lightweight and fast tool that allows pentesters to establish tunnels from a reverse TCP/TLS connection using a tun interface (without the need of SOCKS).
First, we set up a TUN (network tunnel) interface called ligolo and configuring routes to forward traffic for specific IP ranges (240.0.0.1
, 172.18.0.0/24
) through the tunnel.
Next, we download the latest release of ligolo-ng. The proxy and the agent are in the amd64 version.
On our attack machine, we start the proxy server.
Next, we run the agent on the target machine to connect to our proxy.
We get a message on our ligolo-ng proxy that an agent has joined. We use session
to select the session and then start it.
Now we are able to scan 172.18.0.0/24
using nmap. We see that we have 172.18.0.1
, 172.18.0.2
, and 172.18.0.3
reachable. The MySQL server is running on 172.18.0.2
.
We try to log in to the web server with the credentials, but are unsuccessful. The relay using ligolo-ng does not seem to work properly.
We used ligolo-ng to make the Docker network available and found out that the MySQL server is running on 172.18.0.2
. Since the MySQL client cannot connect properly using ligolo-ng, we use Chisel.
We setup the chisel server on our attacker machine.
Download chisel on the target machine, make the binary executable and execute the chisel client to set up a reverse port forwarding tunnel, forwarding remote port 3306 on the target (at 172.18.0.2) to local port 3306 on the Chisel server (at 10.14.90.235) via the client.
Now, we are able to ascess the MySQL server on 127.0.0.1 3306.
There is a web database, which hs a users table containing the usernames and password hashes. Among them we have the previously unknown user rgiskard
. Perhaps we can reuse its password, for example for SSH access.
We notice that our hash (our actual password for 0xb0b) does not match the database entry.
The password entries are hashed.
Since we know how the initial passwords are composed [md5(username+ddmm)
], we can write a script that generates all passwords for us and compares their hashes with the one found. This way we get to the original string and the hash of the original string which is the password.
We execute our script, provide username and found hash, and we got a hit.
We are able to log in via SSH as rigskard using the hash of the combined string. But we won't find the user.txt
in the home directory of the user.
But we see that we are allowed to execute cURL as the user dolivaw
using sudo with a wildcard.
Using cURL with wildcard allows us to write to a location as dolivaw. Like the following:
We could use this to write our own ssh key public key to authorized_key file in dolivaw
's home directory. Allowing us to SSH as dolivaw
, since we are in possesion of a freshly generated SSH private key.
We generate a private key at /tmp
.
Next, we write the content of the public key in /tmp/id_rsa.pub
to /home/dolivaw/.ssh/authorized_keys
.
We then copy the key to our machine. Encoding helps a little...
... and adjust the permission
We can now use the private key to log in as dolivaw
. In the home directory of the user the first flag can be found.
As dolivaw
we are allowed to execute /usr/sbin/apache2
as root
using sudo
without the need of as password.
We still have the authorized_keys entry of dolivaw we created.
So we could create an Apache config file, that is abusing the logging feature to write an SSH public key into /root/.ssh/authorized_keys
.
After preparing the configuration file, we start the Apache server pointingg to our configuration.
Apache starts using the specified config file (-f /tmp/myapache/apache2.conf
).
Since we’re running Apache as root
using sudo
, Apache will have root-level permissions.
A request to localhost:7777 will trigger the logging mechanism.
The LogFormat
contains the SSH public key, so Apache will:
Handle the request.
Write the LogFormat
content (the SSH key) to /root/.ssh/authorized_keys
.
Since Apache is running as root
, it has write access to /root/.ssh/authorized_keys
.
We reuse our private key to log in as root
using SSH. The final flag can be found at /root/root.txt
.
Don't miss the unintendes discovered by Jaxafed. Among them a file read with Include to read the final flag and RCE with CGI Scripts to gain a root shell.
Furthermore, we have a wonderful writeup by AkewalBiru, who has gained foothold completly on the client side using Javascript without stealing the session cookie.
And on top of that, AkewalBiru had leaked the database by executing PHP on the target without having to foward the ports. Great!