Foro de elhacker.net

Sistemas Operativos => GNU/Linux => Mensaje iniciado por: WHK en 5 Mayo 2015, 21:02 pm



Título: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 5 Mayo 2015, 21:02 pm
Hola, estoy usando la última versión de nginx y tengo una duda...

Estoy intentando de crear un sistema de baneo a través de nginx junto a un servicio estadístico de ips baneadas, el tema es que no se como hacerlo.

Lo que hice fue crear una regla muy simple en la configuración de nginx:

Código:
server{
...

location / {
if ($request_uri ~ /.ht.*) {
# Ejecutar un .sh que banee la ip por iptables y
# cree un log personalizado entre otras cosas.
return 403;
}
}
}

Se comprende lo que quiero hacer? :P la idea es que cuando alguien intente acceder a archivos no permitidos termine denegando el acceso y a demás baneandose a traves de iptables, ahora, lo que quiero principalmente es generar un log personalizado muy similar al del nginx pero que indique la razón de porque fue baneado, fecha de baneo, regla de solicitud denegada, etc.

Por eso estaba pensando pasar todo a traves de un único archivo .sh pasándole argumentos y que este se encargue de ejecutar el iptables o apf y que genere este log o que llame a un archivo en python y guarde en una base de datos en mongodb los datos de baneo... pero para lograr todo esto necesito saber si es posible ejecutar un comando sobre la linea comentada antes de retornar el 403, también sería genial que desde el mismo archivo sh se comunique por telnet al router y bloquee la ip por hardware a traves del firewall cisco asa.

Hay alguna manera de lanzar esta ejecución de alguna manera?

La segunda alternativa pero no tan efectiva sería que solamente genere un log personalizado pero tendría que tener un servicio que revise el log cada x segundos y vaya baneando las ips que tengan ciertas reglas, pero eso quiere decir que ya no será baneado sobre la primera solicitud sino cuando el servicio recorra el log, a demás al crecer el log el proceso se hará mas pesado y no es la idea.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 5 Mayo 2015, 21:30 pm
Lo unico que se me ocurre es que reescribas la url a un script en php, python o perl. No creo que puedas ejecutar iptables a menos que el que corra el script tenga permisos root.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: moikano→@ en 5 Mayo 2015, 23:08 pm
Lo unico que se me ocurre es que reescribas la url a un script en php, python o perl. No creo que puedas ejecutar iptables a menos que el que corra el script tenga permisos root.

Puedes darle permisos a www-data para que ejecute un sh como permisos de root, pero solo un sh. Es un poco peligroso, pero si solo le das permisos de escritura a root no hay peligro.

En el fichero sudoers sería algo así:

Código:
www-data   ALL=NOPASSWD:/bin/bash /path/a/tu/script.sh

También puedes usar el permiso sticky bit con:

Mentira, no es el sticky bit lo que hace eso, es el setuid. Se activa de esta forma:

Código:
chmod u+s /path/a/tu/script.sh

Eso lo que hace es que se ejecuta el fichero con los permisos del usuario propietario aunque no lo sea.

Aunque lo que no se como se pone en nginx para ejecutar un sh en una regla, pero suena interesante.

Edito: Parece que en nginx puedes ejecutar código de Lua, para ejecutar el bash script:

Código:
content_by_lua 'os.execute(" /path/a/tu/script.sh")';

La fuente: http://stackoverflow.com/questions/22891148/nginx-how-to-run-a-shell-script-on-every-request (http://stackoverflow.com/questions/22891148/nginx-how-to-run-a-shell-script-on-every-request)

Suerte.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 6 Mayo 2015, 00:01 am
Si, de hecho intenté hacer un rewrite hacia un cgi/bash pero si la persona está usando un robot para escanear puede cancelar la solucitud y cancelar la ejecución a menos que se cargue sin ninguna redirección como lo hace el mod rewrite de apache

