Etiquetas

miércoles, 21 de febrero de 2018

SELinux ¿De forma fácil?

SELinux es una de las alternativas disponibles en Linux para MAC (Mandatory Access Control), que es una segunda y potentísima barrera de contención por encima de DAC o Discrecionay Access Control, es decir el sistema clásico de permisos en derivados de Unix.
SELinux tiene fama de resultar complejo y dificil para el recién llegado. Este artículo viene por una parte a confirmar esa percepción, pero con la esperanza de que con horas de trabajo el aprendizaje se irá completando.




SELinux fue desarrollado por la NSA junto a otras empresas como Red Hat y Mc Afee que contribuyeron mucho al proyecto. Fue incluído desde las ramas 2.6 del kernel Linux.

SELinux ¿Por qué importa usarlo?

Un kernel linux con política de MAC (Control de Acceso Obligatorio) sirve para confinar programas de usuario y servidores (demonios), como también acceso a archivos y recursos de red. De esta forma es posible aplicar tan solo el menor privilegio requerido para que una aplicación dada funcione, lo que reduce enormemente la exposición a fallas, errores de configuración o buffers overflows. Como SELinux es una forma de implementar RBAC (Role Based Access Control) su uso es altamente recomendado en aplicaciones de la industria financiera o en organizaciones donde hay que reducir al mínimo la exposición de información.
Este confinamiento de aplicaciones, usuario y recursos no reconoce el concepto de "roor" o super-
usuario y no comparte características del control de acceso discrecional como setuid/setgid.
En tiempos de Spectre y Meltdown, cualquier implementación de MAC que contribuya a ofrecer un cierto grado de seguridad adicional resulta valiosa.

Él está ahí, no lo deshabilites

En muchas oportunidades nos encontramos con algún tutorial o incluso con el vendor de alguna aplicación que diga "La aplicación X requiere deshabilitar SELinux". Eso siempre es lo último que hay que hacer. En realidad lo que eso quiere decir el vendor Y no tiene idea acerca de cómo hacer que su app funcione con SELinux.
¿Por qué deshabilitarlo es la peor idea? Porque por defecto las distribuciones actuales que utilizan SELinux (puede ser Centos o RH pero también Debian) vienen con una política ya configurada que permite que cuando ejecutamos aplicaciones como nginx o apache estas ya corran "confinadas" en un dominio SELinux. Deshabilitar SELinux globalment supone perder esa ventaja.
Pero SELinux tiene una fama bien ganada de tener una curva de aprendizaje lenta, de ser complicado por demás. Hay que decirlo también, puede ser complicado pero ofrece una solución sumamente potente para MAC.
Este artículo, breve es el resultado de haber dedicado unas cuantas horas a entender algo sobre SELinux y a escribir un módulo para ejecutar confinada una aplicación web simple. Por defecto, en un sistema con SELinux una apliación que no está descrita en la "policy" correra en modo no-confinado, es decir, como si SELinux no estuviera corriendo.
Es cierto que actualmente SELinux es mucho más sencillo de lo que acostumbraba debido a que vienen incluidas con él un set de herramientas que hacen las cosas bastante más fáciles.
Más que nada el artículo tiene por objeto describir cuál fue el proceso para escribir un módulo, lo que implicó un arduo trabajo de iteracioes prueba/error, hasta que finalmente la aplicación quedó funcionando confinada.
Antiguamente la policy de SELinux solía ser monolítica, pero actualmente se pueden escribir módulos (de alguna forma similares a los del kernel linux) que permiten escribir políticas modulares por cada aplicación. De hecho si en un sistema SELinux hacemos # semodule -l veremos todos los módulos que componen la policy, identificados en general por la aplicación que confinan.

Algo concreto con SELinux

Para esta PoC utilicé una aplicación web muy simple que suele la que uso para probar algunas cosas. Es una versión web del clásico Fortune (escrita con el micro framework flask en python). La misma, junto con la policy SELinux se puede encontrar aquí: https://github.com/retux/flask-web-fortune

La vamos a configurar con un nginx que actuará como reverse proxy:


I N T E R N E T ⇒ NGINX:80 => localhost:5000



Para escribir nuestro módulo CentOS se requieren los siguientes paquetes:

setools-console
policycoreutils-python-2.5-17.1.el7 // Este último provee el binario para /usr/sbin/semanage
policycoreutils-devel // este provee los pkg de desarrollo para escribir policies.


