classification
Title: [CVE-2020-10796] Python multiprocessing Remote Code Execution vulnerability
Type: security Stage: resolved
Components: Library (Lib) Versions: Python 3.8, Python 3.7, Python 3.6, Python 3.5, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Junyu Zhang, davin, koobs, pitrou, steve.dower, vstinner, xtreak
Priority: normal Keywords:

Created on 2020-03-22 05:49 by Junyu Zhang, last changed 2020-03-25 12:27 by steve.dower. This issue is now closed.

Files
File name Uploaded Description Edit
Python-multiprocessing-RCE-vulnerability.pdf Junyu Zhang, 2020-03-22 05:49
server.py vstinner, 2020-03-24 22:50
poc.py vstinner, 2020-03-24 22:50
Messages (9)
msg364786 - (view) Author: Junyu Zhang (Junyu Zhang) Date: 2020-03-22 05:58
description:
When we were using python to develop a distributed process service, I noticed that the default serialization parameter of Manager and ManagerBase in multiprocessing was pickl, and it didn't seem to be mentioned in the official website's documentation. This is unsafe unless our server is completely You can trust recv data, but if authkey is not set or leaked, it will cause RCE on the server side, so I applied for a CVE-ID to remind everyone to use this security issue. For details of the vulnerability and the poc code, please refer to the pdf file.
msg364788 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2020-03-22 08:15
Thanks for the report. Is this a case of the warning below?

https://docs.python.org/3.8/library/multiprocessing.html#multiprocessing.connection.Connection.recv

> Warning The Connection.recv() method automatically unpickles the data it receives, which can be a security risk unless you can trust the process which sent the message.

> Therefore, unless the connection object was produced using Pipe() you should only use the recv() and send() methods after performing some sort of authentication. See Authentication keys.
msg364789 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2020-03-22 08:17
I am not sure if this was done but CPython has a page on reporting security issues that you can use for future reports so that they can be triaged before being public.

https://www.python.org/dev/security/
msg364805 - (view) Author: Junyu Zhang (Junyu Zhang) Date: 2020-03-22 15:48
Thank you for your reply, this report is indeed the situation prompted by the warning. There will be few problems in the single-machine deployment mode. Of course, it is also possible to take advantage of the possibility of elevation of privilege. In the distributed deployment mode, the client script is leaked. The resulting authkey leak will also cause RCE problems. I have an idea. If ManagerBase can allow users to customize the serialization operation, it may be greatly relieved. Your suggestion is that I need to submit this to security@python.org Report it?
msg364867 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-03-23 17:30
Lib/multiprocessing/connection.py uses a challenge to authenticate the client. How do you connect to the server?

Yes, it's known that pickle is not safe, there is a big red warning at the top of the doc:
https://docs.python.org/dev/library/pickle.html

But please elaborate your attack scenario. How do you execute arbitrary code on a server? How do you inject code?
msg364965 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-03-24 22:50
Oh, I missed that the PDF contains a link to a PoC:
https://github.com/RGDZ-GZU/Python-Remote-code-exec/tree/master/poc

I attach a copy to this issue: server.py and poc.py.
msg364966 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-03-24 23:02
> if authkey is not set or leaked, it will cause RCE on the server side

In which situation the authkey can be empty?

Lib/mulitprocessing/process.py creates an authkey of 256 bits of entropy using:
AuthenticationString(os.urandom(32))

It's used by default if I understand correctly. I understand that the authkey can only be empty if the developer explicitly pass an empty string to authkey when the manager is created. Am I right?

--

About leaking the authkey: I don't know how the authkey is transfered to the child processes. Through a pipe controlled by the parent process?

--

> it will cause RCE on the server side

I read somewhere that multiprocessing is now supposed to accept other serialization protocol than pickle, but I failed to find the documentation :-( pickle remains the default.
msg364974 - (view) Author: Junyu Zhang (Junyu Zhang) Date: 2020-03-25 02:49
Thank you for your reply. Yes, under normal circumstances, keys are generally not leaked. I may have only considered the following attacks at the time:
1. If the client script of the distributed process is on another machine, or the key is leaked due to accidental leak.
2. When the attacker has obtained some server permissions, but not the highest permissions, and this distributed service process runs with the highest management permissions, and the attacker has read permissions to the script code, this may cause a Simple elevation.

Of course, after thinking about it carefully, I found that the above problem is just a conjecture, so now I have decided to give up reporting it as CVE, unless I find such a situation.
msg364986 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2020-03-25 12:27
Thanks for reporting this.

In future, security issues should be reported *first* through https://www.python.org/dev/security/

*Do not* request a CVE number until we've reviewed it. It causes unnecessary stress for our users who actually pay attention to those disclosures. CVEs are a tool for *us* to communicate with our users, not for researchers to communicate with us (just send us an email :) ).

Since you appear to have a number assigned, I've requested that MITRE retract it. Though it seems you may have done the same already.

Looking forward to meeting you soon on the security mailing list!
History
Date User Action Args
2020-03-25 12:27:46steve.dowersetstatus: open -> closed

nosy: + steve.dower
messages: + msg364986

resolution: not a bug
stage: resolved
2020-03-25 02:49:20Junyu Zhangsetmessages: + msg364974
2020-03-24 23:02:19vstinnersetmessages: + msg364966
2020-03-24 22:50:17vstinnersetfiles: + poc.py
2020-03-24 22:50:09vstinnersetfiles: + server.py

messages: + msg364965
2020-03-23 17:30:39vstinnersetmessages: + msg364867
2020-03-22 15:48:45Junyu Zhangsetmessages: + msg364805
2020-03-22 09:07:43koobssetnosy: + koobs
2020-03-22 08:17:44xtreaksetnosy: + vstinner
messages: + msg364789
2020-03-22 08:15:17xtreaksetnosy: + xtreak
messages: + msg364788
2020-03-22 07:17:39SilentGhostsetnosy: + pitrou, davin
2020-03-22 05:58:16Junyu Zhangsetmessages: + msg364786
2020-03-22 05:49:22Junyu Zhangcreate