Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: TickTack en 23 Julio 2017, 20:41 pm



Título: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 23 Julio 2017, 20:41 pm
Hola,

quiero presentarles el siguiente escenario:

En una computadora hay un servidor y en otra un cliente. Con el cliente queria hackear la contrasena del servidor. Si el cliente sabe la contrasena escribe en el servidor /login <contrasena>.

Codigo del Servidor:

Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7.  
  8.  
  9.  
  10. namespace Servidor
  11. {
  12.    class Program
  13.    {
  14.  
  15.        static void Main(string[] args)
  16.        {
  17.            Servidor_Chat chat = new Servidor_Chat();
  18.        }    
  19.  
  20.    }
  21.  
  22.  
  23.  
  24. }
  25.  
  26.  

Clase Servidor_Chat del servidor:

Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. using System.Threading;
  8. using System.Net.Sockets;
  9. using System.IO;
  10. using System.Net;
  11.  
  12. namespace Servidor
  13. {
  14.    class Servidor_Chat
  15.    {
  16.        /*        
  17.             TcpListener--------> Espera la conexion del Cliente.        
  18.             TcpClient----------> Proporciona la Conexion entre el Servidor y el Cliente.        
  19.             NetworkStream------> Se encarga de enviar mensajes atravez de los sockets.        
  20.         */
  21.  
  22.        private TcpListener server;
  23.        private TcpClient client = new TcpClient();
  24.        private IPEndPoint ipendpoint = new IPEndPoint(IPAddress.Any, 8000);
  25.        private List<Connection> list = new List<Connection>();
  26.        private string contrasena;
  27.  
  28.        Connection con;
  29.  
  30.  
  31.        private struct Connection
  32.        {
  33.            public NetworkStream stream;
  34.            public StreamWriter streamw;
  35.            public StreamReader streamr;
  36.            public string nick;
  37.        }
  38.  
  39.        public Servidor_Chat()
  40.        {
  41.            Inicio();
  42.        }
  43.  
  44.        public void Inicio()
  45.        {
  46.            foreach (string line in File.ReadLines(@"Password.txt", Encoding.UTF8))
  47.            {
  48.                contrasena = line.Substring(12);
  49.            }
  50.  
  51.            Console.WriteLine("Servidor OK!");
  52.            server = new TcpListener(ipendpoint);
  53.            server.Start();
  54.  
  55.            while (true)
  56.            {
  57.                client = server.AcceptTcpClient();
  58.  
  59.                con = new Connection();
  60.                con.stream = client.GetStream();
  61.                con.streamr = new StreamReader(con.stream);
  62.                con.streamw = new StreamWriter(con.stream);
  63.  
  64.                con.nick = con.streamr.ReadLine();
  65.  
  66.                list.Add(con);
  67.                Console.WriteLine(con.nick + " se a conectado.");
  68.  
  69.  
  70.  
  71.                Thread t = new Thread(Escuchar_conexion);
  72.  
  73.                t.Start();
  74.            }
  75.  
  76.  
  77.        }
  78.  
  79.        void Escuchar_conexion()
  80.        {
  81.            Connection hcon = con;
  82.  
  83.            do
  84.            {
  85.                try
  86.                {
  87.                    string tmp = hcon.streamr.ReadLine();
  88.                    Console.WriteLine(hcon.nick + ": " + tmp);
  89.                    foreach (Connection c in list)
  90.                    {
  91.                        try
  92.                        {
  93.                            if(tmp == "/login " + contrasena)
  94.                            {
  95.                                c.streamw.WriteLine(hcon.nick + ", ahora eres administrador!");
  96.                                c.streamw.Flush();
  97.                            }
  98.                            else
  99.                            {
  100.                                c.streamw.WriteLine(hcon.nick + ": " + tmp);
  101.                                c.streamw.Flush();
  102.                            }
  103.                        }
  104.                        catch
  105.                        {
  106.                        }
  107.                    }
  108.                }
  109.                catch
  110.                {
  111.                    list.Remove(hcon);
  112.                    Console.WriteLine(con.nick + " se a desconectado.");
  113.                    break;
  114.                }
  115.            } while (true);
  116.        }
  117.  
  118.    }
  119. }
  120.  

