CVE-2023-44451 (published 2024-05-03T03:16Z)

Linux Mint Xreader EPUB File Parsing Directory Traversal Remote Code Execution Vulnerability. This vulnerability allows remote attackers to execute arbitrary code on affected installations of Linux Mint Xreader. User interaction is required to exploit this vulnerability in that the target must visit a malicious page or open a malicious file.\n\nThe specific flaw exists within the parsing of EPUB files. The issue results from the lack of proper validation of a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to execute code in the context of the current user. Was ZDI-CAN-21897.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/linuxmint/xreader
commit_details: repo_url: https://github.com/linuxmint/xreader
author: Michael Webster
author_date: 2023-09-04 13:37:42-04:00
msg: epub: Prevent path traversal when extracting files [CVE-2023-44451]

Test each file's resolved path against the temporary directory
before extracting.

Fixes:
CVE-2023-44451 - Linux Mint Xreader EPUB File Parsing Directory
Traversal Remote Code Execution Vulnerability.

This vulnerability was discovered by:
Febin Mon Saji working with Trend Micro Zero Day Initiative
repository: repo_url: https://github.com/linuxmint/xreader
repo_name: linuxmint/xreader
description: A generic Document Reader
repo_language: C
owner: linuxmint
file_changes: filename: epub-document.c
change_type: ModificationType.MODIFY
diff: @@ -665,7 +665,7 @@ check_mime_type(const gchar* uri,GError** error)
 }
 
 static gboolean
-extract_one_file(EpubDocument* epub_document,GError ** error)
+extract_one_file(EpubDocument* epub_document, GFile *tmp_gfile, GError ** error)
 {
     GFile * outfile ;
     gsize writesize = 0;
@@ -696,6 +696,21 @@ extract_one_file(EpubDocument* epub_document,GError ** error)
     if (g_strrstr(currentfilename, ".html") != NULL)
         g_string_insert_c (gfilepath, gfilepath->len-4, 'x');
 
+    outfile = g_file_new_for_path (gfilepath->str);
+    g_autofree gchar *rpath = g_file_get_relative_path (tmp_gfile, outfile);
+
+    if (rpath == NULL)
+    {
+        g_set_error_literal (error,
+                             EV_DOCUMENT_ERROR,
+                             EV_DOCUMENT_ERROR_INVALID,
+                             _("epub file is invalid or corrupt"));
+        g_critical ("Invalid filename in Epub container - '%s'", (gchar *) currentfilename);
+        g_object_unref (outfile);
+        result = FALSE;
+        goto out;
+    }
+
     /*if we encounter a directory, make a directory inside our temporary folder.*/
     if (directory != NULL && *directory == '\0')
     {
@@ -723,7 +738,6 @@ extract_one_file(EpubDocument* epub_document,GError ** error)
 		g_string_free(dir_create,TRUE);
     }
 
-    outfile = g_file_new_for_path(gfilepath->str);
     outstream = g_file_create(outfile,G_FILE_CREATE_PRIVATE,NULL,error);
     gpointer buffer = g_malloc0(512);
     while ( (writesize = unzReadCurrentFile(epub_document->epubDocument,buffer,512) ) != 0 )
@@ -751,6 +765,7 @@ extract_epub_from_container (const gchar* uri,
                              EpubDocument *epub_document,
                              GError ** error)
 {
+    GFile *tmp_gfile = NULL;
     GError *err = NULL;
     epub_document->archivename = g_filename_from_uri(uri,NULL,error);
 
@@ -812,9 +827,11 @@ extract_epub_from_container (const gchar* uri,
         goto out;
     }
 
+    tmp_gfile = g_file_new_for_path (epub_document->tmp_archive_dir);
+
     while ( TRUE )
     {
-        if ( extract_one_file(epub_document,&err) == FALSE )
+        if ( extract_one_file(epub_document, tmp_gfile, &err) == FALSE )
         {
             if (err) {
                 g_propagate_error (error, err);
@@ -835,6 +852,7 @@ extract_epub_from_container (const gchar* uri,
     }
 
 out:
+    g_clear_object (&tmp_gfile);
     unzClose(epub_document->epubDocument);
     return result;
 }

programming_language: C