C# - Hackear una contrasena de un servidor

Iniciado por TickTack, 23 Julio 2017, 20:41 PM

0 Miembros y 1 Visitante están viendo este tema.

TickTack

Hola a todos,

les escribo de nuevo porque todavia no se me aclaro la duda de como hacer que un servidor interprete lo que yo quiera como una variable.

Es decir, si el servidor espera que escriba /login <contrasena>, yo no se la contrasena. Pero se que en el programa hay una variable que se llama contrasena y que esa variable contiene la contrasena al ser comparada por lo que yo puse.

Es decir, si pongo /login 8888 y la contrasena es 1234 el programa compara la verdadera contrasena (que esta en la variable contrasena) con lo que yo puse.

Pero como puedo hacer para poner la variable contrasena dentro del comando y esperar que el servidor la interprete como tal?

Asi /login "contrasena"?

Porque se que Visual Studio filtra este tipo de enganos. Pero como lo hace?


Gracias y saludos
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

Serapis

No estoy seguro de haberte entendido en esta parte (como tampoco en esta parte te entendí la otra vez).

...pero vamos intentanto elucubrar, creo que lo que tu pretendes es decirle que no le quieres pasar un texto, si no una variable... esto es, un texto pero no específicamente escrito por tí, si no obtenido de alguna parte en la memoria...

En realidad, se puede (pasar un string que reside en memoria), porque nunca se pasa un texto, lo que una variable esconde en realidad suele ser la dirección de dicha variable, eso es lo que suele pasarse en parámetros que no son de tipo primitivo (byte, integer, char, buleano, etc...), como es el "string", y que aún siendo considerado un tipo primitivo, por admitir la posibilidad de diferente tamaño, y que dicho tamaño puede ser considerablemente más grande que el ancho de palabra del bus de datos del procesador, se pasa su dirección.

Más aún, cuando escribes una función todos sus parámetros, han de ser de no más de 1,2,4,8 bytes (8bytes = 64 bits), luego todo aquella variable cuyos datos sea más largo, no se puede pasar su valor intrínseco, en parámetros, si no la dirección de memoria donde yace dicho valor. Decir variable, equivale en la práctica a señalar su dirección.

...entonces (y resumiendo), para hacer lo que tu quieres necesitas pasarle la dirección de memoria donde el servidor aloja esa 'variable' de nombre 'contrasena'... aún suponiendo que tanto el cliente como el servidor estén en el mismo equipo, tampoco es garantía de que sea posible, de hecho no es que pueda o no ser posible, si no que debería ser imposible salvo que esté muy mal programado. Me explico...

Tengo el servidor esperando un login de un cliente:
Buleano = Login(alias, contraseña)
Esta línea de pseudocódigo la resumiríamos como que un cliente invoca la función 'login pasándole dos parámetros, el nombre del cliente y una contraseña y a su vez el servidor le responde con un buleano indicando si el login tuvo éxito...

Bien, si lo miras bien, la memoria no tiene ahora mismo (en el momento de ser invocada la función), la contraseña de nadie, solo cuando recibe una llamada de login, mirando el alias, es cuando verificando que exista un usuario registrado con el mismo, es cuando puede optar a verificar si coincide la contraseña recibida, con lo que sea que esté alamcenado, pero como en ese momento de ser llamada la función ya debes haberle pasado la contraseña (la dirección donde se localiza el string), no podrá ser la del usuario 'alias' indicado, porque aún no se ha 'extraído', de parte ninguna... lo hará cuando haya validado el alias y deba comparar contraseñas o lo que sea que tenga almacenado.

Y como ya te indiqué (creo recordar) en un mensaje anterior... yo no compararía contraseña con contraseña en crudo, sino hash contra hash, y el hecho de que el hash deba ser calculado a través de la 'contraseña' recibida implica que no tendrías modo de falsificar una dirección, porque una vez dentro de la función lo recibido como 'contraseña' sufre una alteración por una función hash... y se compara contra el hash que consta en la base de datos (hash que se crea y guarda en la BD, cuando el usuario se registra).