Con web-fortune escuchando en el puerto 5000 la aplicación correrá como unconfined:

# ps auxZ | grep web
system_u:system_r:unconfined_service_t:s0 rtxapps 12430 0.0 1.6 223476 17064 ? Ss 15:08 0:00 /usr/local/share/venvs/flask-web-fortune/bin/python /usr/local/share/applications/web-fortune/app.py

Una vez que hayamos configurado el reverse proxy para que conecte a localhost:5000 seguramente nos entraremos con una barrera que nos pone SELinux. En el audit.log veremos mensajes como este:

type=AVC msg=audit(1519064697.245:443): avc: denied { name_connect } for pid=12674 comm="nginx" dest=5000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:commplex_main_port_t:s0 tclass=tcp_socket
type=AVC msg=audit(1519064697.246:444): avc: denied { name_connect } for pid=12674 comm="nginx" dest=5000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:commplex_main_port_t:s0 tclass=tcp_socket

audit2allow es LA herramienta SELinux que servirá para todo el camino, en general siempre va a darnos alguna pista acerca de lo que hay que hacer, pero debemos tener cuidado de no seguir todo al pie de la letra.

# tail -n30 /var/log/audit/audit.log | grep avc | audit2allow


#============= httpd_t ==============

#!!!! This avc can be allowed using the boolean 'httpd_can_network_connect'
allow httpd_t commplex_main_port_t:tcp_socket name_connect;

nginx no consigue conectar al puerto TCP 5000 porque la policy no lo permite.
Como indica audit2allow, tenemos dos alternativas:

La primera utilizar booleans (httpd_can_network_connect), con este boolean vamos a habilitar varias cosas, por ejemplo que el servidor web (en este caso nginx pueda conectar diversos puertos, smtp, el 5000 como requerimos acá).

# getsebool httpd_can_network_connect
httpd_can_network_connect --> off

# setsebool httpd_can_network_connect on

Si funciona de la manera esperada lo podemos setear como Persistente (con el modificador -P)

# setsebool -P httpd_can_network_connect on

Los booleans de SELinux son como interruptores que permiten cambiar algún aspecto de la policy al vuelo. Habilitando este boolean permitieremos que las aplicaciones que corran en el dominio httpd_t puedan conectar a un puerto TCP. Este puede ser el 5000 de nuestra app o el 25 para un MTA local por ejemplo, con lo cual este boolean tiende a ser bastante utilizado.
Cabe destacar que bajo ningún concepto SELinux reemplaza a otras herramientas como iptables o firewall en general. SELinux es una capa más en el camino de la seguridad que se complementa con muchas otras.
Habilitado el boolean y con web-flask-fortune corriendo en modo no-confinado tendremos las cosas funcionando. Pero siempre hay más, siga leyendo lector.


Creando un módulo de SELinux policy "from scratch" para confinar fortune

Si por ejemplo queremos confinar una aplicación, en mi caso una web app flask que escucha en localhost:5000 y que tiene un nginx río arriba.

El comando sepolicy generate sirve para crear los archivos iniciales necesarios para compilar un módulo, o sea los .te, .fc y .if.

Ejemplo:

sepolicy generate --init -n web-fortune /home/rtxapps/.venvs/flask-web-fortune/bin/python

Nótese que el path a python es el binario con el que va a correr la app python, en este caso la versión del venv. En general el path al archivo que inicia el demonio lo podríamos tomar de ExecStart del unit file de systemd.

Después de ejecutar el .sh que provee tendremos que tener el módulo compilado e insertado en la policy de SELinux:

# semodule -l | grep web-fortune

Y después de un restart del servicio podremos ver que en contexto (más que nada el tipo) con el que corre el script ha cambiado:

# ps auxZ | grep fortune | grep -v grep
system_u:system_r:web-fortune_t:s0 rtxapps 15081 0.0 1.6 223476 17068 ? Ss 19:55 0:00 /usr/local/share/venvs/flask-web-fortune/bin/python /usr/local/share/applications/web-fortune/app.py

Puede decirse que ahora la aplicación está corriendo confinada.

Podemos ver también que SELinux etiquetó el “binario” python que inicia nuestro script:

# semanage fcontext -l | grep "fortune"
/usr/local/share/venvs/flask-web-fortune/bin/python regular file system_u:object_r:web-fortune_exec_t:s0

Este era el contexto original de fortune.txt:

ls -lZ /usr/local/share/applications/web-fortune/fortune.txt
-rwxrwxr-x. rtxapps rtxapps unconfined_u:object_r:usr_t:s0 /usr/local/share/applications/web-fortune/fortune.txt


De seguro, la app habrá quedado funcionando sin problemas porque el type web-fortune-t está corriendo en modo permissive:

# semanage permissive -l

Customized Permissive Types
Builtin Permissive Types

web-fortune_t


Por defecto en el archivo .te que nos haya generado sepolicy generate incluye una línea:

permissive web-fortune_t;

“Builtin permissive” se refiere a módulos que fueron construidos con ese tag en su archivo .te.
Esto es MUY interesante, porque indica cuál es el flujo de trabajo cuando trabajamos para “confinar” los privilegios de una app con SELinux. El modo permissive permite que una vez que hayamos insertado nuestro módulo éste haga que SELinux escriba las AVC que violen las reglas, pero eso es precisamente para que la aplicación corra sin restricciones, va a loguear los problemas y podremos ajustar el módulo para ajustarlo a la necesidad.

Hay que tener en cuenta que un módulo que corra en modo permissive no lo podremos deshabilitar, de esta forma:

# semanage -d web-fortune_t
libsemanage.semanage_direct_remove_key: Unable to remove module permissive_web-fortune_t at priority 400. (No such file or directory).
OSError: No such file or directory
Source: http://danwalsh.livejournal.com/42394.html

Para que podamos cambiar un "tipo" o app de modo permisivo o no debemos comentar en esa línea en el .te.
Pero esto define el flujo de trabajo para el desarrollo del módulo de la app. En modo permisivo la app va a funcionar sin bloqueos, pero logueando las violaciones a las reglas de la policy. Con dichas violaciones en el log (audit.log o messages) usaremos audit2allow para depurar el código. Este es un arduo camino. Nadie dijo que era fácil.

¿Qué hacer cuando lo sacamos de modo permissive y la app no anda y aparecen AVCs en el log?

El trabajo es recursivo, prueba y error. Una forma en que audit2allow nos puede ayudar -y mucho- es la siguiente:

audit2allow -a -l

O bien:

audit2allow -a -l -M nombre-modulo

Este último generará los cambios que necesitamos en un módulo (.pp) podemos ir agregando las indicaciones que nos de audit2allow a nuestros .te. El modificador -l nos dará una indicación de las AVCs ocurridas desde la última carga de la policy (o de módulo).
En el caso de este módulo, fue central agregar el contenido de la sección require:


require {
type commplex_main_port_t;
type net_conf_t;
type ldconfig_exec_t;
type bin_t;
type proc_t;
type node_t;
type shell_exec_t;
type web-fortune_t;
type cert_t;
type usr_t;
type lib_t;
type user_home_dir_t;
class tcp_socket { accept bind name_bind node_bind shutdown };
class file { execute execute_no_trans getattr open read };
}

Queda para otro artículo la comparación y la misma implementación usando otra herramienta para confinamiento, como puede ser apparmor.

Fuentes:

https://mgrepl.wordpress.com/2015/05/20/how-to-create-a-new-initial-policy-using-sepolicy-generate-tool/

Dan Walsh es la autoridad de SELinux, la mejor doc es de su autoría. Todos sus posts son más que útiles: https://danwalsh.livejournal.com/

Continuar »

viernes, 16 de febrero de 2018

Infra como codigo: manejar containers LXD con terraform

No hace falta argumentar las ventajas del uso de Infraestructura como Código, sea cuál fuere el destino, plataformas de cloud como aws, google o muchas más. Pero también es una herramienta muy práctica para gestionar como código la creación de containers de docker o lxc. En este caso me ocupo de algunos ejemplos simples para uso con LXD.

Terraform es una herramienta para construir, cambiar y versionar infraestructura de manera segura y eficiente.



Terraform y sus providers

Terraform tiene la enorme ventaja de manejar sos providers como plugins instalables, separados del binario principal. Esta es una forma de modularizar la aplicación como también de hacerla más fácilmente extensible.
Existen providers no solo para las principales plataformas de cloud (SaaS, PaaS, IaaS). Una lista de los plugins oficiales puede encontrarse en el site de terraform: https://www.terraform.io/docs/providers/
Pero también la comunidad crea otros providers, en este caso el plugin para manejar containers de LXD es: https://github.com/sl1pm4t/terraform-provider-lxd
Una vez instalado el plugin como indica la doc, en el directorio .terraform/plugins/linux_amd64/, relativo a donde tengamos nuestro "código" de terraform, podremos listar los providers:

