Cuatro Meses y Medio

Una actualización después de mucho: Como varios de los que me conocen en persona o de redes sociales saben, estoy viviendo en Buenos Aires hace un poco más de cuatro meses.

Cuesta dejar el lugarcito que uno se ganó, las comodidades, los amigos, la familia... arriesgar lo ya conquistado para así poder crecer aún más. Es cierto que en Encarnación tenía un buen trabajo, todo cerca y accesible, pero era lo mismo que ya tenía hace mucho y no estaba aprendiendo cosas nuevas. Y charlé con un amigo, me comentó de una oferta de trabajo, de ahí surgió una conversación por email, luego unas entrevistas. Y surgió una propuesta, y me jugué y me vine.

Si bien no tuve que aprender ningún idioma nuevo, me sigo adaptando a la cultura, al ambiente, a los códigos de un nuevo lugar y la forma de hacer las cosas que requiere una ciudad grande. Aprendí a moverme con transporte público, a saber que cualquier trámite puede llevarte la mitad de un día, a que todo está lejos, pero se sobrelleva bien cuando existe infraestructura y un mínimo de organización.

Luego del shock inicial de las primeras semanas, el simple hecho de estar expuesto a nuevos estímulos en un lugar donde requiere toda mi atención resulta una experiencia sumamente gratificante. Estoy trabajando en un proyecto muy diferente a todo lo que hice anteriormente en cualquier otro lugar. Estoy jugando con tecnología nueva, y también resulta que tengo compañeros de trabajo muy copados. Estoy aprendiendo técnicas en un área que siempre me resultó atrapante: todo lo relacionado a lenguajes de programación y análisis de código.

Empezar esta aventura está siendo una de las mejores decisiones que tomé en mi vida.

Hackeo a NIC.PY

Sorry, this post is spanish only.

En la tarde de hoy jueves, un compañero de trabajo me comenta que la página principal del sitio www.google.com.py fue modificada. Descartando algún problema con Google en sí (en donde trabajan algunos de los mejores expertos en seguridad del mundo), mi primer sospecha fue que el servicio DNS a nivel Paraguay fue comprometido. Lo cual es evidente siguiendo el enlace a la página de los "hackers" iraníes, que relata el detalle del ataque realizado: http://ha.cker.ir/2014/02/www-nic-py-py-registrar-rce-vulnerablity/.

DN... ¿qué?

El sistema de DNS (Domain Name System o Sistema de Nombres de Dominio) es un componente crucial en el funcionamiento de Internet. Su tarea principal es la de poder traducir nombres legibles para seres humanos, como google.com, www.mibanco.com.py, etc, en direcciones numéricas de cuatro números separados por puntos, como 201.217.0.176 o 201.217.19.9.

Estos números tienen por nombre "dirección IP" y sirven para que una máquina pueda establecer una conexión con otra dentro de Internet. Básicamente, cada equipo conectado a la red tiene asignado una dirección IP. Cuando una computadora (de escritorio, tablet o celular) desea acceder a un sitio web por su nombre, si o si debe realizar una consulta DNS para convertir el nombre consultado en una dirección IP.

¿Y cómo me afectaría algo así?

La clave para entender la gravedad de lo que ocurrió, es que el sistema DNS funciona de manera jerárquica. La jerarquía comienza por los Servidores Raíz DNS, que delegan la respuesta de consultas por sitios con la terminación '.py', a los servidores DNS de NIC.PY, que pueden responder con autoridad por CUALQUIER sitio que termine en .PY. Esto hace posible que alguien que llegue a tener acceso a NIC.PY, pueda alterar a qué servidor físico se accede cuando se ingresa una dirección cualquiera que termine en .PY, simplemente respondiendo con una dirección IP diferente a la auténtica, para una determinada consulta.