Bueno, si es necesario poner el codigo del cliente, avisenme.

No se si lo puedo llamar inyeccion de codigo pero lo hare hasta que ustedes me digan que es incorrecto llamarlo asi a esto. Bueno trate de hacer una inyeccion de codigo poniendo en el texto de enviar del cliente: /login "" + contrasena + "" y despues, al ver que no funciono, envie: /login " + contrasena ".

Yo crei que el servidor, al recibir un texto, tiene lo recibido entre comillas. Por eso trate de cerrar las comillas (") luego de poner variable que contiene la contrasena (+ contrasena +) y luego de abrir otra comilla mas para cerrar la supuesta comilla final.

Si ustedes no me entienden debido a que me expreso mal quiero saber solo una cosa entonces.

Puedo hackear la contrasena desde la computadora cliente o tengo que hackear la computadora en donde esta el servidor para obtener la contrasena?

Esto lo estaba testeando en mi computadora.

Gracias y saludos


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: engel lex en 23 Julio 2017, 20:57 pm
no es una inyección de codigo, es simplemente envío de datos D:

Código:
tmp == "/login " + contrasena


es decir si la contraseña es 1234 el login espera

Código:
/login 1234

Código:
/login "" + contrasena + "" 

no se nada de c# pero ese codigo debió dar error, si te fijas bien no estás poniendo comillas dentro de comillas... estás abriendo y cerrando comillas justo inmediatamente es decir, un string vacío

para que se entienda mejor
Código:
if(vacio == "") console.log("es vacio")

por otro lado
Código:
 /login " + contrasena ".

se está enviando (no se si interpreta la variable, lo dudo)

Código:
/login  + contrasena 

es decir, el servidor está recibiendo exactamente eso escrito arriba

tienes que usar tal cual está en el servidor
Código:
prueba = "/login " + contrasena

Citar
Puedo hackear la contrasena desde la computadora cliente o tengo que hackear la computadora en donde esta el servidor para obtener la contrasena?

desde donde puedas enviar la contraseña al servidor


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: Eleкtro en 23 Julio 2017, 22:30 pm
No se si lo puedo llamar inyeccion de codigo pero lo hare hasta que ustedes me digan que es incorrecto llamarlo asi a esto.

Lo que estás haciendo se denomina IPC (Inter-Process Communication). Inyección de código... no lo es xD.



Si te lias con las comillas y con el operador de concatenación de C#, recuerda que siempre tienes a tu disposición una herramienta muy útil de formato... precisamente para evitar la escritura excesiva (y horriblemente ininteligible cuando se usa en exceso) de comillas y de +++++. Me estoy refiriendo a la función String.Fromat():

Código
  1. string str = string.Format("/login {0}", this.contrasena)

Saludos


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 24 Julio 2017, 12:40 pm
Hola engel lex,

que bueno verte en la sección .NET de Programacion en General. Das muy buenos aportes siempre,
al igual que Elektro.

Citar
no se nada de c# pero ese codigo debió dar error, si te fijas bien no estás poniendo comillas
dentro de comillas...

En serio... o... que error.. o.. porque no me da error a mi. Solamente que no logro logearme
con esa contrasena sin poner esa contrasena....

Dices que lo tengo que enviar asi:?

prueba = "/login " + contrasena

Pero no funciona.

O dices que lo tenga que enviar asi:?

/login  + contrasena

Asi tampoco funciona porque el servidor toma + contrasena como un string y no como una
variable. La idea era enviar /login + un envio de datos que permitiese al servidor
interpretar contrasena no como un string sino como una variable.

Gracias y saludos


Hola Elektro,

muchas gracias por la recomendacion.

Veo que me interprete mal. Ok miren:

Descarganse el servidor: http://www.mediafire.com/file/z7n27mai7p3upfo/Servidor.exe
Descarganse este documento de texto (ponganlo en donde este el servidor):
http://www.mediafire.com/file/jhqxcdupl40mnqe/Password.txt
Y descarganse el cliente: http://www.mediafire.com/file/o4lden8adjzd4ja/Cliente.exe

Ahora abran el servidor. Y luego el cliente. Ponen un nombre y denle a conectar.
Para loguearse escriban /login <contrasena>.

Lo que yo queria es loguearme sin saber la contrasena. Osea queria de una forma
escribir /login contrasena o algo parecido para que el servidor intreprete contrasena no
como un string sino como una variable para lograr loguearme como administrador sin poner
la contrasena y sin cambiar el codigo fuente del servidor.

Gracias y saludos


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: Serapis en 24 Julio 2017, 17:13 pm
algunos consejos:

No suele ser muy útil, que el administrador se loguee de la misma forma que un cliente cualquiera.

De entrada si, hay una base de datos (clientes registrados), además de la contraseña, debería requerirse también el alias del usuario. Y por supuesto el admin, no debe llamarse 'admin', por mucho que en los routers venga así de mal...

Tampoco es buena idea registrar a cualquier cliente con una única contraseña.
Añade un método de 'AddCliente', donde el usuario especifique 3 cosas:
- Alias de registro.  (login)
- Contraseña de registro. (login)
- Nombre de interfaz. (interfaz)

Rechaza el registro si:
 - Alias o nombre tiene menos de 'x' caracteres. Usa una constantes c_MinCharsAlias = 6 (por ejemplo)
 - Contraseña tiene menos de 'y' caracteres. ídem sobre la constante
 - Alias y nombre son idénticos.
 - Alias, nombre o contraseña, contienen caracteres que al caso considerares 'ilegales'... Esto es, debe tener un string con los caracteres legales "LegalChars = "ABCDEFGHIJK... abcdrfghijkl...01234...", una función debe chequear si algún carácter en un string recibido contiene un carácter que no aparece en LegalChars en cuyo caso devolver FALSE...
 - Alias y/o nombre ya existen.
 - Al patrón de la contraseña es fácilmente reconocible: por ejemplo "qwerty" "QWERTY", "123456", "PASSWORD", password"... Esto puede ser máso menos complejo, pero al menos hazte con una lista de las 100 contraseñas más frecuentes, las metes en un array y si coinciden lo recghazas... es lo mínimo. algo más potente es contabilizar los caracteres: mayusculas, minúsculas, números, espaciadores, simbolos. Exige que al menos haya caracteres en 3 de esos grupos, y que excepto el grupo con más caracteres (de la contraseña), sumen al menos 3 caracteres...
 ejemplos:
---------- "ahsdfjktovuirmncv3" solo está el grupo minúsculas y en números solo contiene 1, rechazar no hay caracteres para 3 grupos al menos.
--------- "1845763W938564n" hay 3 grupos, pero aparte del más numeroso, solo hay 2 caracteres del resto, rechazar...
En fin puede complicarse más, pero algo similar, debe ser lo mínimo exigible.

El administrador, podría ser el único capacitado para encender el servidor. Esto exige que sea el primero en loguearse. Luego el servidor debe rechazar un login 'efectivo', si hay 0 usuarios logueados y éste no es administrador. al hacerlo así, implica que va a ser imposible que alguien se loguee como el administrador, toda vez que el servidor solo atiende cuando el administrador enciende el servidor. esta solución no siempre va a poder ser adecuada, especialmente cuando el administrador está en una máquina y el servidor reside en otra. El administrador podría ser automático, esto es cuando un cliente intenta loguearse, si hay 0 usuarios logueados, primero loguear internamente al administrador y luego al cliente. Y el administrador (remoto), cuando se loguee como un usuario cualquiera, el servidor debería poder reconocerle y reasignarle el administrador 'precargado'. Así ese administrador aparecerá como si fuera duplicado, esto es consta como un cliente normal y como administrador, pero tiene funciones y roles de administradro, ya que el servidor lo ha reconocido como tal.

Si todo es solo un proyecto de pruebas, tampoco hace falta que te compliques tanto con la seguridad, aunque algo mínimo debes hacer y tenerlo siempre presente la importancia de la seguridad.

Nunca almacenes las credenciales crudas, es decir si el alias de registro es: Tick-Tack y la contraseña: "pSd8F4 0a17Zh4", genera el hash de ambos y concaténalos y asocia un ID al azar y crea un hash también para ese ID (para crerar este hash toma el ID y le concatenas algún caracter del hash anterior, delante, detrás..),  ... esos 3 campos es lo que debes guardar en tu BD. Así un usuario que se loguea, sigue el mismo patrón, se hashea su alias y contraseña y se concatenan, luego se busca si ese hash existe en la base de datos (debe devolver el ID si se encontró), si es así se da por válido el login, si no, que devuelva como ID = -1.
Si fue validado, al cliente entrégale un hash del ID (3º campo guardado). En lo sucesivo (mientras el user esté logueado), será esa referencia la identificación del usuario. Yendo un poco más lejos, este hash entregado debería crearse nuevo cada vez que un usuario se loguea, así no hay posibilidad de que si alguien tomo tu 'referencia' pueda usarla en un futuro...
Cada usuario logueado, añade su referencia a una tabla, así cualquier petición de un usuario antes de ser atendida, se verifica que existe en esa tabla...

En fin la seguridad dependerá mucho de como hagas las cosas.





Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 24 Julio 2017, 17:47 pm
Muchas gracias NEBIRE por tus puntos importantes para tomar medidas de seguridad a lo hora de crear o disenar un servidor de chat. Estaria bastante tiempo en todo lo que mencionaste...

Pero.. me intereso eso de crear un hash y concatenar sus datos.... Asi que... manos a la obra!!!


Pero antes...

Viste el servidor y cliente que subi a internet?

Antes queria saber si el cliente puede loguearse como administrador sin saber la contrasena.

Mas arriba postee el codigo del servidor.

Existe un vulnerabilidad de poder loguearse como administrador sin saber la contrasena en el servidor que hice?


Gracias y saludos


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: Serapis en 24 Julio 2017, 19:40 pm
Los he descargado, pero no se ejecutan aquí tengo win-XP (32 bits).

---------------------
Respecto del login... fíjate que recurres a usar una contraseña que yace en un fichero de texto. Así, que en teoría eso lo hace altamente vulnerable. Además, ya te he comentado, que usar una sola y misma contraseña para todos es una malña solución.

--------------------
Si tu chat solo va a admitir un administrador, haz que sea el primero que se loguee, es decir él y solo él prende el servidor, y nadie más pueda loguearse como administrador. Si el administrador no se loguea, no existe el chat, porque no se crea.

Pero para poder loguear como administrador... en  realidad para poder manejar diferentes usuarios con permisos diferentes, hay que separar los roles de usuario. Cuando te puse tiempo atrás un pseudocódigo sobre un chat, realmente allí te puse cosas muy útiles, bien que luego no hayas sabido aplicarlas. Los roles se pueden resumir en sus permisos-privilegios, y se puede reducir a su mínima expresión en una propiedad de tipo string (de solo lectura como cliente, lectura y escritura para los administradores).

Entonces para un usuario, lo mínimo como Rol, es una propiedad de solo lectura con ese nombre Rol y cuyo contenido sea una cadena de texto. Unos simples caracteres, así un ejemplo de los roles de un usuario podría ser algo tan sencillo como esto: cliente.Rol = "LSER", cuyo significado simple podría ser:puede Loguearse (ideal para retirarlo cuando se banea a un usuario), puede crear Salas, puede Enviar mensajes, puede Recibir mensajes.
En cambio el rol de Admin podrá usar muchos más métodos, luego su Rol, tendría un string, mucho más 'largo': Admin.Rol = "LSERXBPVG..."
X = puede eliminar user
B = puede Banear un usuario (al hacerlo se le retira a ese usaurio de su rol, la "L")
P = puede otorgar privilegios de administrador (admin restringido) a usuarios normales y retirar privilegios de administrador...
V = puede reiniciar el serVidor (pero no encender ni apagar)
G = Administrador Global. Ningún usuario puede tener este atributo, excepto el dueño del chat. Es decir el resto de administradores, habrá cosas que no pueden hacer. Solo quien tenga el privilegio G, podría apagar, encender el servidor
... = etc, etc... es cuestión de ver que quieres que haga.

Si un usuario (cliente) invoca un método, se verifica si su rol contiene el 'carácter' asociado a ese método, si es que sí, se permite la ejecución del método, si no, no. algunos métodos, en cambio los valida el servidor...
Al crearse un usuario se le añaden un rol básico... al crear el administrador su rol es completo.

Te pego el pseudocódigo de la clase servidor que te puse la otra vez (algo muy resumido, pero que te puede servir de orientación)... (este foro no admite spoilers, así que los mensajes a veces pueden quedar largos).

Date cuenta, que en este código, aparece Privilegios, como sinónimo de Rol, y por ejemplo: el privilegio "CreateSala" (que lo puse así por claridad), puede ser "S" (como aparece en el ejemplo más arriba), es decir resumido a un sólo carácter...

Código:
Clase Servidor
   // Instancias de clases.
   TablaHash Clientes Privado ConEventos
   TablaHash ClientesOcultos Privado  ConEventos // clientes privilegiados, admins
   TablaHash Salas Privado ConEventos
   Sala SalaRaiz  Privado ConEventos
   Cliente ClienteRaiz  Privado ConEventos

   Buleano Existe

   Entero = Propiedad Sololectura NumClientes Publico
       Numclientes = Clientes.Cantidad
   Fin Propiedad

   Entero = Propiedad SoloLectura NumclientesOcultos Publico // o admins  
       NumClientesOcultos = ClientesOcultos.Cantidad
   Fin Propiedad
  
   Entero = Propiedad SoloLectura NumSalas Publico
       Numsalas = Salas.Cantidad
   Fin Propiedad

   Buleano = Propiedad SePermiteCrearSalas Oculto //lectura y escritura

  
   // Esta función se invoca para crear el servidor, que luego es público y permite la conexión... crea además, la primera sala y el resto de objetos necesarios.
   Funcion Nuevo(x,y,z) Oculta  ' parámetros que requiriese para crear el servidor
       Clientes = Nueva TablaHash
       ClientesOcultos = Nueva TablaHash
       Salas = NuevaTablaHash

       SalaRaiz= Nueva Sala
       ClienteRaiz = Nuevo Cliente(Alias, Invisible, Privilegios)
      
       Salas.Add(SalaRaiz)
       Clientes.Add(ClienteRaiz)
       ClientesOcultos.Add(ClienteRaiz)

       Existe = TRUE
    Fin Funcion
    
    // El ciente cuando se conecta al servidor, se añade a la lista de clientes.
    // Y también se le añade a la salaRaiz, y se le devuelve una referencia a esa sala.
    Sala = Funcion Conectar(Cliente Cli) Publico
        Si SalaRaiz.AdmiteClientes = TRUE luego
          //podría filtrarse aquí comparando con una lista de clientes/IPs, baneadas, pero quizás no sea muy efectiva...
             Si SalaRaiz.Add(cli) = TRUE  // solo debería devolver false si ya existe un cliente con el mismo alias.
                 Devolver SalaRaiz
             Fin si
        Fin si
    Fin Funcion        

    Sala = Funcion CrearSala(Cliente Cli, String NombreSala, Entero MasUsers)
        Si (SePermiteCrearSalas = TRUE) luego
            Si (Clientes.Existe(cli) = TRUE ) luego  // Todos los clientes, incluso los ocultos, constan en la colección Clientes.
                Si (Salas.Existe(NombreSala) = FALSE) luego
                    Sala = Nueva Sala(Cli, Nombresala, MaxUsers, This)
                    Salas.Add(sala)  //allí se dispara un evento de 'SalaCreada(Sala.nombre)' que le llega a todos los clientes.

                    Devolver Sala
                Fin Si
            Fin si
        Fin si


        // Ó si solo se permite a clientes ocultos (admins).
        Si (ClientesOcultos.Existe(cli) = TRUE ) luego ...
        ....

        // Ó si solo se permite a cliente con privilegios
        Si (cli.Privilegios.Contiene("CreateSala")) luego
            Si (Clientes.Existe(cli) = TRUE ) luego ...
            ....
        Fin si
    Fin Funcion

    // Otras funciones que tenga el servidor... (especialmente resolver los eventos de las intancias de las clases: Clientes, ClientesOcultos, Salas,  SalaRaiz, ClienteRaiz
Fin Clase

Fíjate comno en este ejemplo, la instancia del servidor cuando se crea, es creada por el administrador cuando invoca el New(x,y,z) x,y,z representa los parámetros que vayan a ser necesarios durante la creación de la instancia.. fíjate que luego en ese mismo métodos se concreta:
   ClienteRaiz = Nuevo Cliente(Alias, Invisible, Privilegios)
...Alias, invisible y privilegios, serían parámetros de entrada (al margen de otros parámetros más fueren precisos). Y al caso, el admin, ni siquiera precisa una contraseña. Ya que es él quien crea la instancia, es el poseedor de la misma, el método New, es el constructor de la instancia, solo puede ser invocado una única vez y además al inicio antes que nada suceda, luego nadie puede usurpar el administrador-absoluto (si no hay métodos para un login posterior de administrador, por ejemplo), a lo sumo podrán crear otras instancias del servidor (...si lograran acceso al terminal que lo contiene)...
Digo administrador absoluto, porque en un chat, suele ser frecuente que haya otros usuarios con roles de administrador (restringido)... en tal caso, es el Administrador absoluto, quien sólo puede otorgar-retirar privilegios de Administrador (restringido)...


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 24 Julio 2017, 21:19 pm
Hola NEBIRE,

ahhh.. vale. Muchas gracias. Bueno... mas notas que apuntar y un codigo que traducir......

Que haria sin esta buena paginas:? http://converter.telerik.com/

Bueno. Te queria preguntar de que maneras uno se podria aprovechar de la vulnerabilidad de que la contrasena estuviera en un fichero de texto?

Y unas preguntas mas:

1) A lo que en realidad iba en todo este post era esto:

En realidad que haria lograr loguearme al servidor sin saber la contrasena usando algo como una interpolacion de string.

Osea que pudiera escribir esto:

/login "$"{contrasena}

Pero no funciona. Trato de hacer una referencia a la variable contrasena despues de haber escrito /login para poder loguearme sin saber la contrasena. Pero como puedo hacer esto? No se como incluir dentro de un string una referencia de una variable.

2) Los Querys solo se pueden hacer desde el cliente si el servidor es programado para recibir Querys?

Gracias y saludos


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: Eleкtro en 24 Julio 2017, 22:36 pm
Bueno... mas notas que apuntar y un codigo que traducir......

Pues apunta una nota más que no te han dicho:

Cuando se trata de exponer contraseñas e información confdencial en general, en lugar de la clase System.String deberías utilizar la clase System.Security.SecureString para potenciar la seguridad de tu aplicación previniendo que los strings puedan ser almacenados por más tiempo del necesario en la memoria de la aplicación y por consiguiente intentar prevenir que un "intruso" (llámese hacker) pueda obtener dicha información mediante estrategias de ing. inversa que impliquen leer secciones de memoria.

Al utilizar la clase System.Security.SecureString para almacenar un string confidencial, el string se almacena en un bloque de memoria no administrada, se cifra el bloque de memoria mediante la función Win32 RtlEncryptMemory (u otra función no documentada), y cuando el string ya no es necesario internamente se llama a la función Win32 ZeroMemory para llenar el bloque de memoria con ceros, es decir, para limpiar el bloque de memoria de cualquier rastro de nuestra información confidencial.