$ terraform providers
.
├── provider.lxd

Con eso listo ya podemos crear los containers codificándolos, sigue un ejemplo simple:

providers.tf
provider "lxd" {
alias = "unix"
}

profiles.tf
resource "lxd_profile" "ssh-access" {
name = "ssh-access"

config {
limits.cpu = 1
}
}


container.tf
resource "lxd_container" "test1" {
name = "test1"
provider = "lxd.unix"
image = "images:debian/stretch/amd64"
ephemeral = false
profiles = ["default", "ssh-access"]
depends_on = ["lxd_profile.ssh-access"]


provisioner "local-exec" {
command = "lxc exec test1 -- /bin/sh -c 'apt-get update && apt-get install openssh-server -y'"
}

}

Y con terraform plan / apply ya tendremos nuestro primer container creado.
Para un aprovisionamiento simple terraform utiliza ssh, como la mayoría de las imágenes de lxd vienen sin openssh-server instalado, deberemos aprovisionarlo con el recurso local-exec.
Continuar »

domingo, 26 de marzo de 2017

Story of a Commodore 64

Almost any object can become part of a certain story. This is the story of an old Commodore 64 (8 bits computer) I got for a few dollars here in Buenos Aires. The computers was not working so this is the story of how I found the parts needed to take it back to life.


In part of my spare time I enjoy working on electronics and with nowadays is called “maker culture” and more particularly with retro-computing.
When I was a kid my first computer was a Radio Shack Color Computer II (known as coco 2). I was lucky to get that computer. At that time it gave me lot of fun and excitement. Coco was just great. Still I keep that coco with me, and is working just fine as in the old days. Of course today, it is mostly useless as you can not search the web, or even use a fancy spreadsheet.
I remember Linus Torvalds’ opinion on 8 bit computers: At those days if you had enough documentation and curiosity you could develop a good knowledge about how a computer works. Because computers were simpler than the ones that came after. That is part of the success of a computer like Raspberry Pi.
I think we can still learn a lot of those old computers. It’s just like going to a museum, but a particular one where you can play around
with objects.
Some months ago I got a Commodore 64 for a few argentine pesos. The reason why? The computer did not work. The outside was good, keyboard looked fine, case was in good shape too, but there was no video output and the power supply had been lost. No video, no power supply.
I wondered if I should have removed the pcb and put a raspberry Pi in it, but I decided first to try to repair the commodore and to get or build a power supply.

The cause of the video failure (no video at all/black screen) was the MOS-8701 chip. The chip had to be replaced, and finding one of them nowadays is not easy.
Fortunately, I was able to find a new one. The price was not cheap, but at that point I was committed to get the C64 repaired.

Then, I went to a the house of a friend of mine who owns a c64 and tested mine. With the new 8701 it was working.
Now it was necessary to get or build a power supply. C64 original PSU it was its weakest part. The power supply used to get very hot, and I mean very hot. It was placed inside a dust proof case and that contributed to the increasing heat.
So building a modern power supply using a switching psu would be fine. With parts I have lying around the house: a case, a switching 5 Vdc power supply and a transformer for 9 Vac. Finding a DIN plug the C64 uses for PSU was not easy nowadays. I almost gave up, but finally I could get one. Otherwise I would have had to order it abroad.
I put those parts inside the case, added a 2A fuse for the 9 Vac output. Tested the voltages and the DIN pinout twice, and then plugged into the C64.
The computer is working as in the old days. Now is time to get some games and show the kids how we had fun time ago.

In this video C64 and it "brand new" psu can be seen working:

-RetuX-
Continuar »

sábado, 25 de marzo de 2017

Una historia retro (computación)

Casi cualquier objeto puede convertirse en una historia. Cosas incluso con poco o nulo valor de cambio pueden tener un enorme valor de uso para alguien. Los que amamos ciertos objetos, aún más allá de las posibilidades de nuestro espacio en casa lo sabemos bien.
Esta es la historia de una Commodore 64.
A más o menos 30 años de su punto de mayor suceso en el mercado la conseguí por unos pocos pesos. Claro, no funcionaba y tampoco tenía fuente de alimentación. Lento trabajo y diversión de fin de semana, ayuda de amigos y un poco de cabezadurismo per jodere y la C64 está en funcionamiento otra vez.


