CocaCola Happing(tm) for fun and profit.
Actualizada con nuevos pasos a seguir (gracias Max). Sigue funcionando.
Hola HAMIJOS!, hoy vamos a pasarnos por la piedra a un sistema de SMSs gratuitos ofrecido por Cocacola. Conseguiremos enviar SMSs controlando todos sus elementos:
+ Número del remitente
+ Número del receptor
+ Totalidad de los caracteres a enviar
Todo esto sin publicidad,de manera anónima y gratuita, con todo lo que ello supone…
Pero antes, representantes legales, FSE y Belén Esteban como nueva cabeza visible del Estado (si sabes leer) etc, lean el disclaimer silvuplé.
——————————————-
Para la realización de este post, ningún sistema fue accedido ilegalmente, no se usaron medios o herramientas ilegales para modificar, revelar,acceder o destruir contenido protegido, privado o secreto. No se han accedido a bases de datos protegidas ni revelado directorio de usuarios, contraseñas ni ningún otro dato considerado personal o no.Todo lo necesario para comprender el funcionamiento del sistema está en ficheros accesibles públicamente. Esto puede ser refrendado por cualquier persona con los conocimientos técnicos necesarios. En el caso de que CocaCola requiriera a través de los medios legales ésta verificación, llegarían a la misma conclusión.
Con este post yo simplemente pongo en conocimiento de la gente un hecho que me parece curioso, para que cada uno tome las medidas oportunas.
Por último,dejar claro que el problema no es que yo esté divulgando una manera «creativa» de utilización del sistema (que no hackearlo, comprometerlo o como quieras llamarlo), el problema es que la empresa ofrece un servicio que puede ser usado, o incluso ya puede estar siendo usado, para suplantar identidades.Esto es debido a que no provee los medios técnicos para asegurar su correcta utilización. Es a la empresa y no a mí a quien correspondería solventarlo.
Te puede parecer más o menos ético que lo publique, me chupa un pie. Como ya expliqué en un post en Reversemode:
I’ve got a new ethic rule: «No explicit security contact publicily available + no money involved (I’m used to eat almost three times a day) == 0day».
Empresas del mundo: contratando gente válida ( aquí en 48bits se reune mucha de ella 😛 ) te ahorras muchos dolores de cabeza.
No me hago responsable, porque no lo soy, de que algún notas haga un mal uso de esta información y la líe parda. Tal y como cláramente explica la política de uso de la web de cocacola.es y happing.com, el mal uso de la web recae únicamente en el usuario responsable.
Chispún.
—-
Al lío…
Estas navidades recibí un SMS desde un numero 77** que luego resultó haber sido enviado desde un internet kiosk que hay en determinados sitios( eso tengo que mirarlo todavía, quiza haya post jeje ) y me chiné porque no había mirado mucho sobre estas cosas. Asi que me puse a ver como funcionaban las SMSCs, SMS gateways, el software que había y esas cosas…Buscaba páginas de envio de SMS gratuitos para ver cómo funcionaban internamente. Acabé en la de Cocacola…
DWR y la rotura de la lógica.
DWR es una engine que permite usar de manera remota clases de Java desde el client-side mediante el uso de JavaScript. La idea es buena, muy buena diría yo. Pero peligrosa. ¿Por qué? Porque es flexible y muy cómodo, y de cara a un developer con poca formación en seguridad hace demasiado fina la separación entre client-side y server-side y la lógica que tiene que seguir una aplicación de este tipo.
En el siguiente enlace puedes enterarte de cómo funciona DWR http://directwebremoting.org/dwr/documentation.html
Haré un resumen mínimo para el que no le apetezca leer.
Te haces una clase en Java en la que ciertos métodos deberán ser accedidos mediante el engine DWR que hará de pasarela desde el client-side.
Declaras los métodos que quieres que se puedan acceder desde el client-side.
Se generan varios .js que tienen que ser cargados en el client-side. engine.js, util.js mas el interface de tu clase: ‘morrocola.js’ por ejemplo.
DWR genera una serie de htmls destinado a que tu pruebes los métodos automáticamente, es conveniente borrarlos de los servers de producción: https://entrades.fcbarcelona.cat/Ticketing/dwr/index.html
Básicamente una llamada de tipo DWR puede ser GET o POST, y en ella se especifican varios parametros como el tipo de método que se va a usar dentro de la clase, ids de sesión…Los parametros que recibirá el método van serializados en varios tipos de variables de la siguiente forma : «tipo:valor» -> «string:tuvieja_la_cangreja».
Ejemplo:
URL:www.foo.com/dwr/call/plaincall/pizzaService.hazPedido.dwr
Los argumentos a enviar podrían ser:
callCount=1
page=/pedido/Pizza.do
httpSessionId={$httpSessionId}
scriptSessionId={$scriptSessionId}
c0-scriptName=pizzaService
c0-methodName=hazPedido
c0-id=0
batchId=1
c0-param0=string:pepperoni
c0-param1=string:familiar
c0-param2=number:1
c0-param3=boolean:false
El server devuelve los datos que sean que son manejados en el client-side por una callback que hayamos especificado. Básicamente es lógica AJAX.Y es con esa mentalidad con la que tenemos que ver las aplicaciones. Lo básico es no exportar al interface público aquellos métodos que sólo se deberían acceder en el server-side así como bloquear los posibles métodos heredados que sean peligrosos.
Pero lo más importante es no aplicar la lógica secuencial a una aplicación DWR si no la estamos aplicando en el server-side. No permitas llamar a ‘hazPedido‘ si no hay un ‘loginConfirmado‘ antes y eso lo tienes que comprobar en el server-side. No asumas que porque alguien ha hecho un call a ‘hazPedido‘, que según la logica de tu aplicación solo se puede generar una vez logueado, esta ha sido hecha antes de un ‘loginConfirmado‘ porque DWR nos permite eso, y es peligroso.
¡En el lado servidor hay que seguir comprobando que todo es válido! Ahí es donde radica el fallo en algunas aplicaciones que usan DWR.
El caso de CocaCola.
Cocacola lanzó recientemente su red social: happing.com. Para potenciar su uso ha puesto a disposición de los usuarios registrados 500.000 SMS gratuitos. Cada usuario puede enviar un máximo de 10 SMS al día. Para poder acceder a este servicio es necesario, en teoría, que sigas una serie de pasos.
1.Registrarte.
2.Loguearte.
3.Registrar tu móvil.
4.Recibir un SMS con un código de activación en tu móvil.
5.Activar tu móvil mediante ese código.
6.Ya puedes enviar SMSs a cualquier movil, donde el remitente será el número de tu móvil ( o el que activaste mediante el código ).
Vamos a analizar todo el lio.
Viendo el código fuente de la web nos fijamos en lo siguiente:
Lo que nos da la pista de que usan DWR. Ahora nos queda saber que clases y métodos se implementan y cómo. Para ello nos creamos una cuenta. Para ello tenemos que resolver una captcha, que es un poco diferente a las demás, son preguntas «comunes». La idea es buena, pero meter el id de la captcha en la petición que verifica si es correcta tampoco mola mucho.
callCount=1
page=/api/usuarios/registro/dispatchRegistro.action?site=happing&tipoRegistro=P
httpSessionId=
scriptSessionId=${scriptSessionId}207
c0-scriptName=captchaService
c0-methodName=compruebaRespuestaCaptcha
c0-id=0
c0-param0=string:jazmin
c0-param1=number:3
batchId=1
Teniendo en cuenta que la captcha se obtiene de manera aleatoria mediante una petición DWR también que te devuelve el Id
Pero bueno, se nos piden varios datos, DNI, un correo etc… El mail, el nick y el DNI se comprueban mediante otra petición DWR con el fin de evitar duplicaciones de cuentas. El DNI también se comprueba que sea válido mediante la letra (la manida fórmula de luhnobtención de la letra del DNI) también en petición DWR.
Después nos envían un email al email que hemos dado para el registro. Este correo contiene un enlace que nos activará la cuenta. Todos los datos son enviados en peticiones HTTP POST o GET sin ningún tipo de seguridad. Todos tus datos, dirección, dni, teléfono, contraseña etc se pueden ver en plain text.
Pero vamos a lo que nos interesa, lo de los SMS. Cuando entramos en la cuenta por primera vez vamos a «premios»->»SMSs gratuitos» y vemos que necesitamos activar nuestro móvil para poder usar este servicio.
Vamos a ver que «esconde» el código fuente…
enviando = false;
jQuery("#formularioSMS").submit(function() {
if(!enviando){
enviando = true;
movil_dest = document.getElementById(‘movildestino’).value;
texto_enviar = document.getElementById(‘mensaje’).value;
if(document.getElementById(‘mensaje’).value == "" || document.getElementById(‘mensaje’).value == "Aquí verás el SMS elegido, también podrás escribir tu propio mensaje"){ /* envio vacio */
alert("Por favor selecciona una plantilla de las disponibles o escribe tu mensaje")
}
else if(movil_dest == "" || !esNumerico(movil_dest) || longitud(movil_dest)!= 9 ){/* comprobacion del móvil */
alert("El teléfono móvil del destinatario no es correcto. ")
}
else if(longitud(texto_enviar) > 160){ /* mensaje demasiado largo */
alert("El mensaje es demasiado largo. Sólo se pueden enviar 160 caracteres)")
}
else {/* todo correcto.*/
jQuery.ajax({type: ‘POST’, url: ‘sms_enviar.cfm’, data: jQuery(this).serialize(),
success: function(resultado) {
array_resultado = resultado.split("|");
cod_resultado = array_resultado[0];
num_smss = array_resultado[1];
//mensajes_hoy = 4-parseInt(num_smss);
if(cod_resultado == 1){window.location.href="sms.cfm?rnd=0.0778374419541&enviook=1#cabecerasms";}
else if(cod_resultado == -1){alert("Por hoy no puedes enviar más mensajes.");}
else if(cod_resultado == -2){alert("Se ha alcanzado el máximo de sms de la aplicación");}
else if(cod_resultado == -3){alert("Sólo puedes enviar 3 mensajes a cada destinatario.");}
else{alert("Se ha producido un error. Inténtalo de nuevo un poco más tarde");}
},
error: function(){
alert("Se ha producido un error. Inténtalo de nuevo un poco más tarde");
},
cache: false
})
}
enviando = false;
return false;
}
});
});
Vemos que aunque de cara al usuario, el envio de SMSs está desactivado, la lógica que permite enviarlo nos muestra cómo. ¿Que pasará si en el lado servidor no controlan que estemos logueados?
También funcionaría mediante una petición POST obviamente.
Placa! recibimos el SMS desde el remitente 000000000, que tiene su lógica. No comprueban que estemos logueados ni que este activado nuestro movil, solo mira el móvil asociado a la sesión, y como no hay pues 0.
Primer fallo gordo.
Pero lo que queremos es poder spoofear el número del remitente y hacer que sea cualquiera que queramos. Esto no lo podríamos hacer siguiendo los pasos que nos marcan ya que necesitamos activar el móvil con un código que recibiríamos en el móvil. Pero tal vez podamos hacer algo. Vamos a echar un vistazo a interface DWR de la clase que lleva todo el tema AJAX.
http://www.cocacola.es/js/servicioAjax.js
}if(dwr.engine==null){dwr.engine={}
}if(DWREngine==null){var DWREngine=dwr.engine
}if(servicioAjax==null){var servicioAjax={}
}servicioAjax._path="/dwr";
servicioAjax.compruebaLogado=function(A){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaLogado",A)
};
servicioAjax.compruebaDNI=function(B,A){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaDNI",B,A)
};
servicioAjax.compruebaPaso2=function(D,B,A,C){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaPaso2",D,B,A,C)
};
servicioAjax.compruebaMailNickHapping=function(C,A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaMailNickHapping",C,A,B)
};
servicioAjax.compruebaUsuarioActivo=function(C,A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaUsuarioActivo",C,A,B)
};
servicioAjax.compruebaDNIHapping=function(C,A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaDNIHapping",C,A,B)
};
servicioAjax.compruebaFrasesMinutoYFraseiguales=function(A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaFrasesMinutoYFraseiguales",false,false,A,B)
};
servicioAjax.compruebaLogadoCompleto=function(B,A){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaLogadoCompleto",B,A)
};
servicioAjax.compruebaFraseRepiteCorreo=function(A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaFraseRepiteCorreo",false,false,A,B)
};
servicioAjax.compruebaEnvioCorreo=function(A){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaEnvioCorreo",false,false,A)
};
servicioAjax.compruebaNumTelefono=function(A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","compruebaNumTelefono",false,false,A,B)
};
servicioAjax.validaSMS=function(A){dwr.engine._execute(servicioAjax._path,"servicioAjax","validaSMS",false,false,A)
};
servicioAjax.insertaMovil=function(A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","insertaMovil",false,false,A,B)
};
servicioAjax.activaSMS=function(A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","activaSMS",false,false,A,B)
};
servicioAjax.onChangeMovil=function(A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","onChangeMovil",false,false,A,B)
};
servicioAjax.validaEtiquetas=function(D,B,A,C){dwr.engine._execute(servicioAjax._path,"servicioAjax","validaEtiquetas",D,B,A,C)
};
servicioAjax.validaMail=function(C,A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","validaMail",C,A,B)
};
servicioAjax.validaPasswordYCapcha=function(C,A,B){dwr.engine._execute(servicioAjax._path,"servicioAjax","validaPasswordYCapcha",C,A,B)
Aunque aparentemente todos estos métodos estan exportados, los «más interesantes» devuelven siempre error.Supongo que o estan declarados como private, a pesar de estar exportados al interface js, o en el server-side hacen algun tipo de comprobación ( no se porqué pero me da que no).
El caso es que solo viendo los métodos nos podemos hacer una idea de la lógica que sigue la clase. Suficiente.
La idea es que bajo nuestras suposición al solo chequear el movil asociado a la sesion del usuario logueado, si de alguna manera conseguimos insertar un móvil en nuestro perfil, esto nos permitiría spoofear el número del remitente, saltándonos el proceso de activación y verificación del móvil.
Vamos a «perfil»->»Editar mis datos»->»Mi contacto» y ponemos el móvil que queramos, un teléfono fijo, una direccion, una provincia y un CP válido y le damos. Se supone que ahora en nuestro perfil ya hay un movil registrado, aunque no activado.
Estando logueados, para poder usar la sesion, ejecutamos lo mismo de antes.
y bingo!! recibimos el SMS pero como remitente el móvil que acabamos de meter.Saltándonos todo el proceso de verificación y registro del móvil.
Recapitulando.
Cualquier persona con una cuenta de correo válida que le permita registrarse podrá enviar SMSs de forma anónima a cualquier otra persona usando el número que él desee.
Ejemplo:
1.Creamos cuenta
2.Editamos nuestro perfil y nos ponemos como número de móvil el de ramoncín.
3.Vamos a la URL que permite enviar los sms y enviamos un mensaje a chuck norris llamándole maricona y cosas peores.
4.Esperamos acontecimientos.
A partir de la publicación de este post, no te fies de cualquier SMS extraño que recibas, aunque sea de un móvil conocido. La única forma de evitar que alguien use tu móvil es registrarlo antes de que lo haga otro.
Esto es sólo válido para SMS nacionales.
Empezamos bien el año…tened cuidado ahí fuera!!
ACTUALIZACIÓN
Han «solucionado» parcialmente el problema, ahora te piden otra vez login para enviar el sms. Por lo que se añade un paso.
1.Creamos cuenta
2.Editamos nuestro perfil y nos ponemos como número de móvil el de ramoncín.
3.Vamos a «Premios»->»SMSs gratuitos» y nos logueamos otra vez.
4.Vamos a la URL que permite enviar los sms y enviamos un mensaje a chuck norris llamándole maricona y cosas peores.
5.Esperamos acontecimientos.