mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.53k stars 1.61k forks source link

Machine file parser allows code execution #6925

Open ePirat opened 4 years ago

ePirat commented 4 years ago

Describe the bug Meson uses eval to parse the the values of machine files (cross and native files), this allows code execution.

To Reproduce Create a crossfile with something like:

[properties]
example: f"{().__class__.__base__.__subclasses__()[211](['uname', '-a'])}"

Call meson with the given cross or native file:

meson --native-file=./native-file.ini build

This will execute uname -a. (The specific payload to do this might not work on other systems, as the index for the class in the subclasses array might change, this is just a example)

~/Projects/meson/meson.py --native-file=./native-file.ini build
Darwin ePirats-MBP 19.4.0 Darwin Kernel Version 19.4.0: Wed Mar  4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64 x86_64
The Meson build system
Version: 0.54.999

Expected behavior This should cause a parser error or get parsed as a example key with a string value containing f"{().__class__.__base__.__subclasses__()[211](['uname', '-a'])}"

system parameters Reproducible with meson git master (1ba62c484d3d4d1f75d59b4d9481f39914ffbb56)

ePirat commented 4 years ago

Note that this does not really has big security implications, as the user has to put the cross or native file in place in a location where meson picks it up or explicitly give it on the command line. So they usually should know whats in it and not put possibly malicious stuff in it.

But it really should be avoided to use eval here, it has a lot of other consequences for cross file parsing and makes it really hard to implement a machine file parser in any other language if users actually start to rely on the special behaviors they get from having values eval'ed, like the ability to make calculations in cross/native files like: foo: 1+1 or even string formatting like foo: 'bar {}'.format(1).

dcbaker commented 4 years ago

we really should be using ast.literal_eval like the rest of the codebase. I'm not sure that we're doing anything that it couldn't handle