Todo ello lo puedes comprobar analizando la referencia del código fuente de .NET Framework:
  • http://referencesource.microsoft.com/#mscorlib/system/security/securestring.cs,77d68ea938f47705

Aparte, si hablamos de un escenario donde hay un cliente y un servidor, y tú envias la contraseña descifrada pues... creo que el riesgo de intercepción de datos es más que evidente. Una idea genial y eficiente al 100% (sino al 99,9%) sería cifrar el string de nuestra instancia SecureString mediante una clave pública otorgada por el servidor, de esta manera el string original nunca se vería expuesto en la transmisión de datos remota entre cliente y servidor, ni en la memoria administrada de la aplicación, por ende tampoco en el GarbageCollector de .NET, y solamente el servidor podria descifrar el string cifrado mediante la clave pública otorgada.

Esta sugerencia que acabo de explicar es exactamente lo que hace Microsoft en el mimebro PSRemotingCryptoHelper.EncryptSecureStringCore().
  • http://referencesource.microsoft.com/#System.Management.Automation/System/Management/Automation/Internal/PSRemotingCryptoHelper.cs



En fin. Dicha clase, System.Security.SecureString tiene ciertas diferencias de uso en comparación con la clase System.String, de hecho no se asemejan en nada. Para que te hagas una idea, se asemenja bastante más a la clase System.Text.StringBuilder en el modo de empleo.

  • SecureString Class | MSDN (https://msdn.microsoft.com/en-us/library/system.security.securestring(v=vs.110).aspx)
  • How secure is SecureString? | MSDN (https://msdn.microsoft.com/en-us/library/system.security.securestring(v=vs.110).aspx#HowSecure)

Saludos


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 6 Agosto 2017, 10:50 am
Hola mis amigos!!!!!!!!!!!
Tanto tiempo!!!!

Y si!! Ya hice mi servidor!!!!

La parte mas put* era la de concatenar algunos datos con un hash.
Esa parte no la hice. Me era demasiado trabajo. Sin agregar que no tengo nada de experiencia en hacer esas cosas no el conocimiento..... Suficiente con los otros complicados puntos para mi que ustedes me mencionaron......

Pero ahora me interesa lo que menciono Elektro...

Como puedo yo obtener strings almacenados en la memoria de una aplicacion mediante sockets o TCP usando estragias de ingenieria inversa que impliquen leer secciones de memoria?

Existen tales estrategias en relidad? Realmente se puede de esta manera interceptar datos?

Porque para me es inpensable que se pueda. Y si se puede... entonces cómo?

Me intereso bastante lo que escribiste....



Gracias y saludos



Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 29 Noviembre 2017, 13:07 pm
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


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: Serapis en 29 Noviembre 2017, 20:18 pm
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:
Código:
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í:
Código:
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.


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: TickTack en 29 Noviembre 2017, 22:06 pm
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.


Título: Re: C# - Hackear una contrasena de un servidor
Publicado por: Serapis en 30 Noviembre 2017, 01:01 am
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:
Código:
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.
Código:
 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)...