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_optionsno está correctamente validado enwp-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.phpse 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_idno 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
stylees 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:
===================================================================
--- 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é.

