Mitigar el CVE-2018-6389

Aunque no suele ser muy normal, de tanto en tanto aparecen vulnerabilidades en WordPress como la CVE-2018-6389.

In WordPress through 4.9.2, unauthenticated attackers can cause a denial of service (resource consumption) by using the large list of registered .js files (from wp-includes/script-loader.php) to construct a series of requests to load every file many times.

Este problema viene de los ficheros [load-scripts.php] y [load-styles.php] que permiten la carga de una serie de scripts y estilos predefinidos. En este caso hablaré del de los scripts aunque el parche a aplicar es para ambos ficheros.

NOTA: Esta entrada está documentada a fecha 2018-02-09.

Problema

Este fichero carga una lista de scripts [wp_scripts] que se encuentran en el fichero [script-loader.php]. Esta lista es de más de 180 posibles valores que daría pie a poder hacer una consulta del estilo a:

/wp-admin/load-scripts.php?c=1&load%5B%5D=eutil,common,wp-a11y,sack,quicktag,colorpicker,editor,wp-fullscreen-stu,wp-ajax-response,wp-api-request,wp-pointer,autosave,heartbeat,wp-auth-check,wp-lists,prototype,scriptaculous-root,scriptaculous-builder,scriptaculous-dragdrop,scriptaculous-effects,scriptaculous-slider,scriptaculous-sound,scriptaculous-controls,scriptaculous,cropper,jquery,jquery-core,jquery-migrate,jquery-ui-core,jquery-effects-core,jquery-effects-blind,jquery-effects-bounce,jquery-effects-clip,jquery-effects-drop,jquery-effects-explode,jquery-effects-fade,jquery-effects-fold,jquery-effects-highlight,jquery-effects-puff,jquery-effects-pulsate,jquery-effects-scale,jquery-effects-shake,jquery-effects-size,jquery-effects-slide,jquery-effects-transfer,jquery-ui-accordion,jquery-ui-autocomplete,jquery-ui-button,jquery-ui-datepicker,jquery-ui-dialog,jquery-ui-draggable,jquery-ui-droppable,jquery-ui-menu,jquery-ui-mouse,jquery-ui-position,jquery-ui-progressbar,jquery-ui-resizable,jquery-ui-selectable,jquery-ui-selectmenu,jquery-ui-slider,jquery-ui-sortable,jquery-ui-spinner,jquery-ui-tabs,jquery-ui-tooltip,jquery-ui-widget,jquery-form,jquery-color,schedule,jquery-query,jquery-serialize-object,jquery-hotkeys,jquery-table-hotkeys,jquery-touch-punch,suggest,imagesloaded,masonry,jquery-masonry,thickbox,jcrop,swfobject,moxiejs,plupload,plupload-handlers,wp-plupload,swfupload,swfupload-all,swfupload-handlers,comment-repl,json2,underscore,backbone,wp-util,wp-sanitize,wp-backbone,revisions,imgareaselect,mediaelement,mediaelement-core,mediaelement-migrat,mediaelement-vimeo,wp-mediaelement,wp-codemirror,csslint,jshint,esprima,jsonlint,htmlhint,htmlhint-kses,code-editor,wp-theme-plugin-editor,wp-playlist,zxcvbn-async,password-strength-meter,user-profile,language-chooser,user-suggest,admin-ba,wplink,wpdialogs,word-coun,media-upload,hoverIntent,customize-base,customize-loader,customize-preview,customize-models,customize-views,customize-controls,customize-selective-refresh,customize-widgets,customize-preview-widgets,customize-nav-menus,customize-preview-nav-menus,wp-custom-header,accordion,shortcode,media-models,wp-embe,media-views,media-editor,media-audiovideo,mce-view,wp-api,admin-tags,admin-comments,xfn,postbox,tags-box,tags-suggest,post,editor-expand,link,comment,admin-gallery,admin-widgets,media-widgets,media-audio-widget,media-image-widget,media-gallery-widget,media-video-widget,text-widgets,custom-html-widgets,theme,inline-edit-post,inline-edit-tax,plugin-install,updates,farbtastic,iris,wp-color-picker,dashboard,list-revision,media-grid,media,image-edit,set-post-thumbnail,nav-menu,custom-header,custom-background,media-gallery,svg-painter&ver=4.9

En principio esta dirección se puede cargar sin problema, excepto que al ser un fichero tan grande tarda unos dos segundos en generarse. Eso puede provocar que en un ataque masivo, se acabe saturando el servidor.

Situación

En estos momentos no hay un parche como tal en el código de WordPress y se plantea si esto es un problema a corregir por el propio sistema o por elementos externos (Firewall, WAF…). Otras propuestas que hay es la de limitar el número de elementos que se pueden cargar a la hora de hacer la llamada al script.

Soluciones

Aunque no existe una solución sencilla en este momento, sí que se están planteando algunas posibilidades a varios niveles.

nginx

Una primera solución que se ha dado es la de aplicar esta regla del nginx que limitaría la longitud de los parámetros a 1024 bytes. Hay que tener en cuenta que la longitud máxima es de más de 2600 bytes. Personalmente y teniendo en cuenta que la cantidad de scripts a cargar no debería ser muy elevada (25 scripts podrían tener una longitud de unos 350 bytes), reduciría el límite a 512. En cualquier caso habría que navegar por el sitio para definir en cada caso (y plantilla) qué es necesario.

location ~* ^/wp-admin/load-(scripts|styles)\.php$ {
  if ( $query_string ~* "^.{512,}$" ) {
    return 444;
  }
}

Apache HTTPD

En el caso particular de Apache HTTPD se plantea otra posible solución, que debe incluir el uso de la cookie de que un usuario ha estado navegando por el sitio web.

RewriteEngine on
RewriteCond %{HTTP_COOKIE} !wordpress_logged_in_
RewriteRule /wp-admin/load-scripts.php - [F]

Carga de los datos (PHP)

Otra posible solución que plantean en un fork de WordPress es cambiar la forma en la que se cargan los datos de este script.

Script bash para Linux

O la de ejecutar este script de Linux en la carpeta principal del WordPress.

Script PHP

De la misma forma que el paso anterior se ejecuta desde la línea de comandos de Linux, esta solución te plantea que subas el fichero a la carpeta raíz, la ejecutes (él hará cambios en los ficheros) y elimines el fichero.

Reglas de ModSecurity

Aunque siempre puedes aplicar una regla como esta a tu firewall.

SecRule REQUEST_URI "@rx (?i:/wp-admin/load-scripts.php?.*?(load%5B%5D|load\[\]|load%5B\]|load\[%5D)=([^&,]*,){20,})" "id:1,msg:'Potential use of CVE-2018-6389',deny"

Deja un comentario