Ticket #2913: CVE-2012-4463 mc-4.8.5: Does not sanitize MC_EXT_SELECTED variable...
authorSlava Zanko <slavazanko@gmail.com>
Fri, 5 Oct 2012 15:14:28 +0000 (5 18:14 +0300)
committerSlava Zanko <slavazanko@gmail.com>
Thu, 29 Nov 2012 10:20:47 +0000 (29 13:20 +0300)
Paul Hartman reported the following (minor) security flaw into Gentoo's bugzilla:

https://bugs.gentoo.org/show_bug.cgi?id=436518

When multiple files are selected and F3 / Enter key is pressed on some of the files,
MC_EXT_SELECTED variable does not sanitize the whitespace characters properly
(leading into situation when first file is used as the actual value of MC_EXT_SELECTED
variable and the remaining files from the list are used as arguments passed to the
temporary script, created to handle F3 / Enter action on the first file).

A remote attacker could provide a specially-crafted archive and trick the local
Midnight Commander user into expanding and viewing it, which under certain
circumstances could lead to arbitrary code execution with the privileges of
the user running the mc executable.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
tests/src/filemanager/Makefile.am
tests/src/filemanager/exec_get_export_variables_ext.c [new file with mode: 0644]

index 4d754b2..26cdcfa 100644 (file)
@@ -14,7 +14,8 @@ endif
 
 TESTS = \
        do_panel_cd \
-       examine_cd
+       examine_cd \
+       exec_get_export_variables_ext
 
 check_PROGRAMS = $(TESTS)
 
@@ -23,3 +24,6 @@ do_panel_cd_SOURCES = \
 
 examine_cd_SOURCES = \
        examine_cd.c
+
+exec_get_export_variables_ext_SOURCES = \
+       exec_get_export_variables_ext.c
diff --git a/tests/src/filemanager/exec_get_export_variables_ext.c b/tests/src/filemanager/exec_get_export_variables_ext.c
new file mode 100644 (file)
index 0000000..03993a3
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+   src/filemanager - filemanager functions
+
+   Copyright (C) 2011
+   The Free Software Foundation, Inc.
+
+   Written by:
+   Slava Zanko <slavazanko@gmail.com>, 2012
+
+   This file is part of the Midnight Commander.
+
+   The Midnight Commander is free software: you can redistribute it
+   and/or modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   The Midnight Commander is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define TEST_SUITE_NAME "/src/filemanager"
+
+#include <config.h>
+
+#include <check.h>
+
+#include "lib/global.h"
+#include "src/vfs/local/local.c"
+
+#include "src/filemanager/midnight.c"
+
+#include "src/filemanager/ext.c"
+
+/* --------------------------------------------------------------------------------------------- */
+/* mocked functions */
+
+
+/* --------------------------------------------------------------------------------------------- */
+
+static void
+setup (void)
+{
+    str_init_strings (NULL);
+
+    vfs_init ();
+    init_localfs ();
+    vfs_setup_work_dir ();
+
+    mc_global.mc_run_mode = MC_RUN_FULL;
+    current_panel = g_new0(struct WPanel, 1);
+    current_panel->cwd_vpath = vfs_path_from_str("/home");
+    current_panel->dir.list = g_new (file_entry, MIN_FILES);
+    current_panel->dir.size = MIN_FILES;
+}
+
+static void
+teardown (void)
+{
+    vfs_shut ();
+    str_uninit_strings ();
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+START_TEST (sanitize_variables)
+{
+    // given
+    vfs_path_t * filename_vpath;
+    char *actual_string;
+    const char *expected_string;
+
+    current_panel->selected = 0;
+    current_panel->dir.list[0].fname = (char*) "selected file.txt";
+    current_panel->dir.list[1].fname = (char*) "tagged file1.txt";
+    current_panel->dir.list[1].f.marked = TRUE;
+    current_panel->dir.list[2].fname = (char*) "tagged file2.txt";
+    current_panel->dir.list[2].f.marked = TRUE;
+    current_panel->count = 3;
+
+    // when
+    filename_vpath = vfs_path_from_str("/tmp/blabla.txt");
+    actual_string = exec_get_export_variables (filename_vpath);
+    vfs_path_free (filename_vpath);
+
+    // then
+    expected_string = "\
+MC_EXT_FILENAME=/tmp/blabla.txt\n\
+export MC_EXT_FILENAME\n\
+MC_EXT_BASENAME=selected\\ file.txt\n\
+export MC_EXT_BASENAME\n\
+MC_EXT_CURRENTDIR=/home\n\
+export MC_EXT_CURRENTDIR\n\
+MC_EXT_SELECTED=selected\\ file.txt\n\
+export MC_EXT_SELECTED\n\
+MC_EXT_ONLYTAGGED=tagged\\ file1.txt tagged\\ file2.txt \n\
+export MC_EXT_ONLYTAGGED\n";
+
+    g_assert_cmpstr (actual_string, ==, expected_string);
+
+    g_free (actual_string);
+}
+
+END_TEST
+
+/* --------------------------------------------------------------------------------------------- */
+
+int
+main (void)
+{
+    int number_failed;
+
+    Suite *s = suite_create (TEST_SUITE_NAME);
+    TCase *tc_core = tcase_create ("Core");
+    SRunner *sr;
+
+    tcase_add_checked_fixture (tc_core, setup, teardown);
+
+    /* Add new tests here: *************** */
+    tcase_add_test (tc_core, sanitize_variables);
+    /* *********************************** */
+
+    suite_add_tcase (s, tc_core);
+    sr = srunner_create (s);
+    srunner_set_log (sr, "do_panel_cd.log");
+    srunner_run_all (sr, CK_NORMAL);
+    number_failed = srunner_ntests_failed (sr);
+    srunner_free (sr);
+    return (number_failed == 0) ? 0 : 1;
+}
+
+/* --------------------------------------------------------------------------------------------- */