Summary
An unsafe deserialization vulnerability was identified in the endpoints used to save configurations for Frigate. This can lead to unauthenticated remote code execution. This can be performed through the UI at /config
or through a direct call to /api/config/save
.
Exploiting this vulnerability requires the attacker to both know very specific information about a user's Frigate server and requires an authenticated user to be tricked into clicking a specially crafted link to their Frigate instance.
This vulnerability could exploited by an attacker under the following circumstances:
- Frigate publicly exposed to the internet (even with authentication)
- Attacker knows the address of a user's Frigate instance
- Attacker crafts a specialized page which links to the user's Frigate instance
- Attacker finds a way to get an authenticated user to visit their specialized page and click the button/link
Details
Input is initially accepted through http.py
at frigate/http.py:998:
@bp.route("/config/save", methods=["POST"])
def config_save():
save_option = request.args.get("save_option")
new_config = request.get_data().decode()
The user-provided input is then parsed and loaded by load_config_with_no_duplicates
at frigate/config.py:1244:
@classmethod
def parse_raw(cls, raw_config):
config = load_config_with_no_duplicates(raw_config)
return cls.parse_obj(config)
However, load_config_with_no_duplicates
does not sanitize this input by merit of using yaml.loader.Loader
which can instantiate custom constructors. A provided payload will be executed directly at frigate/util/builtin.py:110:
PreserveDuplicatesLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, map_constructor
)
return yaml.load(raw_config, PreserveDuplicatesLoader)
This vulnerability was found using CodeQL’s Deserialization of user-controlled data query for Python.
Impact
This issue may lead to pre-authenticated Remote Code Execution.
Proof of Concept:
- Start Frigate in Docker for ease of setup.
- Navigate to
localhost:5000/config
.
- Enter the following content into the config, and save the configuration:
!!python/object/apply:os.popen
- touch /tmp/pwned
- Note that
/tmp/pwned
is created in the container. This access can also be extended to write to mounted filesystems if not mounted as read-only.
Summary
An unsafe deserialization vulnerability was identified in the endpoints used to save configurations for Frigate. This can lead to unauthenticated remote code execution. This can be performed through the UI at
/config
or through a direct call to/api/config/save
.Exploiting this vulnerability requires the attacker to both know very specific information about a user's Frigate server and requires an authenticated user to be tricked into clicking a specially crafted link to their Frigate instance.
This vulnerability could exploited by an attacker under the following circumstances:
Details
Input is initially accepted through
http.py
at frigate/http.py:998:The user-provided input is then parsed and loaded by
load_config_with_no_duplicates
at frigate/config.py:1244:However,
load_config_with_no_duplicates
does not sanitize this input by merit of usingyaml.loader.Loader
which can instantiate custom constructors. A provided payload will be executed directly at frigate/util/builtin.py:110:This vulnerability was found using CodeQL’s Deserialization of user-controlled data query for Python.
Impact
This issue may lead to pre-authenticated Remote Code Execution.
Proof of Concept:
localhost:5000/config
./tmp/pwned
is created in the container. This access can also be extended to write to mounted filesystems if not mounted as read-only.