Hello everyone, this post is to complete the previous post. Indeed I missed another vulnerability even if it was right in front of me. This vulnerability also allows an authenticated attacker to get a PHP code evaluation and consequently to execute commands on the underlying system.

I apologize for the double post. We will now get to the heart of the matter.

How ?

An authenticated user may by changing his display preferences get code execution.

The exploitation is done in three steps:

  1. First the attacker modifies the parameter $_POST['display_navigation'] see the request below.

alt text

  1. Then he saves its navigation parameters.

alt text

  1. The attacker only has to request a page from the private space.

alt text

Which from a browser point of view gives the following result.

alt text

Why ?

As I explained in the introduction, I partially missed this vulnerability.

The form allowing a user to modify his preferences is governed by the function formulaires_configurer_preferences_traiter_dist().

File: <ROOT>/prive/formulaires/configurer_preferences.php


...

/**
 * Traitements du formulaire de préférences d'un auteur dans l'espace privé
 *
 * @return array
 *     Retours des traitements
 **/
function formulaires_configurer_preferences_traiter_dist() {

	if ($couleur = _request('couleur')) {
		$GLOBALS['visiteur_session']['prefs']['couleur'] = $couleur;
	}
	if ($display = _request('display')) {
		$GLOBALS['visiteur_session']['prefs']['display'] = $display;
	}
	if ($display_navigation = _request('display_navigation')) {
		$GLOBALS['visiteur_session']['prefs']['display_navigation'] = $display_navigation;
	}
	if (!is_null($display_outils = _request('display_outils'))) {
		$GLOBALS['visiteur_session']['prefs']['display_outils'] = $display_outils;
	}

	if (intval($GLOBALS['visiteur_session']['id_auteur'])) {
		include_spip('action/editer_auteur');
		$c = array('prefs' => serialize($GLOBALS['visiteur_session']['prefs']));

		if (_request('imessage')) {
			$c['imessage'] = _request('imessage');
		}

		auteur_modifier($GLOBALS['visiteur_session']['id_auteur'], $c);
	}

	if ($spip_ecran = _request('spip_ecran')) {
		// Poser un cookie,
		// car ce reglage depend plus du navigateur que de l'utilisateur
		$GLOBALS['spip_ecran'] = $spip_ecran;
		include_spip('inc/cookie');
		spip_setcookie('spip_ecran', $_COOKIE['spip_ecran'] = $spip_ecran, time() + 365 * 24 * 3600);
	}

	return array('message_ok' => _T('config_info_enregistree'), 'editable' => true);
}

What we are interested in can be summarized as:

File: <ROOT>/prive/formulaires/configurer_preferences.php


...

/**
 * Traitements du formulaire de préférences d'un auteur dans l'espace privé
 *
 * @return array
 *     Retours des traitements
 **/
function formulaires_configurer_preferences_traiter_dist() {

    ...

	if ($display_navigation = _request('display_navigation')) {
		$GLOBALS['visiteur_session']['prefs']['display_navigation'] = $display_navigation;
	}

    ...

	return array('message_ok' => _T('config_info_enregistree'), 'editable' => true);
}

As we can see the variable $GLOBALS['visiteur_session']['prefs']['display_navigation'] is controlled by an attacker. After that, this one is returned by the function init_body_class() before being evaluated.

File: <ROOT>/ecrire/inc/commencer_page.php


...

function init_body_class() {

    ...

	$spip_display_navigation = isset($GLOBALS['visiteur_session']['prefs']['display_navigation'])
		? $GLOBALS['visiteur_session']['prefs']['display_navigation']
		: 'navigation_avec_icones';

    ...

	return $GLOBALS['spip_ecran'] . " $spip_display_navigation $spip_display_outils " . $display_class[$GLOBALS['spip_display']];
}

...