Intentaré lo que dicen, gracias por los tips.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 6 Mayo 2015, 00:11 am
No estoy seguro de como hace el rewrite nginx, pero yo creo que es posible hacer el rewrite sin una respuesta HTTP 30X de por medio. Si vi el tema de lua pero no estaba seguro si puedes enviar parametros, por ejemplo ip. Y no hace falta mencionar... que esos parametros que estes pasando a tu archivo que tiene permisos root pueden representar un riesgo.

Edit: Nginx al parecer no hace uso de ninguna peticion intermediaria con rewrite a menos que tu le indiques.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 6 Mayo 2015, 00:59 am
Asi es, nginx para hacer todo eso lo estoy corriendo como root al igual que snort y squid, estoy haciendo un invento que si resulta bien lo transformaré en un servicio, lo bueno es que no usaré un servidor para varios sitios, usaré un servidor por sitio y ese servidor no tendrá credenciales de ningún tipo y solo harán reverse proxy asi que es muy poco probable que me hackeen el servidor a través de nginx a menos que sea un bug explotable de forma remota pero eso ya es mas difícil, para eso está snort y acciones por iptables de bloqueo preventivo pre procesamiento de datos por parte del servidor web y si lo hackean no expongo nada, con suerte la ip del servidor al que le estoy haciendo el reverse proxy aunque de todas maneras pasará a traves de una vpn configurado a traves del royter y no del sistema operativo, ais que si lo hackean da lo mismo, se levanta una instancia anterior del ec2 y se parcha el bug y listo.

Me tinca mas hacer la redirección, lo que estoy intentando es enviar un header 403 y crear un 403 personalizado en .pl el cual se va a encargar de ejecutar todo, lo único que debe hacer es leer las variables nativas de nginx, asi que todos los que  lean un 403 quedarán baneados :P

Ahora tengo que ver como puedo llevar una variable desde el archivo de configuraciones hasta el archivo perl para obtener el vector de ataque por el cual fue bloqueado.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 6 Mayo 2015, 01:37 am
Si usas FCGI, puedes pasar las variables con fastcgi_params.

http://wiki.nginx.org/FcgiExample

