Estoy mirando una biblioteca para acceder a bases de datos muy copada que se llama sequel. En la misma no hay que declarar nada y el mapeador solo sabe como hacer para acceder a todo (como debería ser). Y quise ver como hace el sql que va a la base, así que prendí el irb e hice un poquito de "aspect programming alla ruby". Primero importé la biblioteca y el driver para postgres y les agregué datos (todo usando la biblioteca sequel desde adentro del irb y sin escribir una línea de SQL).
Pero después me agarró la duda de cómo se generaba el SQL. ¿Tendría quizás alguna forma de hacer un SQL injection si uso la biblioteca para hacer una página web? Lo que siempre me gustó de bibliotecas como ActiveRecord e Hibernate, es que me quitan la responsabilidad por estas cosas. Así que puse manos a la obra.
Una mirada rápida por la documentación y el código no me llevó a la opción de mostrar todo el sql que se ejecuta, así que tuve que hacer un toque de magia.
irb(main):042:0> class Sequel::Postgres::Dataset
irb(main):043:1> alias_method :select_sql_old, :select_sql
irb(main):044:1> def select_sql(*p)
irb(main):045:2> sql = select_sql_old(*p)
irb(main):046:2> puts(sql)
irb(main):047:2> sql
irb(main):048:2> end
irb(main):049:1> end
¿Qué hice? Hice "aspect programming alla ruby". Cambié cómo se hace para generar el sql de las consultas en postgres para que lo muestre por pantalla (solo en mi sesión de irb).
A partir de este momento (y hasta que lo vuelva atrás o salga del irb) me muestra el SQL de cada SELECT que haga a la base.
Así que ahora puedo mirar fácil que pasa si trato de inyectar SQL:
irb(main):053:0> user_name = "aaaa ' or 1=1"
=> "aaaa ' or 1=1"
irb(main):054:0> users.where(:name => user_name).all
SELECT * FROM users WHERE ("name" = 'aaaa '' or 1=1')
=> []
Soy feliz, y veo que la biblioteca parece estar bien pensada (al menos para esto).
Happy hacking,
Aureliano.