Ticket #2913: CVE-2012-4463 mc-4.8.5: Does not sanitize MC_EXT_SELECTED variable properly

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>
This commit is contained in:
Slava Zanko 2012-10-05 18:14:28 +03:00
parent bf475ce339
commit 6bdf50c5a5
2 changed files with 141 additions and 1 deletions

View 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

View File

@ -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;
}
/* --------------------------------------------------------------------------------------------- */