Debe quedarte claro, que un login no debe remitirse a comparar dos cadenas de texto en crudo como si un usuario estuviera buscando un ítem en una lista.
Hashsear es algo intermedio entre cifrado y codificado, pero a diferencia de ambos, es irreversible, luego exige llevar ambos términos a ser hasheados antes de poderse comparar, con lo cual, jamás se ve en claro el texto original.

...yendo más lejos, al registrarse, ni siquiera guardaría el hash de la contraseña (si del alias), sino que guardaría, el hash de concatenar el hash del alias y la contraseña. Como señalo aquí:

Buleano = Funcion Registro(alias, contraseña)
   string h, hPwd, hUser

   hUser = Hashing(alias)
   Si Existe(hUser)= FALSE luego        
       hPwd= Hashing(contraseña)
       h = Hashing(hUser + hPwd)
       Insert into tblRegistro Value (hUser, h, GetTime) //Now
       Devolver TRUE
   fin si
Fin funcion


En resumen, si no manejas directamente nunca más que durante el registro en usuario y la contraseña en la parte del servidor, no hay posibilidad de 'capturar' dicho dato y como al pasarle a la función de login una alias y una contraseña, dichos string son pasados a una función de hashing, quedará modificado, por lo que incluso aún habiendo extraído previamente de la base de datos el dato que se guarda, no es posible saltarse el asunto tal como tu pretendes hacerlo.

TickTack

Hola NEBIRE,

gracias por tu respuesta.

Ok, entonces es imposible. Pero para asegurarme de que nos entendimos bien te quiero dejar
algo.

Lo que te queria dejar es esto:
https://github.com/AresChat/sb0t/blob/master/core/AccountManager.cs#L107

Se trata del metodo SecureLogin. Es a aso a lo que te referias, cierto?

Como puedes ver, tambien hay esta linea dentro del metodo:

byte[] pwd = sha1.ComputeHash(Encoding.UTF8.GetBytes(owner));

Es eso a lo que te referias con "hash contra hash"?

Gracias y saludos

PD.: Si realmente es imposible, entonces eso es bueno.
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

Serapis

#13
Si, más o menos...
Cada cual siempre pondrá más o menos capas de seguridad y hará cosas a su manera, pero es básico no guardar nombres ni contraseñas si no un hash de los mismos a lo sumo, o incluso como te decía un hash del hash concatenado a otra cosa...

Fíjate que tras esa línea luego aparece esta:
pwd = sha1.ComputeHash(SecurePassword(pwd, client.Cookie, ip));
...que invocas a la función SecurePassword donde como te indicaba concatena algún string más (en este caso, la cookie y la ip aunque delante, da igual al caso) y devuelve el array de bytes.

private static byte[] SecurePassword(byte[] password, uint cookie, IPAddress ip)
       {
           List<byte> buffer = new List<byte>();
           buffer.AddRange(BitConverter.GetBytes(cookie));
           buffer.AddRange(ip.GetAddressBytes());
           buffer.AddRange(password);
           return buffer.ToArray();
}


El único modo de lograr algo, es intervenir el propio proceso, para lo cual debes tener bien infectado el equipo y además conocerlo en cierta medida. Si al final del proyecto, usas algún sistema para ofuscar el código antes de compilarlo mejor, cualquiera que quisiere desentrañarlo, lo tendrá más difícil y si al final es un programa que usarán pocos cientos o miles d epersonas, lo más probable es que nadie pierda el tiempo con ello. Un hacker perderá el tiempo cuando haya cierto 'interés', potencialmente millones de personas... a menos que maneje dinero en cantidades sustanciales...

Sólo indicarte que no es estrictamente necesario que utilices un hash complejo o que te cueste entender, para tus propósitos un MD5, incluso un MD4 u otro vale... de hecho incluso sería más acertado tener tu propia función hash, pero si te acomoda las funciones que incluye NET (tiene varias), listo...

También te señalo que no escatimes en hacer llamadas de una función a otra, es decir no dejes que una única 'megafunción' realice todo el login, mucho mejor si distribuyes la carga de trabajo entre varias funciones... aparte de serte más fácil el mantenimiento y cambio del código, también complicas a posibles intrusos (si los llegare a haber)...