martes, 29 de enero de 2008

Re: BoF en inet_network(), afecta a Servidor DNS: BIND

Bien, primero pense que era la variable "val", que sumada al corrimiento de bits que se le hace, podia sobre escribir en la memoria asi que me puse un ejemplo para ver si servia:

Código
int main() {
unsigned long prueba;
long i;
prueba = 0xf;
i = 0;
while(i < 20) {
printf("Prueba: %i\n",prueba);
i++;
prueba = (prueba << 4) + 0xf;
}
return 0;
}

sin embargo no fue asi, me acorde que el corrimiento de Bits se hace en el microprocesador, y el resultado va a la RAM, (Claro que si la variable es register no es asi). cry estoy medio perdido.

Por ahi he oido que los BoF del tipo Off-By-One no son explotables, sin embargo tambien he visto ejemplos en casos donde tienes algo de control del entorno (local) y las condiciones del BoF son casi Optimas, digamos pila Bien alineada capacidad de meter el shell y etc.. el xploit si puede ser posible.

Esto solo me interesa por el reto de poder hacer que una aplicacion Ejecute tu codigo por gusto memeramente educativo. grin

Bueno entre las pruebas que estuve haciendo he visto que la aplicacion que tengo de prueba puede recivir cadenas como las que siguen sin colgarse:

Código:
%./test_network 0xfffff00000011.0xfabcd000000003.0xa.0x90
0x11030a90

pero no nos ganamos nada ya que no ponemos nada en la memoria, las ffff se pierden en el corrimiento de bits hacia la izquierda dentro del microprocesador. sad

Un saludo!!

lunes, 28 de enero de 2008

Re: BoF en inet_network(), afecta a Servidor DNS: BIND

En la pagina de BIND: BIND Vulnerabilities


Impact:

Applications linked against libbind which call inet_network() with untrusted inputs could lead to a denial-of-service or potentially code execution.

Note that none of the applications shipped with BIND 8 or BIND 9 call inet_network().


Veamos La pagina nos dice nuevamente lo mismo Podemos hacer un DoS al servidor BIND, o podemos ejecutar codigo arbitrareo en el equipo que aloja el servidor.


Ahora

Código:
Index: inet_network.c
diff -u inet_network.c:1.5 inet_network.c:1.6
--- inet_network.c:1.5 Wed Apr 27 04:56:21 2005
+++ inet_network.c Tue Jan 15 04:02:01 2008
@@ -84,9 +84,9 @@
}
if (!digit)
return (INADDR_NONE);
+ if (pp >= parts + 4 || val > 0xffU)
+ return (INADDR_NONE);
if (*cp == '.') {
- if (pp >= parts + 4 || val > 0xffU)
- return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
}

Viendo las diferencias vemos que la version, 1.5 del archivo vulnerable es casi exactamente lo mismo solo movieron de lugar la siguiente Intruccion:

Código
 if (pp >= parts + 4 || val > 0xffU)
return (INADDR_NONE);

En la version Vulnerable esta dentro del if (*cp == '.') y la version NO vulnerable esta afuera antes de if (*cp == '.'), lo cual me indica que la clave de esto debe estar en saber manejar el formato de entrada con los Puntos '.'. Ya me he impreso el codigo fuente vulnerable y lo estoy analizando paso por paso, ya que no he podido encontrar un input que vulnere el codigo.

viernes, 25 de enero de 2008

BoF en inet_network(), afecta a Servidor DNS: BIND

Bien, recientemente he empesado a ver en la lista de SECURITY ADVISORIES de FreeBSD, la cual normalmente no veia, sin embargo quiero ser un buen adminsitrador del sistema que utilizo. wink y estar al dia con las actulizaciones grin. he visto que hay algunos bugs, ya descubiertos con todo y parche. Obviamente anuncian esto cuando ya se tiene el parche tongue, pero bueno el Motivo de este mensaje es el siguente:

Ver si somos o mas bien soy capaz de construir un exploit para dicha Vulnerabilidad, he hecho exploits para programas sencillos, y BoF bien ubicados, pero de ahi en mas no lo he hecho con aplicaciones complejas.

Por si alguien me quiere ayudar... se lo agradecere de antemano.



Bien los link de bug que me intereso son los siguentes:


Ahora para los que no sepen y quieran enterarse, BIND, es un Servidor DNS muy extendido hoy en dia, con la ayuda de este, ustedes pueden entrar a google, o al foro.

Mas informacion en BIND by Wikipedia

La funcion donde se encuentra la falla, es una funcion estandar en libc, esto quiere decir y por si no vieron los primeros Links, FreeBSD no es el unico Afectado por esto, tambien hay muchas Versiones de Linux, UNIX, etc. Y ademas todas las versiones del Servidor BIND, hasta ultima version de 22/01/2008.

La pagina de BIND, considera esto como un Riesgo de Seguridad Bajo, y tienen Razon, el parche ya existe, pero cuantos son los Administradores de Sistemas (me Incluyo) que pocas veces (si no es que ninguna) han aplicado parches de seguridad.

