Detección de web shells con NeoPI y técnicas de evasión

Hoy en día, muchas aplicaciones web se desarrollan utilizando lenguajes de scripting como PHP, Python, Ruby, Perl, etc. Estos lenguajes pueden ser lo suficientemente complicados para que un pequeño fallo pueda llegar a permitir la ejecución de código arbitrario en el servidor.

Cuando una de estas condiciones es identificada por un atacante, casi con total seguridad intentará subir un web shell para mantener el acceso al servidor comprometido, permitiendo normalmente la ejecución de comandos del sistema y el acceso a archivos.

Pero, ¿cómo detectar el código de estos backdoors en un servidor con cientos o quizás miles de páginas?

Si la shell no está ofuscada, podremos realizar una búsqueda rápida en base a una serie de patrones aunque, eso sí, obtendremos numerosos falsos positivos. Por ejemplo encontraríamos la mítica C99 con:

grep -RPn "(system|phpinfo|pcntl_exec|python_eval|base64_decode|gzip|mkdir|fopen|fclose|readfile|passthru)" /pathto/webdir/

Otra opción sería utilizar herramientas basadas en firmas como Linux Malware Detect (LMD), que encontrará algunas de las más típicas web shells. Sin embargo, ¿cómo detectaríamos aquellas shells que hayan sido modificadas/ofuscadas para ocultarse?

Para ello podemos utilizar NeoPI, un script en Python que utiliza varios métodos estadísticos para descubrir este tipo de contenido ofuscado o cifrado dentro de scripts y ficheros de texto.

Esta herramienta escaneará recursivamente los ficheros del directorio indicado y los puntuará en base a los resultados de las pruebas. Este ranking nos ayudará a identificar con una alta probabilidad de acierto qué ficheros podrían tener web shells ofuscadas:

root@testbed:~# ./neopi.py -z -e -l -i -s /var/www/ \.php$

[[ Total files scanned: 10235 ]]
[[ Total files ignored: 0 ]]
[[ Scan Time: 48.170000 seconds ]]

[[ Top 10 entropic files for a given search ]]
6.1817 /var/www/gallery/lang/chinese_gb.php
6.1784 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-cn.php
6.1710 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-tw.php
5.8753 /var/www/blog/wp-admin/js/revisions-js.php
5.7846 /var/www/gallery/lang/japanese.php
5.7306 /var/www/webacoo.php
5.6484 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/cs.php
5.6296 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/sk.php
5.6203 /var/www/plugins/system/nonumberelements/helper.php
5.6133 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/pl.php

[[ Top 10 longest word files ]]
745 /var/www/gallery/include/exif_php.inc.php
745 /var/www/gallery/exifmgr.php
741 /var/www/gallery/lang/japanese.php
728 /var/www/blog/wp-admin/js/revisions-js.php
522 /var/www/blog/wp-includes/functions.php
516 /var/www/libraries/tcpdf/tcpdf.php
474 /var/www/plugins/content/jw_allvideos/includes/sources.php
456 /var/www/blog/wp-content/plugins/sexybookmarks/includes/html-helpers.php
436 /var/www/gallery/lang/chinese_gb.php
354 /var/www/blog/wp-includes/class-simplepie.php

[[ Average IC for Search ]]
0.0372679517799

[[ Top 10 lowest IC files ]]
0.0198 /var/www/webacoo.php
0.0206 /var/www/gallery/lang/chinese_gb.php
0.0217 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-tw.php
0.0217 /var/www/plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/langs/zh-cn.php
0.0217 /var/www/templates/system/index.php
0.0217 /var/www/administrator/templates/system/index.php
0.0222 /var/www/blog/wp-content/themes/lightword/alternatives/404.php
0.0226 /var/www/blog/wp-admin/js/revisions-js.php
0.0270 /var/www/includes/HTML_toolbar.php
0.0272 /var/www/templates/beez/html/com_user/reset/complete.php

