Detection with GenAI (Part 2): CrushFTP (CVE-2024-4040)

Detection with GenAI (Part 2): CrushFTP (CVE-2024-4040)
Image by Arantxa Treva

The second in a series of GenAI experiments for prevention, detection and response.

This exercise was the ITWeb Security Summit Hackathon #SS24Hack second day challenge for the Snode Technologies Blue Team GenAI CTF (capture the flag) event.

It's a Hackathon!

Anyone should be able to do it; even if you have not used ChatGPT; and are new to detection or prompt engineering. The challenge is designed to be accessible to all.


Sections

  1. Background (optional)
  2. Building a CrushFTP lab
  3. Vulnerability discovery

Background

The first installment of this (infinite) series of experiments covered the PaperCut (CVE-2023-27350) vulnerability. The idea is to use GenAI (e.g. ChatGPT) natural language prompts to aid prevention, detection and exploitation code development.

There was recently an interesting research paper (R Fang, R Bindu, A Gupta, D Kang) on exactly this topic: "LLM Agents can Autonomously Exploit One-day Vulnerabilities".

I will do a research paper dissection article on this soon - so subscribe to get a copy.

Why CrushFTP?

Great question! So, if you've ever used the VulMon platform (vulmon.com) you may have noticed they list recent vulnerabilities by (CVE) risk score (screenshot below).

VulMon recent vulnerabilities listed by risk score (CVE-2024-4040 top of the list)

This implies it is both recent and high-risk; an excellent case study for experimentation.

What did Shodan say?

I see you were paying attention. Below is a screenshot of (and search parameters for) Shodan - showing us the total number of CrushFTP (HTTP) servers on the internet:

html:"/WebInterface/Resources/js/login.js"
Shodan showing the number of CrushFTP internet-facing servers (at the time of writing).

Ok, now let's get to work,...


Building a CrushFTP lab

Downloading previous vulnerable versions from the vendor was an issue. A quick GitHub search can sometimes do the trick - here is a vulnerable build for your lab.

