My CTF Service Enumeration Methodology

This is a brief overview of my basic methodology that I use when doing CTF challenges, Hack the Box, Proving Grounds, Try Hack Me, and similar test/challenge type activities.

While I have other articles that cover some of the same topics, this is to present these things specifically in the sense of how I think when I doing a challenge, and not just notes dumps like some of my other material.

This article will cover my methodology for external service enumeration up to the point of getting an initial access shell.

Theory: Vulnerabilities on Services

The overall mentality I have approaching a "box" is simply to do the following:

  • Discover services
  • Probe them for vulnerabilities
  • Document and exploit those vulnerabilities

That's really it. Find services. See if they have a CVE or insecure misconfiguration, exploit that security issue, and document how I did it.

Workspace setup

Before I even begin a box, I setup my workspace so that I have sufficient command windows open to be able to complete most tasks with convenience. In order to accomplish this, I use the Terminator terminal emulator. Usually, I'll divide up my workspace like so:

  • VPN Stuff -- With most of these practice challenges, I'll be connecting to some VPN over OpenVPN. This windows is for the OpenVPN session.
  • Generic Workspace -- These are for basically any task I need done. File operations, throwaway http servers, payload creation, etc etc.
  • Shell handlers -- This is for MSFConsole or netcat shell handlers. Can be split up as needed if you need more than one handler.

For web challenges, I'll also open 2 seperate tabs: 1 for running tools like FFUF and GoSpider, and another for MitmProxy. Neither of these apps like running in anything but a full sized terminal, so they necessitate their own tabs.

Once I've got my terminals split up as I like, I'll then create a directory for the project. For me, this is usually in a folder named like


~/Documents/[CTF platform]/[box name]

This will be for storing extraneous files. Anything from exfiltrated data from the target host, to exploit code, PEAS output, payloads that need to be served up to the remote host, etc etc. If it's a file and related to the box, it lives here. Once I create this directory, I pwd, and then copypaste the directory into cd commands in each workspace to make sure all of my terminals are running from the box's project directory.

Then, of course, I'll connect to whatever VPN I need to connect to, sign into the platform I'm playing on, and fire up the box I'm intending to play.

Note taking

In addition to setting up my workspace, I also use Joplin to take notes. Joplin is a markdown based note taking app.

The goal of these notes is to create a document that meticulously details all of the processes that I perform during an engagement. Ultimately, I intend that the notes should be thorough enough that I could replicate a compromise from them, and construct a report without having the engagement fresh in mind just from the notes.

Typically, I'll create 2 to-do lists: 1 for service enumeration, and a 2nd for internal privesc enumeration. This article focuses on the process of creating the first one.

Usually, I don't publish these notes, since they're not intended to be coherent to anyone but myself.

Here, however, is a sample (as a PDF) you can see as an example.

Overview of the process

Generally when I'm making out my notes for Service Enumeration/Initial Access, I'm looking to have sections for the following:

  • Nmap
  • Service table
  • Individual service enumeration

We'll go into these in detail below.

Nmap

Nmap is a famous TCP/UDP portscanner. Any engagement with a box that I'm doing will begin with a scan like this:


sudo nmap -sC -sV -vvv -Pn -t 4 [IP] 

