Activar ASLR, PIE, RELRO, NX-Stack y hardening en FreeBSD
FreeBSD a día de hoy (9.0-RELEASE) no tiene ASLR de serie, en este artículo vamos a enseñar a aplicar un parche con soporte de ASLR, recompilar el kernel, instalarlo y la nueva sysctl para configurar el espacio aleatorio de ASLR.
Para empezar necesitamos tener las fuentes del sistema (kernel) que se instalan en: /usr/src/sys
Si no tenemos las fuentes deberemos descargarlas, el sistema más cómodo es mediante cvsup (o csup, un clon en C)
Para ello, lo primero es instalar cvsup en caso de no disponer de él:
[root@reki ~]# cd /usr/ports/net/cvsup
[root@reki /usr/ports/net/cvsup]# make install clean
Una vez instalado, debemos configurarlo:
cat > /root/RELENG_9-supfile
*default host=cvsup11.FreeBSD.org
*default base=/var/db
*default prefix=/usr
*default release=cvs tag=RELENG_9
*default delete use-rel-suffix
*default compressports-all
src-all
^D
En la configuración expuesta, se está utilizando el mirror cvsup11, recomiendo verificar el mejor en vuestra conexión.
Por otro lado, el tag es RELENG_9 que es el utilizado para FreeBSD 9. Si queréis probar lo último de lo último (Ahora mismo 10.0-CURRENT) con poner un "." como tag es suficiente.
Este supfile actualizará todo el árbol de ports de FreeBSD y todos los sources del userspace.
Si solo queréis los sources del kernel, comentar las dos lineas y añadir la siguiente: src-sys
Una vez tenemos nuestro fichero es el momento de ejecutar cvsup:
[root@reki ~]# cvsup -g -L2 /root/RELENG_9-supfile
Este proceso es bastante lento, así que recomiendo armarse de paciencia y ponerse a otra cosa :-)
Una vez finalizado deberemos de parchear nuestro kernel.
[root@reki ~]# fetch http://lists.freebsd.org/pipermail/freebsd-current/attachments/20111116/...
[root@reki ~]# cd /usr/src
[root@reki /usr/src]# patch -p1 < /root/randomize-stack-and-mmap.bin
Hmm... Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|commit 779a962519e7ead63dda24348b98f6cde8156752
|Author: Oliver Pinter
|Date: Tue Oct 4 00:24:01 2011 +0200
|
| forwardport mmap-randomization patch from 7-STABLE-op
|
| Signed-off-by: Oliver Pinter
|
|diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
|index fe01142..dc66db6 100644
|--- a/sys/kern/kern_exec.c
|+++ b/sys/kern/kern_exec.c
--------------------------
Patching file sys/kern/kern_exec.c using Plan A...
Hunk #1 succeeded at 107 (offset 1 line).
Hunk #2 succeeded at 122 (offset 1 line).
Hunk #3 succeeded at 182 (offset 1 line).
Hunk #4 succeeded at 1274 (offset -2 lines).
Hunk #5 succeeded at 1295 (offset 1 line).
Hmm... The next patch looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
|index e85b681..991a37d 100644
|--- a/sys/vm/vm_mmap.c
|+++ b/sys/vm/vm_mmap.c
--------------------------
Patching file sys/vm/vm_mmap.c using Plan A...
Hunk #1 succeeded at 68.
Hunk #2 succeeded at 101 (offset 1 line).
Hunk #3 succeeded at 260 (offset -1 lines).
Hunk #4 succeeded at 272 (offset 1 line).
done
[root@reki /usr/src]#
Este es un paso opcional, pero recomiendo añadir el flag "-fstack-protector", "-fomit-frame-pointer" y "-fPIE" en el /etc/make.conf También es recomendable instalar clang y sustituir gcc por clang. [root@reki ~]# cat /etc/make.conf CPUTYPE?= core2 # Comment from -fomit-frame-pointer to kernel compiling CFLAGS= -O3 -pipe -fno-strict-aliasing -fstack-protector -fomit-frame-pointer # -Wl,-z,relro -Wl,-z,now -D_FORTIFY_SOURCE=2 -fPIE -pie COPTFLAGS= -O3 -pipe -fno-strict-aliasing -fstack-protector -fomit-frame-pointer -funroll-loops -ffast-math # -Wl,-z,relro -Wl,-z,now -D_FORTIFY_SOURCE=2 -fPIE -pie CXXFLAGS+= -O3 -pipe -fno-strict-aliasing -fstack-protector -fomit-frame-pointer -funroll-loops -ffast-math # -Wl,-z,relro -Wl,-z,now -D_FORTIFY_SOURCE=2 -fPIE -pie FORCE_MAKE_JOBS= yes MAKE_JOBS_NUMBER= 3 KERNCONF= BSD GENERIC OPTIMIZED_CFLAGS= YES WITHOUT_X11= YES BUILD_OPTIMIZED= YES WITH_CPUFLAGS= YES WITH_OPTIMIZED_CFLAGS= YES WITHOUT_DEBUG= YES BUILD_STATIC= YES NO_PROFILE= YES CC= clang CXX= clang++ CPP= clang-cpp NO_WERROR= WERROR= NO_FSCHG= # added by use.perl 2012-06-08 14:22:50 PERL_VERSION=5.10.1
Una vez parcheado pasamos a configurar el kernel. Si no entiendes este paso, puedes ignorarlo, es opcional.
[root@reki /usr/src]# vi sys/amd64/conf/GENERIC
Una vez configurado (o si se ha dejado por defecto) hay que compilarlo:
[root@reki /usr/src]# make -j4 buildkernel KERNCONF=GENERIC
Una vez compilado, si todo ha ido bien, es hora de instalarlo (también descomentar las opciones de make.conf):
[root@reki /usr/src]# make installkernel
Ahora activaremos el soporte de NX en Stack:
cat >> /etc/sysctl.conf
kern.elf64.nxstack=1
kern.elf32.nxstack=1
^D
El siguiente paso sería compilar e instalar el userland.
[root@reki /usr/src]# make -j4 buildworld
[root@reki /usr/src]# make installworld
Ahora reiniciamos y si todo ha ido bien, deberíamos volver a tener nuestra shell :-)
[root@reki ~]# uname -a
FreeBSD reki 8.2-STABLE FreeBSD 9.0-STABLE #1: Thu Jul 19 19:01:37 CEST 2012 root@reki:/usr/obj/usr/src/sys/GENERIC amd64
Para comprobar si tenemos ASLR, se puede hacer algo como lo siguiente:
[capi_x@reki ~]$ cat > kk.c
#include <stdio.h>int main() {
float pp;
char kk[256];printf("%p\n", &pp);
printf("%p\n", kk);return(0);
}
^D
[capi_x@reki ~]$ clang -fstack-protector -fPIE -pie kk.c -o kk
[capi_x@reki ~]$ ./kk
0x7fffffff70b0
0x7fffffff7040
[capi_x@reki ~]$ ./kk
0x7fffffff9bf0
0x7fffffff9b80
[capi_x@reki ~]$
Como se puede observar, las direcciones cambian, eso es por que tenemos una implementación de ASLR.
Si queremos aumentar el tamaño de aletorización puede realizarse mediante la sysctl: kern.stackgap_random
Por defecto su valor es 65536 (16 bits) no recomiendo aumentar su valor, ya que he visto que algunos software pueden dar problemas.
Bueno, una vez terminado el artículo recomiendo leer la siguiente presentación donde se expone una arquitectura basada en FreeBSD y su securización al completo: Deploying web servers
De verdad y no es peloteo, os recomiendo leer la presentación, es una auténtica delicia con sello FreeBSD ;-)
Disclaimer: Esto es un parche no oficial, ya sabéis si todo casca, pues rollback y pasando de esto.
Update: El make.conf expuesto y el patch de ASLR funcionan perfectamente en 10.0-CURRENT a día de hoy.
P.D: Saludos a bryn1u si lees esto :)
Hasta la próxima!

