Falla de seguridad en sharethis.com API con Google Chrome

En un artículo anterior “Herramientas esenciales para un webmaster” indicábamos cuales eran las principales herramientas y servicios que no deben faltar a la hora de desarrollar una aplicación o página web.Entre ellas hablábamos de los navegadores y los principales o más comunes y populares.

Uno de estos navegadores es el Googe Chrome, navegador que fuese lanzado luego de la aparición del Google OS en teoría y que forma parte de este. Desde entonces he entrado a la competencia de los navegadores junto con Internet Explorer y Mozilla Firefox.

En teoría, todos los navegadores deberían ser iguales en cuanto a renderización de las páginas web según la estructura DOM del documento o fichero que contengan los elementos de la arquitectura de la página web que estemos vizualizando. Sin embargo, desde que fue utilizado inicialmente por Netscape navigator y luego implementado “copiado” por Internet Explorer. Este último introdujo su propia extensión al DOM para definir la manera en que objetos y elementos se relacionan entre sí en el navegador y en el documento.

A pesar de que World Wide Web Consortium  (W3C), el consorcio encargado de definir los estándares de la web, decidió crear un modelo de objetos único, el DOM, para que todos los fabricantes pudieran adoptarlo, facilitando la compatibilidad plena entre ellos, todos los nuevos navegadores tienen elementos propios lo cual dificulta la compatibilidad y por consiguiente problemas de renderización de nuestras páginas en los navegadores.

Recientemente el banco BHD de la República Dominicana actualizó su sitio web y posteriormente su plataforma web para clientes y manejo de cuentas online. una vez lanzado hicimos varias pruebas con diferentes navegadores y plataformas dando como resultado problemas de compatibilidad con los dispositivos y ordenadores con el navegador Safari de Apple.

Este problema de incompatibilidad presentó un grave problema de seguridad pues el despliegue permitía ver las variables y datos exncryptados de la aplicación para clientes y manejo de cuentas del Banco. Gracias a un pronta respuesta a las quejas esto fue corregido.

Desde entonces, he establecido una política de probar cualquier elemento que incluyo en una aplicación o página web para evitar estas incompatibilidades que por cada navagador se presentan.

La mas reciente la realicé con el servicio sharethis para compartir enlaces en las diferentes redes sociales. Probando el servicio en los diferentes navegadores me topé con una gran sorpresa con Google Chrome y el archivo sharer.php del api del servicio de sharethis.com el cual es el archivo que hace posible publicar el link en los diferentes servicios de bookmark existentes.

El archivo es localizado en http://wd.sharethis.com/api/sharer.php de la implementación y este fue el resultado al querer compartir un enlace: (vista parcial de la vista obtenida al clickear paera compartir un enlace)
[code lang=”php”]
get($usrHash);
if(false==$incr || (int)$incr<5){
logEvent();
$log.= "log event\n";
}
$incr=(int)$incr+1;
if(false==$memcache->replace($usrHash,$incr,0,300)){
$memcache->set($usrHash,$incr,0,300);
$log.="user hash count updated:$incr\n";
}else{
$log.="user hash count updated:$incr\n";
}
$out=$memcache->get($urlHash);
if($out!=false){ //increment count
$resp=json_decode($out,true);
if( isset($resp)){
$mm=$resp;
$resp[‘total’]=(int)$resp[‘total’]+1;

foreach($mm as $key=>$val){
if($key==$destination){
$resp[$key]=(int)$resp[$key]+1;
}
}
$memcache->replace($urlHash,json_encode($resp),0,60); //sets the new count in mc for 60 seconds
$log.="count updated and replaced\n";
}
}
}else{
logEvent();
}
$t2=microtime(true);
$totaltime = ($t2 – $t1);
$totaltime=round($totaltime,4);
$log.="Method: ProcesssAndLog time: $totaltime seconds\n";

}

function logEvent(){
global $url,$title,$content,$destination,$ip,$agent,$refer,$clicookie2,$token,$publisher,$fpc,$sessionID,$source,$aurl,$log;
if(defined("L_LOG_SERVER")){
$lserver=L_LOG_SERVER;
}else{
$lserver="l.sharethis.com";
}
$lurl="http://$lserver/log?event=click&source=$source"
."&url=".urlencode(isset($aurl) ? $aurl :$url)
."&title=".urlencode($title)
."&destinations=".$destination
."&ip=".$ip
."&agent=".urlencode($agent)
."&refer=".urlencode($refer)
."&clicookie=".$clicookie2
."&token=".$token
."&publisher=".$publisher
."&fpc=".$fpc
."&sessionID=".$sessionID;
$curl = curl_init();
if(curl_setopt($curl, CURLOPT_FAILONERROR, TRUE) === FALSE) return FALSE;
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_URL, $lurl);
if(defined("CHARLES") && defined("CHARLES_LOC")){
curl_setopt($curl, CURLOPT_PROXY, CHARLES_LOC); //for charles
}
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 2);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
$log.="Method: logEvent, Total time for call: ".$info[‘total_time’]."\n";
if($info["http_code"]=="200" || $info["http_code"]=="204"){
return true;
}else{
$log.="ERROR:  logging call failed http code:".$info["http_code"]."\n";
return false;
}
}

function call_api($method, $params){
global $log;
$url = "http://" . API_SERVER . "/" . $method . ".php";
$curl = curl_init($url);
$params["return"] = "php";
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_TIMEOUT, 2);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params, ”, ‘&’));
if(curl_setopt($curl, CURLOPT_FAILONERROR, TRUE) === FALSE) return FALSE;
if(defined("CHARLES") && defined("CHARLES_LOC")){
curl_setopt($curl, CURLOPT_PROXY, CHARLES_LOC); //for charles
}
$response = curl_exec($curl);
$info = curl_getinfo($curl);
curl_close($curl);
$log.="Method: $method, Total time for call: ".$info[‘total_time’]."\n";

if($info["http_code"]=="200"){
try{
$retval = unserialize($response);
return $retval;
}catch(Exception $e){
return false;
}
}else{
$log.="ERROR: $method failed http code:".$info["http_code"]."\n";
return false;
}
}
[/code]
Lo que vemos en este código es en sí el codigo PHP del script. Si así es, increíble como podemos visualizar el server side code de este servicio de una manera tan sencilla. No he colocado el código completo del archivo por cuestion de seguridad pero esto es el resultado de la incompatibilidad entre navegadores y la no optimización para que neustro código funcione de manera segura.

La moraleja es notar que el documento no cuenta con una declaración de DOCTYPE y esto es el fallo No.1, lo segundo es cómo google chrome puede poner en peligro nuestros sistemas en la web y tercero, debemos tomar medidas extremas y por mas tedioso que paresca es importante probar nuestras web apps en todos los navegadores, no solo por estética, sino también por seguridad.

Ya he notificado a la gente de sharethis.com sobre este “fallo”, e hice la observación de que no es la primera vez que Google Chrome no codifica la programación server side lo cual es un serio caso de falla de seguridad.

Para mi sorpresa también he detectado el fallo en Firefox, es esencial la seguridad y la revisión de nuestro código antes de colgar en producción nuestras apps con servicios terceros.