[[ Top 10 signature match counts ]]
43 /var/www/gallery/include/themes.inc.php
43 /var/www/gallery/themes/sample/theme.php
26 /var/www/blog/wp-admin/includes/class-ftp.php
19 /var/www/blog/wp-content/plugins/nextgen-gallery/lib/imagemagick.inc.php
14 /var/www/libraries/geshi/geshi/php.php
13 /var/www/blog/wp-includes/Text/Diff/Engine/native.php
10 /var/www/blog/wp-includes/js/tinymce/plugins/spellchecker/classes/PSpellShell.php
9 /var/www/gallery/include/functions.inc.php
8 /var/www/blog/wp-includes/js/tinymce/plugins/spellchecker/config.php
8 /var/www/blog/wp-admin/includes/class-wp-filesystem-ssh2.php

[[ Top 10 compression match counts ]]
1.0704 /var/www/administrator/templates/system/index.php
1.0704 /var/www/templates/system/index.php
1.0000 /var/www/blog/wp-content/plugins/sexybookmarks/includes/index.php
1.0000 /var/www/blog/wp-content/plugins/sexybookmarks/js/index.php
0.9663 /var/www/blog/wp-content/themes/lightword/alternatives/404.php
0.8958 /var/www/includes/mambo.php
0.8860 /var/www/includes/joomla.php
0.8821 /var/www/includes/vcard.class.php
0.8818 /var/www/includes/PEAR/PEAR.php
0.8796 /var/www/includes/HTML_toolbar.php

[[ Top cumulative ranked files ]]
122 /var/www/webacoo.php
202 /var/www/blog/wp-admin/js/revisions-js.php
528 /var/www/plugins/content/jw_allvideos/includes/elements/header.php
912 /var/www/plugins/content/jw_allvideos/includes/helper.php
984 /var/www/modules/mod_archive/helper.php
1100 /var/www/libraries/bitfolge/vcard.php
1210 /var/www/administrator/components/com_content/elements/article.php
1240 /var/www/gallery/addfav.php
1246 /var/www/administrator/components/com_installer/admin.installer.php
1258 /var/www/administrator/components/com_config/views/component/view.php

Encontraremos emelco, una shell osfuscada y una wso metida al final de una imagen, pero también hay que decir que esta herramienta no es infalible y que, si el atacante pone un poco de empeño, se pueden evavir sus métodos de detección:

- Strings largas: NeoPI identifica las cadenas largas que normalmente representan código ofuscado. Se podrían añadir espacios para separar el string (base64_decode los va a ignorar).

- Entropía: NeoPI calcula la entropía de Shannon de los datos y devuelve un valor float entre 0 y 8. Si metemos espacios despues de cada caracter del string en base64 aumentamos el largo del archivo y la entropia va a ser menor. Tambien se puede agregar un comentario con los caracteres suficientes para que la entropia baje lo suficiente.

- Índice de coincidencia (I.C.): esta técnica se basa en el cálculo de las coincidencias de combinaciones de caracteres comparadas con las de un texto de ejemplo con la misma distribución. Un bajo IC indicará una posible ofuscación o cifrado. Teóricamente se podría intentar modificar el índice añadiendo caracteres basura o junk.

- Firmas: la típica búsqueda de patrones. Evitando el uso de eval(), system() y demás funciones comunes de las webshells. Se pueden usar funciones globales o 'strrev' ($b=strrev("edoced_4"."6esab")).


Referencias:
NeoPI in the Wild - Neohapsis
Bypasseando NeoPI - El rincon de seth
Maths behind web shell code detection - Anestis Bechtsoudis

Web Shell Detection Using NeoPI - InfoSec

Comentarios

  1. Me gusta mucho la entrada, lo interesante es que identificar este tipo de archivos parece ser bastante sencillo cuando tenemos acceso al codigo, basta con seguir la ruta de los archivos con permisos de escritura y gripear funciones como exec o shell_exec.-

    ResponderEliminar

Publicar un comentario