Esto permitiría a un atacante realizar una copia de un sitio web de algún banco local y alojarlo en un servidor de su propiedad que automáticamente almacene las credenciales para los usuarios que intenten acceder a la banca web del mismo. Un usuario no técnico difícilmente tenga posibilidad de darse cuenta de que no está accediendo al sitio que desea, ya que la barra de direcciones del browser mostraría una dirección correcta. Lo del banco es sólo un ejemplo, pero practicamente cualquier sitio con la terminación .PY puede verse afectado por un ataque así.

Esto es alarmante, no sólo por el abanico de posibilidades que abre el ataque que se realizó, sino por lo relativamente sencillo que les fue a los atacantes realizar las alteraciones de dominio, evidenciados en los siguientes motivos:

Técnicamente hablando, el servidor de NIC.PY:

  1. Usa un Sistema Operativo muy desactualizado. Día a día se descubren errores en muchos componentes de software que forman parte de un servidor, desde el componente principal (kernel) del sistema operativo, y varios de los componentes que brindan servicios de red, como por ejemplo, la posibilidad de servir páginas Web. El sitio de los "hackers" mostraba claramente que varios de los componentes del servidor de NIC.PY no habían sido actualizados desde 2010.
  2. Utiliza una aplicación web vulnerable a ejecución remota de código. Esto significa que una persona, virtualmente desde cualquier parte del mundo, puede enviar una combinación especial de texto a la web del NIC.PY usando únicamente su navegador web, con lo cual se pueden ejecutar comandos que resulten en exposición de información confidencial del equipo de NIC.PY, alteración de datos, destrucción de información, y un sinnúmero de actos que ponen en riesgo el funcionamiento correcto de los servicios que brinda.
  3. No poseía un esquema mínimo de hardening. Se llama "hardening" a una práctica correspondiente a ocultar información de los servicios que se ejecutan en un servidor, y en el caso de una intrusión, dificultar que el atacante pueda lograr privilegios que le permitan alterar información en el equipo atacado. Por la facilidad con la que los intrusos detallan su ataque, nada de eso fue realizado.

A todos estos factores, hay que sumar a que ya fueron explotados previamente (al menos 5 años atrás!), y nuevamente en el 2012, sin siquiera tomarse la molestia de 'limpiar' el equipo de los rastros de ataque. Y que varias de las falencias técnicas comentadas aquí ya fueron expuestas en ocasiones previas: http://ticpy.blogspot.com/2008/11/el-cnc-y-una-nueva-negligencia_4917.html.

Para un país con una brecha digital inmensa, con deficiencias de infraestructura enormes en los servicios más básicos, esto constituye una muestra más de la desidia y falta de capacidad de quienes nos gobiernan, que con su inacción no solamente nos siguen sumiendo en el atraso, sino que también ponen en riesgo nuestras actividades diarias.

A self contained SQL parser/pretty printer

For a great part of the day, I work as an backend developer, dealing with writing and reviewing all kinds of SQL to move data in commercial(a.k.a. enterprise) applications. For that purpose, using a tool that formats SQL statements is essential, in order to keep your code as neat as possible and easier to mantain.

I've used some commercial and freemium applications such as SQLInform, and also sites like http://sqlformat.org/ and http://www.dpriver.com/pp/sqlformat.htm from time to time. But always felt that there is no need to use this kind of "heavy" applications for something that could be done entirely in JavaScript, self-contained, and possibly, evolving through Open Source.

So I ended up writing a simple SQL formatter/pretty printer that works in a browser, with no need for server-side processing.

You can find it here: http://codespeak.cc/sequeljs

Working entirely on the browser, SequelJS has the additional benefit that developers aren't forced to disclose details of schema design or business issues to third parties, because there isn't any data transferred through the ether when formatting statements.

Currently, the formatter still lacks important features (like parsing comments or establishing a max line width), but can handle an nice subset of SELECT queries, with joins, subquerys, expressions, function calls, etc. The current style of indentation is just what I'm accustomed to, but is something that will be possible to tune in future releases.

When building a program to process SQL statements, it's important to settle on which set of possible statements are accepted as valid, and also recognize their structure. In compilers jargon, this is called a grammar.