El documento hace mencion a PHP FPM, hay un fcgi para perl pero la verdad nunca he tratado con el.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 6 Mayo 2015, 21:44 pm
Bueno, hice funcionar fast cgi wrap pero el binario está compilado para que no se pueda iniciar en modo root :( y el lua está dificil de instalar ya que requiere la instalacion manual de versiones especificas de paquetes y no es bueno si quiero automatizar su instalación.

Lo que hice fue instalar httpd y php y lo hice correr en modo root y desde nginx hice que cuando se produjera un error 403 hiciera un reverse proxy a localhost puerto 81 a la ruta del 403.php :D y php es el encargado de hacer todo, es mas, ahora puedo utilizar mongodb con php directo o migrar a futuro a oracle si es necesario :D y httpd blindado unicamente en localhost.

Me salió muy larga la vuelta que quería hacer pero finalmente fue efectivo, tampoco creo que haya problema de carga con apache ya que las solicitudes se harán unicamente cuando se haga un baneo o algo por el estilo.

Gracias de todas maneras, a futuro buscaré una manera mas facil de hacer todo sin tener que pasar por el httpd y un doble reverse proxy xd

Ahora intentaré hacer lo que dice moikano→@ para no tener que usar todo en modo root sino solo los scripts necesarios.

Saludos.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 6 Mayo 2015, 22:23 pm
Agregué al /etc/sudoers la linea:
Código:
apache ALL=NOPASSWD:/bin/bash /var/ban/403.sh

Ahora ejecuto desde php:
Código
  1. <plaintext>
  2. <?php
  3. system('id');
  4. system('/var/ban/403.sh');
  5. system('/bin/bash /var/ban/403.sh');
  6. system('sudo /var/ban/403.sh');
  7. system('sudo /bin/bash /var/ban/403.sh');
  8. ?>

el archivo 403.sh tiene:
Código:
#!/bin/bash
id

Código:
[root@localhost ban]# ls -la
total 8
drwxr-xr-x.  2 root root   19 may  6 17:21 .
drwxr-xr-x. 22 root root 4096 may  6 17:20 ..
-rwxrwxr-x.  1 root root   15 may  6 17:21 403.sh

Le di permisos de ejecución con chmod +x 403.sh y nada, solo se ejecuta el primero con id de apache:
Código:
uid=48(apache) gid=48(apache) groups=48(apache) context=system_u:system_r:httpd_t:s0

Pero el resto nada :( apache está corriendo con permisos de apache y nginx con permisos de nginx, supuse que php al tener permisos de apache podría ejecutar el script de baneo con permisos de root pero nada.

Le acabo de poner:
Código:
apache ALL=(ALL) NOPASSWD: ALL
A sudoers para descartar un problema con la ruta o cosas así y tampoco :-/


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: moikano→@ en 6 Mayo 2015, 23:00 pm
Estás seguro que el usuario que ejecuta es apache? en debian suele ser www-data sea apache o nginx.

Aparte de eso, prueba a reinciar el servicio, ya que los permisos de sudo se cargan cuando se reinicia la sesión.

El que me suele funcionar a mi es este :

Código:
system('sudo /bin/bash /var/ban/403.sh');


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 6 Mayo 2015, 23:46 pm
Pues a mi me funciona en mi consola. ¿Sera open_basedir? ¿O quizas tu SELinux?


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 01:17 am
Pues no, aplico todos los cambios, reinicio el servidor (es centos 7) y nada, el script me dice que el id es apache y es el httpd el que está ejecutando el script en php, nginx lo único que hace es hacer de reverse proxy nada mas porque la configuración para interactuar con scripts dinámicos es mas complejo, generalmente debes usar servicios paralelos con sockets de comunicación, al final nginx nunca ejecuta finalmente el script sino el servicio de cgi, en ese caso supongo que httpd hace lo mismo pero de manera mas ordenada, nativa y automatizada, por eso mejor dejé ambos instalados.

open_basedir puede se eh, lo revisaré ahora mismo aunque por defecto debería poderse.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 7 Mayo 2015, 01:21 am
¿No te lanza ningun error? Revisa que tengas configurado PHP para lanzar errors. error_reporting y display_errors.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 02:03 am
Código:
[root@localhost ~]# tail -f /var/log/httpd/error_log
sh: /var/ban/403.sh: Permission denied
/bin/bash: /var/ban/403.sh: Permission denied
sudo: unable to open audit system: Permission denied
sudo: unable to open audit system: Permission denied

En orden sería:
Código
  1. system('/var/ban/403.sh');
  2. # sh: /var/ban/403.sh: Permission denied
  3.  
  4. system('/bin/bash /var/ban/403.sh');
  5. # /bin/bash: /var/ban/403.sh: Permission denied
  6.  
  7. system('sudo /var/ban/403.sh');
  8. # sudo: unable to open audit system: Permission denied
  9.  
  10. system('sudo /bin/bash /var/ban/403.sh');
  11. # sudo: unable to open audit system: Permission denied

Definitivamente el sudoers no funciona :( , el script en php corre con permisos de "apache" y el sudoers está habilitado para ejecutar cualquier cosa sin contraseña con sudo y nada. Cuando resulte bien dejo habilitado solo los scripts necesarios.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 02:14 am
Bueno ya busqué por algunos blogs y definitivamente el problema es el selinux tal como decías.

Intenté hacerle un bypass como se recomendaba en algunos lados pero sin éxito:
Código:
User_Alias WWW=apache
Cmnd_Alias WEBCMDS=/bin/bash /var/ban/403.sh
WWW ALL=NOPASSWD: WEBCMDS

Ahora... entiendo que por todos lados está muy restringido que un script via http se ejecute como root desde el mismo servidor hasta los sistemas de protección del mismo sistema operativo, por lo cual podría decirse que no debería hacerlo, pero entonces como lo hago si necesito que dependiendo de ciertas solicitudes http se generen acciones inmediatas a bajo nivel como cambiar la configuración de balanceos de carga, baneos por firewall, etc, no me sirve crear un log y listo, necesito que el sistema sea proactivo y rwactivo, esto quiere decir que si existe una solicitud peligrosa el usuario quede baneado al instante y no esperar a que un daemon barra un log.

En ese caso que sería mas óptimo? crear un servicio que reciba comandos? porque al final igual de todas maneras el servicio web va a tener que gatillar acciones como root, asi que no entiendo como debería hacerse sin arriesgar la seguridad de todo el sistema, no quiero tener que deshabilitar selinux.

O será que esta es una excepción a la regla?

creo que tendré que ir replanteandome si hacer esto via nginx y apache o snort directamente, veré si snort tiene la capacidad de ejecutar cosas dependiendo de cada regla.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 7 Mayo 2015, 02:30 am
Bueno, es que SELinux tiene reglas mucho mas restrictivas. Siempre y cuando sepas lo que estas haciendo y entiendas las consecuencias no hay problema, claro que no siempre es posible prever todo. Yo diria que simplemente le des los permisos adecuados bajo SELinux, no veo razon por la cual no deba permitirte estando configurando propiamente.

Creo tambien que puedes pasar de Enforcing a Permissive con SELinux aunque yo creo que es preferible en enforcing sobre todo por lo que estas haciendo de configurar los contextos adecuadamente con SELinux.

Este comando cambia el type a uno que supuestamente permite apache lanzar el script:

Código
  1. sudo chcon -t httpd_sys_script_exec_t /var/ban/403.sh


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 04:15 am
Pues si, efectivamente deja ejecutar el script pero manteniendo los permisos de apache, los que se llaman con sudo siguen sin ejecutarse :(


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 7 Mayo 2015, 04:21 am
Pues si, efectivamente deja ejecutar el script pero manteniendo los permisos de apache, los que se llaman con sudo siguen sin ejecutarse :(

Porque no tienes el setuid puesto:

Código
  1. sudo chmod 4711 /var/ban/403.sh

Si quieres usar sudo en apache vas a necesitar agregar a las politicas el typo de /usr/sbin/sudo o donde quiera que este en centos. No intentes cambiar el tipo al binario de sudo.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 04:41 am
Bueno, para ir descartando puse selinux en modo permisivo y reinicié la maquina, ahora ejecuto:

Código:
[root@localhost ~]# su apache -s /bin/bash
bash-4.2$ id
uid=48(apache) gid=48(apache) grupos=48(apache) contexto=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
bash-4.2$ sudo id
uid=0(root) gid=0(root) grupos=0(root) contexto=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
bash-4.2$ exit
exit

Ahora si efectivamente el sudoers funciona perfectamente, pero el script en php no puede ejecutar el mismo comando a pesar de que tenga el mismo permiso. El log de errores dice:

Citar
sudo: sorry, you must have a tty to run sudo

Será que debo asignarle un bash al usuario apache dentro del /etc/passwd?


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 7 Mayo 2015, 04:45 am
Pruebalo con shell_exec en lugar de system.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 04:51 am
El mismo mensaje de error y ya agregué /bin/bash al usuario apache desde /etc/passwd y al ejecutar su apache entra directamente al bash, pero aun así quiere funcionar en php, talves sea algo de sudoers.


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: MinusFour en 7 Mayo 2015, 05:04 am
Vaya yo pense que shell_exec usa una tty pero parece que no (la verdad no se porque pense eso). Aparentemente puedes hacer un bypass de eso con:

Código:
Defaults:apache !requiretty

Tambien puedes hacerlo por comando aparentemente, revisa aqui:

http://unix.stackexchange.com/questions/79960/how-to-disable-requiretty-for-a-single-command-in-sudoers

No funciono lo del setuid?


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 05:11 am
eaeaeaaa ahi sii :D pero me funciona con system() no con shell_exec(), no se porque pero ya no es mi prioridad xD

Ahora volveré a habilitar selinux como estaba y configuraré el script para que pueda ser ejecutado por apache para no afectar la seguridad nativa del sistema :P


Título: Re: Ejecutar comandos desde las reglas de Nginx
Publicado por: WHK en 7 Mayo 2015, 05:30 am
Bueno, ya está todo ok y funcionando perfectamente :D muchas gracias por el tiempo y la paciencia.

Saludos.