La falla Esta en la funcion inet_network(), la cual es usada por BIND.

he hecho un archivo para testearla, pero no consigo burlarla, pero bueno ya que, aqui esta mi codigo de test, creo yo que asi se puede testear. que alguien con mas experiencia me corrija si es que me equivoco.

test_network.c
Código
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc,char *argv[]) {
char *host = (argc > 1) ? argv[1] : "192.168.0.1";
in_addr_t net = inet_network(host);
printf("0x%x\n",net);
return 0;
}

Ahora, todos los links que mostre muestran que si tratas de explotar dicho bug, y fallas ocacionarias un DoS a los usuarios legitimos del servidor. Pero si das en el punto exacto podras ejecutar codigo arbitrario en la maquina remota. lo cual te puede permitir el acceso al servidor.

Successfully exploiting this issue may allow attackers to execute arbitrary machine code in the context of applications that use the affected library. Failed exploit attempts may crash applications, denying service to legitimate users.

He instaldo el servidor BIND en una maquina de prueba para ir probando los avances en la aplicacion mas Afectada por este BoF.



Bien ahora estoy analizando la funcion Vulnerable, cabe mencionar que es casi la misma en mi sistema FreeBSD que la que trae incluida el Servidor BIND.

Código
u_long
inet_network(cp)
register const char *cp;
{
register u_long val, base, n, i;
register char c;
u_long parts[4], *pp = parts;
int digit;

again:
val = 0; base = 10; digit = 0;
if (*cp == '0')
digit = 1, base = 8, cp++;
if (*cp == 'x' || *cp == 'X')
base = 16, cp++;
while ((c = *cp) != 0) {
if (isdigit((unsigned char)c)) {
if (base == 8U && (c == '8' || c == '9'))
return (INADDR_NONE);
val = (val * base) + (c - '0');
cp++;
digit = 1;
continue;
}
if (base == 16U && isxdigit((unsigned char)c)) {
val = (val << 4) +
(c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
cp++;
digit = 1;
continue;
}
break;
}
if (!digit)
return (INADDR_NONE);
if (*cp == '.') {
if (pp >= parts + 4 || val > 0xffU)
return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
}
if (*cp && !isspace(*cp&0xff))
return (INADDR_NONE);
*pp++ = val;
n = pp - parts;
if (n > 4U)
return (INADDR_NONE);
for (val = 0, i = 0; i < n; i++) {
val <<= 8;
val |= parts[i] & 0xff;
}
return (val);
}

Lo que he hecho es lo siguiente.
  • Instalar BIND en la Computadora de prueba con la opcion -g
Esto es para mayor depuracion del mismo.
  • Active la creacion de archivos core en el sistema de prueba
Esto es por si la aplicacione se llega a caer en alguna de las pruebas, poder analizar esto mejor.
  • Agregar a mi ejemplo test_network.c, la funcion Vulnerable.
La agrege con otro nombre esto para poderlo compilar con la opcion -g -static para poder depurarlo sin tener que terner el server abierto.

Asi mi codigo para testear la funcion vulnerable queda asi.

Código
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

in_addr_t inet_networkbuf(const char *cp);

int main(int argc,char *argv[]) {
char *host = (argc > 1) ? argv[1] : "192.168.0.1";
in_addr_t net = inet_networkbuf(host);
printf("0x%x\n",net);
return 0;
}

in_addr_t
inet_networkbuf(cp)
const char *cp;
{
in_addr_t val, base, n;
char c;
in_addr_t parts[4], *pp = parts;
int i, digit;

again:
val = 0; base = 10; digit = 0;
if (*cp == '0')
digit = 1, base = 8, cp++;
if (*cp == 'x' || *cp == 'X')
base = 16, cp++;
while ((c = *cp) != 0) {
if (isdigit((unsigned char)c)) {
if (base == 8U && (c == '8' || c == '9'))
return (INADDR_NONE);
val = (val * base) + (c - '0');
cp++;
digit = 1;
continue;
}
if (base == 16U && isxdigit((unsigned char)c)) {
val = (val << 4) +
(c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
cp++;
digit = 1;
continue;
}
break;
}
if (!digit)
return (INADDR_NONE);
if (*cp == '.') {
if (pp >= parts + 4 || val > 0xffU)
return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
}
if (*cp && !isspace(*cp&0xff))
return (INADDR_NONE);
*pp++ = val;
n = pp - parts;
if (n > 4U)
return (INADDR_NONE);
for (val = 0, i = 0; i < n; i++) {
val <<= 8;
val |= parts[i] & 0xff;
}
return (val);
}

Como vemos la unica diferencia entre la funcion existemente en FreeBSD y la del Servidor BIND, es que BIND declara las variables mas utilizadas como register, esto es para que sea mas efeciente. Lo cual me da a entender que va a ser un poco diferente la Explotacion de la funcion inet_network(), dentro de aplicaciones comunes de FreeBSD, que la del Servidor BIND.

Populares Siempre