Some SQL grammars can get tough quickly. Parsing real-life SQL statements (like PostgreSQL/MSSQL ones) —even if only to format them— is a difficult task. So I started from scratch, using the H2 SQL grammar as a foundation, which I believe is a really nice basis for a design that can be evolved organically.

SequelJS uses the great Jison library, which is a JavaScript port of the Bison LALR parser. Color formatting is done with the prettify library.

I plan to keep adding new features in the following days. If you want to contribute, feel free to fork the project on GitHub.

On simple language and API design: Java vs. Python

How do you capture the latest 15 chars on a Java String? Easy!

String str = "The quick brown fox";
String last = str.substring(str.length() - 15);
System.out.println(last);

What if, for some misfortune, you read a String with less than 15 characters?

String str = "The quick";
String last = str.substring(str.length() - 15); // boom
System.out.println(last);

If you're not careful enough with the sizes of the Strings you're dealing with, you end with a StringIndexOutOfBoundsException, which is a Exception than aborts the execution of the flow of code in that thread.

The natural solution for that is creating a method as follows:

static String rightmost(String s, int amount) {
    int len = s.length();
    if (amount > len) return s;

    return s.substring(len - amount);
}
public static void main(String[] args) {
    System.out.println(rightmost("The quick brown fox", 15)); // Outputs "quick brown fox"
    System.out.println(rightmost("The quick", 15)); // Outputs "The quick"
}

The lack of a no-surprises implementation for trivial operations makes Java a language that's difficult for begginers to grok. In simple stuff like this is where a well-designed language like Python shines:

st = 'The quick brown fox'
print st[-15:] # prints 'quick brown'
st = 'The quick'
print st[-15:] # prints 'The quick'

Three points here:

  • First, Python substring manipulation is first class (by letting you grab a piece of the string simply by using the [] operator)
  • Second, it takes care of indexes that may be overflow the size of the string (think: forget bounds-checking, we're not doing C here!)
  • Third, it lets you express succinctly "grab the last 15 chars" by using the [-15:] notation, where you also could use [:-15] to say "all except the last 15 chars"

It's intuitive, it's safe, and I'm inclined to say... beautiful, too.

String subscripting in Python is just a small but tremendously useful feature of the language. Learn more about it here.

Final note: Yes, I know there is something called StringUtils inside CommonsLang that contains a safe version of the substring method, an implementation of rightmost (as right), and a myriad of other methods for String manipulation. But let's say we try hard to avoid bundling yet another library.

High level concepts

A couple of days ago, I was revisiting a Java piece of code that needed some changes. It's about an app that listens on a TCP socket, and receives ASCII lines that processed individually.

Each line represents commands that do different things, and they all share the same trait: they encode an operation and parameters partitioned by a separator, let's say it's '#'. Examples follow:

41#200000#Y#15020#17010

26#124#N#300500#0#8000324

340#100#400#11.10#0#2050#11#Y#Y

You can't extract the diferent fields in each line just by reading them in fixed position, because a) there may be different amount of parameters and b) each parameter can have different lengths.

So the natural solution is using the well-known string function: "split". But instead of that, what I found was something like:

String[] params = new String[100];
...
while (true) {
  /* code to grab the indexes here ...*/
  params[idx] = string.substr(pos0, pos1);
  /* code to exit loop if done ... */
  idx++;
}

Which is maybe what a freshman student will write in its college C class.

The problem is... this is code that was written by a programmer with at least 10 years of experience! Besides using a convoluted logic, I'd argue that this shows the programmer has a lack of knowledge for high level patterns.

The simple abstraction "separate this string into it's N parts by a delimiter", while not often seen in C, is used everywhere in all kind of code in high-level languages such as Python, JavaScript. Or even PHP.

I believe there may be need in programming to reinvent the wheel from time to time. But not to solve this simple kind of problems. And getting acquainted in these common patterns is just critical to solve real problems in software.

Keep Calm and do not Reinvent the Wheel

So that's why programmers need to be exposed to such commonplace concepts, learning how to solve common problems in different programming languages as early as possible in their careers.