Headline
CVE-2022-35411: Remote Code Execution 0-day in rpc.py - Elias Hohl - Medium
rpc.py through 0.6.0 allows Remote Code Execution because an unpickle occurs when the “serializer: pickle” HTTP header is sent. In other words, although JSON (not Pickle) is the default data format, an unauthenticated client can cause the data to be processed with unpickle.
There is an Unauthenticated Remote Code Execution vulnerability in https://pypi.org/project/rpc.py/. No specific configuration is required, it works with the scripts from the “examples” folder. Versions v0.4.2 to v0.6.0 (latest) are affected. The maintainer has not replied to my emails in a time frame of two weeks, so I decided to disclose the vulnerability. The package has around 150 stars on Github at the time of writing and is advertised in the official ASGI documentations: https://asgi.readthedocs.io/en/latest/implementations.html
According to the rpc.py documentation: Currently supports three serializers, JSON, Pickle, Msgpack and CBOR. JSON is used by default. You can override the default JSONSerializer with parameters.
This is, however, not the whole truth. Looking at the code, one can see that this function somehow chooses the serializer according to the request headers:
The get_serializer function:
All we need to do is to pass the request header serializer: pickle and we can execute arbitrary code on the server by sending a malicious pickle payload.
The attack works against both sync_server.py and async_server.py from the “examples” folder.
The full exploit code can be found here:
Related news
rpc.py version 0.6.0 suffers from a remote code execution vulnerability.
rpc.py through 0.6.0 allows Remote Code Execution because an unpickle occurs when the "serializer: pickle" HTTP header is sent. In other words, although JSON (not Pickle) is the default data format, an unauthenticated client can cause the data to be processed with unpickle. [Per the maintainer](https://github.com/abersheeran/rpc.py/issues/22), rpc.py is not designed for an API that is open to the outside world, and external requests cannot reach rpc.py in real world use. A [fix](https://github.com/abersheeran/rpc.py/commit/491e7a841ed9a754796d6ab047a9fb16e23bf8bd) exists on the `master` branch. As a workaround, use the following code to turn off pickle in older versions: ``` del SERIALIZER_NAMES[PickleSerializer.name] del SERIALIZER_TYPES[PickleSerializer.content_type]