Moodle is a free and open-source Course Management System (CMS), also known as a Learning Management System (LMS) or a Moodle Learning Environment (VLE). Written in PHP, it is currently used for blended learning, distance education, flipped classroom and other online learning projects in many Vietnamese and oversea schools, universities, workplaces and other sectors.
While finding 1days, 0days (one of the KPIs we must run in this year lmao),our team figured out that there had not been any public exploit for CVE-2022-35649 on Moodle v4.0.1 yet. Then we decide to make exploit, PoC and detailed analysis for this interesting CVE.
II. Installation and setup:
First we downloaded Moodle v4.0.1.
III. Findings and Analysis:
The report of National Vulnerability Database about CVE-2022-35649 told us that this vulnerability occurs due to improper input validation when parsing PostScript code in Moodle sites running GhostScript versions older than 9.50. Not at all, this report provided us with some useful references:
For me the patch is enough to continue digging deep into this CVE.
The above patch indicates that the bug is locating at
/mod/assign/feedback/editpdf/classes/pdf.php in function
ensure_pdf_file_compatible. More particularly, it is locating at line
680 in version 4.0.1.
I set a breakpoint at line
680 and started my debugging process. XDebug was still listening and we need to find what screen would execute the function
ensure_pdf_file_compatible and 680th line of code.
Firstly I took a look at the directory structure in moodle, especially the base directory
/mod/ (which is containing
Sequentially, I continued browsing
I was already logging in this moodle site so only the above highlighted case happened: a required parameter call "id" was missing while we was browsing
/moodle/mod/assign/. It was quite unfamiliar as we try browse a directory (
/moodle/mod/assign/) instead of a php file (e.g.
/moodle/mod/assign/hello.php), but the server still responded with a php file. What is this "mysterious" php file? Based on my experience in PHP Web Development, I guessed it was
Bingo! As you can see in line 5 and 8,
index.php will decide how to render itself based on
id parameter. Let's see how it would be when
id is equal to 0, 1, 2.
These above responses of Moodle site told me that:
As we logged in as a teacher,
/mod/assignis a module for teacher to create and manage assignments in a course.
There was no courses created by "teacher" as we just deployed this Moodle site and start from scratch.
idurl parameter is used to index the course. The course with
id=1is created by default when we installed Moodle from scratch.
--> we need to create a course and add an assignment in it right now.
Go inside the created assignment and we came back the module
Not only managing assignment but this screen also allow teacher to view all submissions of students for this assignment and grade them. But the debug process in the 680th line of
/mod/assign/feedback/editpdf/classes/pdf.php had not been triggered at this time. We need to learn more about the source code, check the comments first to understand what
pdf.php is doing.
Then the function containing the 680th line:
Next, the nearby line of code of the 680th:
Finally, I can conclude:
pdf.phpcontain functions to manipulate PDF files (might these functions be used to process PDF documents of assigment's submission uploaded by students?). (1)
ensure_pdf_file_compatiblefunction is used to check if the source pdf file
$tempsrcwas compatible (PDF is version 1.4) and convert it into the compatible one
$tempdstby ghostscript if it is incompatible. (2)
As for the conclusion (1), the questions is "Are there any relations between processing PDF files by ghostscript and viewing submissions?" (3). This document about a PDF submission plugin called Annotate PDF confirms the answer is yes. By default, Annotate PDF plugin is enabled with the path to ghostscript (
pathtogs variable in 677th line of
Unfortunately, the path
/usr/bin/gs is also the default location of ghostscript 9.50 in Ubuntu 20.04.5 LTS (ghostscript 9.50 is installed by default in Ubuntu 20.04.5 LTS too). It means CVE-2022-35649 is taking advantage of an old vulnerability of ghostscript 9.50 to perform RCE in Moodle. We googled for a while with the search contents "ghostscript 9.50 ubuntu 20.04.05 postscript RCE poc" and see a limited number of useful results:
RCE 0-day for GhostScript 9.50 - Payload generator from @ducnt_ is really amazing but modify it a little bit as this payload generator is used to exploit ImageMagick (ghostscript 9.50 is a component of ImageMagick). Baidu is better than Google in this case by the way:
The second search result is the most reliable one, as it is a detailed analysis from Tencent Security Emergency Response Center about this 0-day, nowadays known as CVE-2021-3781, including analysis and exploit code for GhostScript 9.50 standalone.
I do not wanna repeating what TSRC have explained about CVE-2021-3781. As Ghostscript is a PostScript interpreter, how we run postscript by ghostscript would somehow look like how we run a
.py file by python interpreter. All we need to do is replace
sleep 1000 with our another command, e.g.
Successfully reproducing CVE-2021-3781 of Ghostscript 9.50, we learned how to apply it in CVE-2022-35649 after that by continuing debug process. Back to question (3), "viewing submissions" function of teacher seems to be the root cause of triggering RCE in Ghostscript 9.50 like what we saw in my reproduction of CVE-2021-3781. Before teacher can view submission of a student, students need to submit it first, so I logged in Moodle site once again as a student, then tried to submit a pdf file containig Postscript as we have seen in the above picture.
Back to assignment screen of teacher, click "View all submissions" button.
Finally our Moodle site reached the breakpoint we hadset at line
680. I press
F10 to view how
$command variable looked like before it was exexcuted.
$command variable is quite long with some unimportant ghostscript's command options, I can write it briefly like this:
gs -sDEVICE=pdfwrite -sOutputFile='/tmp/.../target.pdf' '/tmp/.../source.pdf'
You can learn what
-sOutputFile command options of ghostscript here. Basically, the above command is used to convert
source.pdf (from a defined 'abc' type) to
target.pdf (to a defined 'xyz' file). Both
target.pdf are saved into /tmp directory, meaning that they are temporary files and will be deleted after finish the function
ensure_pdf_file_compatible (as we mentioned in conclusion (2)). In order to saving a bunch of time reading code, I came up with an idea of check whether content
source.pdf was the same as
exploit.pdf I had uploaded a few minute ago.
Bingo! So we can confirm that when
exploit.pdf was upload into Moodle server, its content was copied into a temporary file named
F10 one more time to execute line 681 and we performed RCE successfully.
Section "Findings and Analysis" has already told us the exploit idea, so I will not repeat it. To make our exploit more convenient, I have write a CVE-2022-35649 payload generator, inspired by RCE-0-day-for-GhostScript-9.50 from ducnt.
V. Patching MDL-75044 and Still Vulnarable?
To be honest, the patch for CVE-2022-35649 is a joke :D. In MDL-75044 commit, they only add
-dSAFER command option into the ghotscript command at line
680 and it is so useless to prevent CVE-2021-3781 in Ghostscript 9.50.
I tried to reproduce CVE-2022-35649 in the latest version of Moodle (Version 4.1.1+) and the exploit was still successful.
VI. Temporary Mitigation:
CVE-2022-35649 only happened in Moodle using Ghostscript 9.50, so developers must update to the latest version Ghostscript (10.0.0).