Actualización: g30rg3_x me comenta que ya están disponibles los parches oficiales para estos problemas de seguridad, pueden ver los archivos modificados para las versiones 2.2.x (zip) y 2.0.x (zip).
Hace algunas horas acaban de reportar 7 problemas de seguridad en WordPress:
- WordPress Persistant XSS Vulnerability in the Default Theme (v.2.2): Los parámetros para la imagen y color de la cabecera en el tema por omisión de WordPress (Kubrick) son vulnerables. Aunque no lo probé, me parece que es parecido al que reporté hace tiempo.
- WordPress /options.php SQL Injection Vulnerability: El parámetro
page_options
no está correctamente validado en wp-admin/options.php
. Sólo los usuarios con nivel Administrador pueden explotar esta vulnerabilidad.
- WordPress /options.php Information Disclosure: Esta vulnerabilidad se deriva de la anterior, porque en
wp-admin/options.php
se asume que el nombre de las opciones son seguras.
- WordPress /edit-comments.php Database Error (Bug): Simplemente muestra un error en la consulta si el valor de la página es negativo.
- WordPress /link-import.php XSS Vulnerability: El parámetro
cat_id
no es filtrado adecuadamente, para explotarlo requiere tener un valor adecuado para el parámetro _wpnonce
.
- WordPress /upload.php XSS Vulnerability: En este caso el parámetro
style
es inseguro.
La misma persona que reportó estos bugs se tomó el trabajo de realizar un gusano que se encarga de parchar los blogs vulnerables, siempre y cuando se el servidor web tenga permisos de escritura en los archivos afectados.
En cada uno de los tickets abiertos ya existen parches oficiales disponibles (4689, 4690, 4691 y 4692). Mi parche para corregir esos problemas es ligeramente diferente:
diff:
Index: wp-admin/edit-comments.php
===================================================================
--- wp-admin/edit-comments.php (revision 5825)
+++ wp-admin/edit-comments.php (working copy)
@@ -76,7 +76,7 @@
endif;
if ( isset( $_GET['apage'] ) )
- $page = (int) $_GET['apage'];
+ $page = (int) abs($_GET['apage']);
else
$page = 1;
Index: wp-admin/link-import.php
===================================================================
--- wp-admin/link-import.php (revision 5825)
+++ wp-admin/link-import.php (working copy)
@@ -73,7 +73,7 @@
<h2><?php _e('Importing...') ?></h2>
<?php
- $cat_id = $_POST['cat_id'];
+ $cat_id = (int) $_POST['cat_id'];
if ( $cat_id == '' || $cat_id == 0 )
$cat_id = 1;
Index: wp-admin/options.php
===================================================================
--- wp-admin/options.php (revision 5825)
+++ wp-admin/options.php (working copy)
@@ -143,6 +143,7 @@
$options_to_update[] = $option->option_name;
$class = 'all-options';
}
+ $option->option_name = attribute_escape($option->option_name);
echo "
<tr>
<th scope='row'><label for='$option->option_name'>$option->option_name</label></th>
Index: wp-admin/upload-functions.php
===================================================================
--- wp-admin/upload-functions.php (revision 5825)
+++ wp-admin/upload-functions.php (working copy)
@@ -104,6 +104,8 @@
function wp_upload_form() {
$id = get_the_ID();
global $post_id, $tab, $style;
+ $style = attribute_escape($style);
+ $post_id = (int) $post_id;
$enctype = $id ? '' : ' enctype="multipart/form-data"';
?>
<form<?php echo $enctype; ?> id="upload-file" method="post" action="<?php echo get_option('siteurl') . "/wp-admin/upload.php?style=$style&tab=upload&post_id=$post_id"; ?>">
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php (revision 5825)
+++ wp-includes/functions.php (working copy)
@@ -206,6 +206,7 @@
function get_option($setting) {
global $wpdb;
+ $setting = $wpdb->escape(stripslashes($setting));
// Allow plugins to short-circuit options.
$pre = apply_filters( 'pre_option_' . $setting, false );
if ( $pre )
@@ -305,6 +306,7 @@
function update_option($option_name, $newvalue) {
global $wpdb;
+ $name = preg_replace('/[^a-z\d_-]/i', '', trim($name));
wp_protect_special_option($option_name);
if ( is_string($newvalue) )
@@ -352,6 +354,7 @@
function add_option($name, $value = '', $description = '', $autoload = 'yes') {
global $wpdb;
+ $name = preg_replace('/[^a-z\d_-]/i', '', trim($name));
wp_protect_special_option($name);
// Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
@@ -391,6 +394,7 @@
wp_protect_special_option($name);
+ $name = $wpdb->escape(stripslashes($name));
// Get the ID, if no ID then return
$option = $wpdb->get_row("SELECT option_id, autoload FROM $wpdb->options WHERE option_name = '$name'");
if ( !$option->option_id ) return false;
Los que no sepan -- o no quieran -- aplicar manualmente este parche no oficial, pueden descargar el conjunto de archivos modificados para la versión 2.2.1, úsenlo bajo vuestra propia responsabilidad. 🙂
Actualización (03/08/2007): Miquel encontró un bug en el parche que publiqué.