Github helps us find a vulnerable CrushFTP for our lab (the-emmons/CVE-2023-43177).
Link to the vulnerable release (https://github.com/the-emmons/CVE-2023-43177)

You can download the installation files, source code and find instructions on this page.

Alternatively, you can get a step-by-step installation guide from the research portal.

Once installed, I used the following command to access the administration interface:

java -jar CrushFTP.jar

Once you start CrushFTP (HTTP) services you can browse to the console shown below.

CrushFTP Landing Page (/WebInterface/login.html).

Vulnerability discovery

As with the PaperCut vulnerability (we discussed in the first article of this series), to achieve a (Arbitrary File Read) exploit, you leverage multiple vulnerabilities:

  1. Authentication bypass - you can connect to their API endpoint (/WebInterface) and get a higher privileged (CrushAuth) token; and
  2. Server-side template injection (SSTI) - with step 1 complete, you now access the API and inject, your own code, into a template.

Vulnerability analysis

To better understand the vulnerabilities we need to manually exploit them. My recommendation is to use Burp to analyse the web application and API endpoint.

I'm not going to reinvent the wheel on this - Rapid7 did an excellent write up:

CVE-2024-4040 | AttackerKB
On Friday, April 19, 2024, managed file transfer vendor CrushFTP released information to a private mailing list on a new zero-day vulnerability affecting Crush…

Detection engineering

This section simply completes the detection process. The high level process is:

  1. Detect CrushFTP with Nmap; and
  2. Detect CrushFTP CVE-2024-4040.

Fingerprinting CrushFTP servers

For fingerprinting I'm going to just look for the default landing (login) page.

ChatGPT prompt for login page detection

Which returned the following python code:

import requests
import argparse

def check_web_server(ip, port):
    # Construct the URL using the provided IP and port
    url = f"http://{ip}:{port}/WebInterface/login.html"

    try:
        # Send a GET request to the URL
        response = requests.get(url)
        
        # Output the status code and response content
        if response.status_code == 200:
            print(f"Resource found: {url}")
            print("Status Code:", response.status_code)
            print("Response Content:", response.text[:200])  # Print the first 200 characters
        else:
            print(f"Resource at {url} returned status code: {response.status_code}")

    except requests.exceptions.ConnectionError:
        print(f"Failed to connect to {ip}:{port}")
    except requests.exceptions.RequestException as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    # Setup command line argument parsing
    parser = argparse.ArgumentParser(description="Check a web server for a specific resource")
    parser.add_argument("ip", help="IP address of the web server")
    parser.add_argument("port", help="Port number of the web server")
    
    # Parse arguments
    args = parser.parse_args()
    
    # Check the web server for the specified resource
    check_web_server(args.ip, args.port)

Python fingerprinting script provided by ChatGPT.

The script worked fine straight out of box,... must be the swanky new version of GPT:

Running the script provided by ChatGPT.

Being a bit more adventurous second time round, I asked for a Nmap NSE script.

Asking ChatGPT to produce Nmap NSE scripts instead.

This produced the following NSE (Lua) script.

local http = require "http"
local stdnse = require "stdnse"

description = [[
  This script checks if the resource `/WebInterface/login.html` is available on a web server.
]]

author = "Your Name"
license = "Same as Nmap - See https://nmap.org/book/man-legal.html"
categories = {"default", "discovery"}

-- Define the script arguments (optional)
portrule = function(host, port)
  return port.number == 80 or port.number == 443
end

-- Main function
action = function(host, port)
  local path = "/WebInterface/login.html"
  local url = string.format("http://%s:%d%s", host.targetname or host.ip, port.number, path)
  
  stdnse.print_debug(1, "Checking for resource: %s", url)
  
  -- Perform the HTTP request
  local response = http.get(host, port, path)
  
  if response and response.status == 200 then
    return string.format("Resource %s found (Status: %d)", url, response.status)
  elseif response then
    return string.format("Resource %s not found (Status: %d)", url, response.status)
  else
    return string.format("Failed to connect to %s", url)
  end
end

Nmap NSE fingerprinting script provided by ChatGPT.

The Nmap NSE script work straight out of the (vi) gates:

Nmap NSE (Lua) script to fingerprint CrushFTP.

So, why and Nmap script specifically? Good question! Neo uses Nmap,... nuff said.

Neo,... Nmap,... Nuff! (https://www.zbrushcentral.com/t/neo-keanu-reeves-the-matrix/418311)

Also (if saving you from the Matrix wasn't enough), it also offers the following:

  1. Portability, it's (still) cross-platform and now highly configurable.
  2. Community, you can contribute your (ChatGPT) script to others.
  3. Standards, we can standardise our approach to testing and tooling.

Detecting CrushFTP CVE-2024-4040

For the detection, we need to manually devise and confirm an approach. So, we look to confirm the vulnerability, and design our test method, with Burp Proxy:

Using Burp Suite (Repeater) to confirm the CVE-2024-4040 vulnerability.

In the screenshot above we can clearly see the "CrushAuth" cookie defined. So, the simplest approach is to ask ChatGPT to confirm the "CrushAuth" cookie is present:

Asking ChatGPT to write the NSE detection script based on our testing method.

This produced the following NSE (Lua) script.

local http = require "http"
local stdnse = require "stdnse"

description = [[
  This script checks if the resource `/WebInterface/` is available on a web server
  and verifies if a `CrushAuth` cookie is present in the response headers.
]]

author = "Your Name"
license = "Same as Nmap - See https://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "auth"}

-- Define the script arguments (optional)
portrule = function(host, port)
  return port.protocol == "tcp" and (port.number == 80 or port.number == 443)
end

-- Main function
action = function(host, port)
  local path = "/WebInterface/"
  local url = string.format("http://%s:%d%s", host.targetname or host.ip, port.number, path)
  
  stdnse.print_debug(1, "Checking for resource: %s", url)
  
  -- Perform the HTTP request
  local response = http.get(host, port, path)
  
  if not response then
    return "Failed to connect to " .. url
  end
  
  -- Check for CrushAuth cookie
  local cookies = response.cookies
  local has_crushauth = false
  for _, cookie in ipairs(cookies) do
    if cookie.name == "CrushAuth" then
      has_crushauth = true
      break
    end
  end
  
  -- Return result based on the presence of the CrushAuth cookie
  if has_crushauth then
    return string.format("Resource %s found and CrushAuth cookie detected.", url)
  else
    return string.format("Resource %s found, but no CrushAuth cookie detected.", url)
  end
end

Nmap NSE CVE-2024-4040 detection script provided by ChatGPT.

Again, the Nmap NSE script work straight out of the (vi) gates:

Nmap confirms the CrushFTP target is vulnerable to CVE-2024-4040

With minimal clean up we can now share our detection script with the community:

GitHub - art-of-defence/NSE: NSE (Nmap Scripting Engine) tools for the detection of vulnerabilities.
NSE (Nmap Scripting Engine) tools for the detection of vulnerabilities. - art-of-defence/NSE

Our repository for these (and future) NSE scripts.

Conclusion

Our experiments using GenAI (ChatGPT) to create detection scripts is taking shape. Our next GenAI experiment will include basic exploitation - subscribe to be notified.

As always, if I got anything wrong,...

References

Here is the list of resources that were used to perform the exercise.

CVE-2024-4040 | AttackerKB
On Friday, April 19, 2024, managed file transfer vendor CrushFTP released information to a private mailing list on a new zero-day vulnerability affecting Crush…
GitHub - Stuub/CVE-2024-4040-SSTI-LFI-PoC: CVE-2024-4040 CrushFTP SSTI LFI & Auth Bypass | Full Server Takeover | Wordlist Support
CVE-2024-4040 CrushFTP SSTI LFI & Auth Bypass | Full Server Takeover | Wordlist Support - Stuub/CVE-2024-4040-SSTI-LFI-PoC
Nmap Scripting Engine (NSE) | Nmap Network Scanning
The Programming Language Lua
Official website of the Lua language
The Matrix (1999) ⭐ 8.7 | Action, Sci-Fi
2h 16m | 16
art-of-defence - Overview
art-of-defence has one repository available. Follow their code on GitHub.