This will run "safe" scripts and service version scanning. It also gives verbose output (so you can see newly discovered ports as they're discovered instead of after the scan is complete), does not use ICMP, and has a timing of 4. This is the same opening nmap scan used in all of my CTF box writeups thusfar.

Deeper nmaps

If no vulnerable services are discovered with the basic scan, I'll use "deeper" scans to different ends:

Vulnerability Script Scan

This scan will run all of the installed nmap script engine scans that contain "vuln" in their title. This is effectively a stock vulnerability scan:


sudo nmap --script "vuln"  [IP]

Full port scan

This will scan everything TCP.


sudo nmap -vvv -Pn -p- [IP]

UDP scanning

UDP can be scanned like this:


sudo nmap -sU [IP]

UDP scans strangely, and it may be prudent to aim for very specific UDP protocols, e.g. IPSEC:


sudo nmap -sU -p 500,4500 [IP]

Service table

Once I have basic nmap results, I'll build out a tables documenting the following stuff.

  • port
    • Self explanitory; the transport layer protocol and the port number. Usually I ctrl+c straight from the nmap results
  • protocol
    • What protocol this is.
  • version
    • Software version. As soon as I get ahold of this, I check searchsploit, msfconsole, and github for known public exploits.
  • notes
    • Is it vulnerable? Did the nmap safe script scan find anything? If I ran a vuln scan did it find anything? Etc.

You'll be used to seeing these as I do put them in most of my writeups:

port protocol version notes
TCP 135 MSRPC ? Nothing noted
TCP 139 Netbios MS Netbios Nothing noted
TCP 445 SMB Windows XP Critical Vulnerability Discovered : MS08-067

Or, as written in markdown:


|port|protocol|version|notes|
|-|-|-|-|
|TCP 135|MSRPC|?|Nothing noted|
|TCP 139|Netbios|MS Netbios|Nothing noted| 
|TCP 445|SMB|Windows XP|Critical Vulnerability Discovered : MS08-067| 

Note that I only document noteworthy ports. 50k+ RPC or tcpwrapped ports usually aren't exploitable.

Individual service enumeration

Moving on, for each noteworthy port on my service table, I'll create a level 2 heading named after the port number and service. This might look like so in markdown:


## TCP 25 SMTP

## TCP 80 HTTP

## TCP 53 DNS

[...]

Port by port, I perform attacks against each protocol, documenting every command and noteworthy output I perform under each heading. The following are the methods I use for common services.

SMB

SMB is the common fileshare protocol on Windows systems and runs on TCP 445, but also often appears alongside port 135, as this is the legacy NetBIOS system that allows SMB to work with legacy applications that are unable to utilize TCP/IP networking.

When I see SMB, I'm going to:

  • Check for null logon rights
  • If permitted, attempt to enumerate users and shares.
  • Attempt PsExec command execution

Crackmapexec is a fairly useful multipurpose tool for Windows network pentesting. Note that under the hood, most of it's functionality is more or less a wrapper around impacket scripts.

List shares:


crackmapexec smb [IP] -u [user] -p [pass] --shares

Listing domain users:

crackmapexec smb [IP] -u [user] -p [pass] --users

Download all readable files from the host:


crackmapexec smb [IP] -u [user] -p [pass] -M spider_plus -o READ_ONLY=false

Executing commands:


crackmapexec [IP] -u [user] -p [pass] -x [command] --exec-method [method: wmiexec, atexec, smbexec]

Manually using SMBClient to list shares:


smbclient -L [IP]

Connecting to a share:


smbclient //[host]/[share] -U [user]

To enumerate anonymous logon for these commands, use "anonymous" as a user and supply a null password. For null logons, supply a null ('') username and password.

Even if anon and null logon are unavailable, that doesn't mean SMB is completely useless -- it may be a vector later if credentials can be found. Crackmapexec has many more functions that can make it useful for things like password sprays too, so if that's in scope for what you're doing, that could be an option as well.

FTP

Will usually be on TCP 21.

With FTP, my primary aim will be:

  • Check for version specific vulnerabilities
  • Check for anonymous logon

Apart from that, the only other option would be to attempt various sorts of credential bruteforcing, which is usually not in scope for most CTF type challenges.

SSH

Usually on TCP 22, but can often show up on 2222 or other alt-ports for security by obscurity.

Other than version speicifc exploits, SSH is usually only going to be vulnerable to credential bruteforcing.

HTTP

Can be on a number of ports:

  • 80 -- normal http
  • 443 -- https (the encrypted version you'll more often see in real life)
  • 8080 -- http-alt; often used for app server interfaces. Can be pretty interesting.
  • 4443 -- https-alt. You'll see this often IRL for things like appliance logon panels.

You can see all sorts of other ports too. Anything that's not 80 or 443 may be some sort of appserver or other exposed service that could be uniquely vulnerable, so they're especially worth checking out in most cases.

In general, web application pentesting is a fairly in-depth activity that I have a fullscale methodology for in it's own right, and so this is a bit beyond the scope of this article.

MSRPC

Often runs on TCP 135, but RPC hosts also run in very high port ranges as well.

This isn't too often that useful, but in some cases, rpcclient can be used to logon to the system with a null logon and query various things.

Null logon:


rpcclient -U "" -N [IP]

From here, you'd usually do enumdomusers and/or enumdomgroups to dump domain information, but outside of that context, I've not seen much use out of it.

The DC duo: LDAP/Kerberos

A combination of LDAP and Kerberos, especially if it's also seen in tandem with DNS is frequently an indication that a machine is an Active Directory Domain Controller.

If I see this combination, I will follow my methodology for Active Directory, which is beyond the scope of this article, and involves attacks specific to that sort of environment.

DNS

DNS usually runs on TCP 53. It's often useful for finding things like subdomains.

Using dig to discover subdomains:


dig any victim.com @[nameserver IP]

Basic DNS lookup; querying different records can yield interesting results:

host -t [record type] [domain]

DNS record types are as follows:

  • NS
    • Name Server records. This is the DNS server that hosts the domain.
  • A
    • The host record. The IP associated with the name.
  • AAAA
    • IPv6 host record.
  • MX
    • Mail exchange. This is a list of associated mail servers for the domain.
  • PTR
    • Pointer record. This is used for reverse lookups. If a single IP hosts multiple domains, PTR is used to discover domains associated with it.
  • CNAME
    • Canonical name record.
  • TXT
    • Text records. Arbitrary extra information. It's simply what it says on the tin: a text record.

Dealing with unknown services

Obviously, not every service is going to be on this short list. Usually, when I encounter an unknown service, I'll

  • Check Speedguide. This is pretty generic, but can be a start.
  • Check Hacktricks. This will be hit or miss, but a good number of commonly vulnerable services will be listed here with methodologies for testing them.

Once I've gotten a shred of identification for the service, especially if I get the version number, I'll be using searchsploit/exploit-db, msfconsole and github to search for public exploit code or known vulnerabilities. This can be quite a hunt and the specifics will differ service to service.

Often with CTF boxes, an unusual service port may point to the software that's vulnerable for the purpose of whatever the challenge is trying to teach. Obviously, real world scenarios won't be this gameified, but it's something to keep in mind for training and challenges.

Stuff that can usually be ignored

High port (10000+) RPC hosts and "TCPWRAPPED" ports usually do not have anything useful on them.