Linus Torvalds se refería a las computadoras de la era de los 8 bits de una manera, me parece, muy acertada: bastaba que tuvieras acceso a la documentación e información para que desarrollaras conocimiento con y acerca de esas máquinas. No es casual que varios desarrolladores del kernel Linux sean aficionados fervientes del retro computing, quizá el caso más conocido sea el de John Linville.
Tampoco es casual el éxito de las Raspberry Pi. Dejen que sean populares y si los chicos se interesan de verdad seguramente las aprovechen. Cuanto más básica es una herramienta más necesitas desarrollar una habilidad con ella.
Creo que tantos años después sin duda alguna nostalgia cabe: tener una C64 en la Argentina de aquel tiempo era algo que no todos podíamos tener. Sin no me equivoco, fue algún aristócrata europeo el que dijo, la principal diferencia entre un hombre y un niño es el precio de sus juguetes.
Fue así: a fines de 2016 conseguí por unos pocos pesos esta Commodore 64, en buen estado externo pero sin funcionar
.
El bajo precio se justificaba porque la máquina no funcionaba, y además se le había perdido o destruido la fuente de alimentación original.
Con la ayuda de mi amigo Hernán y Alejandro -con los que desde la secundaria nos hicimos todos radioaficionados- hicimos el troubleshooting básico: pudimos detectar por qué la máquina no generaba señal de video. El chip MOS-8701 era el responsable.
Conseguirlo fue providencial. No creo que hoy en día se use ese integrado para alguna otra cosa supongo, así que me hipótesis es que habrá quedado en stock desde los años '90.
Reemplazado el chip había que encontrar una fuente de alimentación. La fuente de alimentación original de la C64 era su talón de Aquiles. Era una caja estanca que calentaba por los cuatro costados. Recuerdo un amigo de la primaria que la tenía sobre una alfombra. Un milagro que de jugar al Moon Patrol no hayamos prendido fuego la alfombra.

Esquemático de la fuente original


La fuente original era muy básica. Por supuesto no era switching, lo que hacía que fuera mucho menos eficaz. Pero eso era lo habitual para la época.
Quizá lo más revolucionario que tuvo la Apple II, primera computadora masiva de Apple fue que fue la primera en contar con una fuente switching. Era algo que la hacía cara, pero era revolucionario para cuando esa máquina salió al mercado.
El resto de las computadoras similares, no la tenía.
Entonces lo más fácil en el siglo XXI era armar un gabinete con una fuente switching y un transformador convencional para la salida de 9 VAC.
La fuente switching vino de algún switch de red que no sirvió más. Y el trafo, lo compré ex profeso. El gabinete también había pertenecido a alguna fuente y lo había guardado pensando usarlo alguna vez.

Agregué un fusible a los 9VAC (de 2A) ya que la switching provee bastante protección.

Y esa es la historia de esta C64. La fuente funcionando puede verse acá:


Continuar »

martes, 31 de enero de 2017

conky se integra cada vez mejor con KDE Plasma

Desde que usaba fluxbox como window manager en una vieja notebook Pentium III durante los primeros años 2000 siempre me gustó conky o su antecesor, torsmo.
En la mayoría de los ambientes de escritorio conky se integraba sin problemas. Con KDE lo hacía interfiriendo un poco con los widgets nativos y modificando un poco el comportamiento general del escritorio. Creo que esos días pasaron para siempre. Por lo menos ahora estoy super conforme con cómo conky se integró con Plasma.

Recientemente también conky cambió la forma en que la configuración (en general el archivo ~/.conkyrc) debe estar estructurada. La configuración que venía usando, que se puede ver en la imagen está disponible en este repo:

https://github.com/retux/conky-configs

Una breve guía sobre cómo instalarlo se puede leer en el README.

¿Cómo optimizar la configuració con Plasma?

La clave de esto la encontré por algún foro que ahora no puedo encontrar su url, pero se trata de lo siguiente:

Verán en el archivo de configuración la definición del tipo de ventana para conky es:

own_window_type = 'dock'

Bueno, esto hará la magia. Lo que debemos configurar es el comportamiento que deseamos para esa ventana, lo que en Plasma se hace de esta forma:


Fíjense que el nombre que le demos a la ventana, en este caso 'conky' es significativo. Con eso debe bastar, desde luego hay que ajustar las preferencias en la sección de texto del .conkyrc para que reflejen las características de su equipo.


Continuar »