La funcionalidad de subida de archivos a Joomla restringe el tipo de los
archivos en base a una lista blanca. Por ejemplo, un usuario podría
subir archivos del tipo jpeg, pdf, xls, etc, pero por otro lado no
estaría permitida la subida de archivos que contuvieran código PHP. Para
impedir esto en esa lista blanca se excluyen extensiones como ‘.php’.
El problema reside en que la función que comprueba esto no tiene en
cuenta extensiones nulas, es decir, extensiones que solo tengan el '.'.
Veamos el código de 'libraries/joomla/filesystem/file.php'.
La función miembro que obtiene las extensiones de la clase JFile:
public static function getExt($file)
{
$dot = strrpos($file, '.') + 1;
return substr($file, $dot);
}
'strrpos' es una función que busca la última ocurrencia de una subcadena
dentro de una cadena o lo que es lo mismo (y más eficiente): busca la
primera ocurrencia de una subcadena en una cadena comenzando desde el
final hasta el principio.
Ante un archivo denominado
'shell.php.' el valor de la variable 'dot' valdrá 10 ya que la cadena termina con un punto.
La función miembro termina retornando el valor de la función 'substr'.
Esta función retorna una subcadena correspondiente a la cadena 'file'
desde la posición 'dot'. Como sabemos que 'dot' vale 10 y la cadena
'file' tiene como longitud 10 lo que retornará la función será una
cadena vacía.
Si ahora observamos el código sin parchear del archivo
'/administrator/components/com_media/helpers/media.php':
$format = strtolower(JFile::getExt($file['name']));
$allowable = explode(',', $params->get('upload_extensions'));
$ignored = explode(',', $params->get('ignore_extensions'));
if (!in_array($format, $allowable) && !in_array($format, $ignored))
{
$err = 'COM_MEDIA_ERROR_WARNFILETYPE';
return false;
}
En la primera linea, con nuestra cadena
'shell.php.', sabemos que retornará falso:
$format = strtolower(JFile::getExt($file['name']));
Posteriormente dicho valor se usará en la comparación:
if (!in_array($format, $allowable) && !in_array($format, $ignored))
Esto quiere decir que si de dan las dos condiciones entonces y solo
entonces se provocará un error en la subida de archivos y se abortará la
operación.
La primera expresión retornará 'true' ya que la cadena vacía no forma
parte de las extensiones permitidas y el 'false' está negado. La segunda
parte, y aquí viene lo ingenioso, es que estamos buscando la cadena
vacía en un array vacío. Esto es debido a que Joomla no tienen
extensiones ignoradas por defecto y por lo tanto dicha función retornará
'true', pero como estamos negando el valor, finalmente lo convertimos a
'false' y con esto hemos evadido la restricción, ya que siendo un AND
se deberían haber evaluado las dos condiciones a 'true'.
El fallo ha sido corregido y afectaría a las versiones anteriores a
la 2.5.13 inclusive de la rama 2.5 y anteriores a la 3.1.4 también
inclusiva. El CVE está pendiente de su publicación.
Fuente:
Hispasec