Está en la página 1de 36

THE ORIGINAL HACKER

SOFTWARE LIBRE, HACKING y PROGRAMA-


CIN, EN UN PROYECTO DE
EUGENIA BAHIT

@eugeniabahit
GLAMP HACKER Y
PROGRAMADORA EXTREMA
HACKER ESPECIALIZADA EN PROGRAMACIN
EXTREMA E INGENIERA INVERSA DE CDIGO
SOBRE GNU/LINUX, APACHE, MYSQL,
PYTHON Y PHP. EUGENIABAHIT.COM
DOCENTE E INSTRUCTORA DE TECNOLOGAS
GLAMP CURSOS.EUGENIABAHIT.COM
CURSOSDEPROGRAMACIONADISTANCIA.COM
MIEMBRO DE LA FREE SOFTWARE
FOUNDATION FSF.ORG, THE LINUX
FOUNDATION LINUXFOUNDATION.ORG E
INTEGRANTE DEL EQUIPO DE DEBIAN
HACKERS DEBIANHACKERS.NET.
CREADORA DE PYTHON-PRINTR, EUROPIO
ENGINE, JACKTHESTRIPPER. VIM CONTRI-
BUTOR. FUNDADORA DE HACKERS N'
DEVELOPERS MAGAZINE Y RESPONSABLE
EDITORIAL HASTA OCTUBRE '13.
Buenos Aires, 3 de
Diciembre de 2013
NDICE DE LA
EDICIN NRO2
INGENIERA INVERSA : DESARROLLAR SOFTWARE
APLICANDO LA INGENIERA INVERSA: EL ARTE DE LA
CIENCIA......................................3
PYTHON SCRIPTING : MANIPULAR ARCHIVOS DE
CONFIGURACIN MEDIANTE CONFIGPARSER..........8
INGENIERA DE SOFTWARE : AGREGADO DE ARCHIVOS
CRON Y EJECUCIN PERIDICA DE PROCESOS EN LOS
PAQUETES .DEB...............................18
EUROPIO ENGINE LAB : CMO SE HICIERON LOS ABM
DE LA WEB THE ORIGINAL HACKER LIBRARY?...21
SEGURIDAD INFORMTICA : CAPAS DE SEGURIDAD
INTELIGENTES EN PHP S ANEAMIENTO DEL ARRAY
SUPERGLOBAL $_POST.........................31
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
3
DESARROLLAR SOFTWARE
APLICANDO LA INGENIERA
INVERSA: EL ARTE DE LA
CIENCIA
DESARROLLAR SOFTWARE
PUEDE CONVERTIRSE EN UN
VERDADERO ARTE
CIENTFICO SI SE ES
CAPAZ DE COMBINAR
PARALELAMENTE, LGICA Y
PENSAMIENTO LATERAL. Y
ESO, ES LO QUE LA
INGENIERA INVERSA NOS
PROPONE. EN ESTA EDICIN
DE THE ORIGINAL HACKER,
VEREMOS EN QU CONSISTE
LA INGENIERA INVERSA DE
SOFTWARE APLICADA
DURANTE SU DESARROLLO.
i alguna vez te viste envuelto en una maraa de ideas y
procedimientos al momento de desarrollar una determinada
funcionalidad y terminaste enredndote tanto que decidiste
dibujar! lo que necesitabas alcanzar y desde all"# fuiste
sustituyendo tu dibujo! por c$digo hasta terminarlo# lo que hiciste#
fue aplicar un procedimiento de ingenier"a inversa para resolver ese
requerimiento que tanto te enredaba.
%
& la ingenier"a inversa muchas veces se le suele tener miedo y esto
sucede 'creo yo' por la inmensa cantidad de mitos alrededor de
este maravilloso concepto pero por sobre todo 'y en definitiva'# por
la gran ignorancia y desconocimiento sobre su e(istencia.
La ingeniera inversa plantea una
forma lateral de alcanzar
objetivos, partiendo del resultado
-el qu- para obtener el modo de
alcanzarlo -el cmo-
La ingenier"a inversa es amplia. )s amplia como ciencia y como
t*cnica pero tambi*n como concepto# ya que si bien posee un +nico
significado# sus aplicaciones son tan variadas y dis"miles que es all"
donde se produce la distorsi$n conceptual que tantos miedos
genera.
&l proponer el inicio de los procesos partiendo del objeto final# es que com+nmente se la relaciona con una de
sus aplicaciones ms frecuentes,
-ngenier"a -nversa de .ardware , aquella que# partiendo de un componente f"sico /hardware0 cuyo
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
4
c$digo es privativo /no libre# no abierto0# intenta obtener un software que permita reemplazar al
controlador del fabricante.
%in embargo# no es +nicamente en esta rea donde la ingenier"a inversa se aplica. La ingenier"a inversa tiene
much"simas ms aplicaciones# entre ellas,
-ngenier"a -nversa de c$digo , aquella que va siguiendo la pista! del c$digo fuente de una aplicaci$n
ya sea tanto para entender la forma en la que *sta funciona como para detectar fehacientemente
vulnerabilidades que no podr"an ser halladas mediante herramientas para pruebas de intrusi$n
automatizadas /que tan de moda se han puesto en los +ltimos tiempos pero que sin embargo# no han
sido capaces hasta el momento# de sustituir ni reemplazar la inteligencia humana01
-ngenier"a -nversa de %oftware , ya sea para descomposici$n de aplicaciones /generalmente# aplicada
para desentraar un %oftware cerrado y privativo0 o para el caso contrario# la composici$n de
%oftware# a la cual nos dedicaremos en este art"culo.
TDD: EL EJEMPLO PERFECTO DE INGENIERA INVERSA DE
SOFTWARE APLICADA AL DESARROLLO
La t*cnica e(trema 233 (Test-Driven Development)#
que en espaol se traduce como Desarrollo guiado
por prueas# es un claro ejemplo de c$mo la
-ngenier"a -nversa aplicada al desarrollo de %oftware
logra l$gicas realmente simples de comprender y
prcticamente un"vocas e inequ"vocas.
4uy frecuentemente# confundimos 5nit 2esting
/pruebas unitarias0 con 2est'3riven 3evelopment y
2est'6irst 7rogramming. )stos errores de concepto
pueden generar que jams se logre entender con
e(actitud# qu* es la -ngenier"a -nversa# c$mo se
aplica y para qu* es necesario implementarla. 7or
ello# me gustar"a tratar de e(plicar los tres conceptos
con la esperanza de que por fin# queden claramente
diferenciados entre s".
)n principio# podemos decir que 5nit 2esting# 2est'
6irst 7rogramming y 233# son tres t*cnicas donde
de menor a mayor! una es requerida por la otra. )s
decir que 233 necesita de 2est'6irst 7rogramming y
*ste# de 5nit 2esting. )s por ello# que comenzaremos
defini*ndolos de menor a mayor!.
!nit "esting
Las pruebas unitarias simplemente son funciones
destinadas a evaluar una +nica acci$n del c$digo
fuente. )s as" que si en nuestra aplicaci$n tenemos
una funci$n destinada a eliminar etiquetas .24L de
una cadena de te(to# podremos tener# en paralelo 8
m*todos por ejemplo# que pasen 8 cadenas de te(to
diferentes a nuestra funci$n y comprueben que el
valor de retorno sea efectivamente el esperado.
Las pruebas unitarias como tales# no requieren de
-ngenier"a -nversa y de hecho# hasta pueden ser
generadas de forma automatizada# por lo que de
forma aislada# no pueden considerarse como una
t*cnica e(trema. %in ir ms lejos# las pruebas
unitarias podr"an escribirse una vez que la aplicaci$n
se encontrase ya desarrollada.
"est-#irst $rogramming
)sta es una t*cnica que consiste en escribir primero
las pruebas unitarias y luego el c$digo de la
aplicaci$n.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
5
)sta t*cnica ya es un poco ms compleja que el
mero hecho de escribir pruebas unitarias pero sin
embargo# no alcanza a ser una t*cnica de -ngenier"a
-nversa# puesto que podr"a facilitarse tranquilamente#
el diseo de lo que se quiere lograr /es decir# el
c$mo!0 antes de contar e(actamente con el objeto
/es decir# el qu*!0.
"DD % "est-Driven Development
)l desarrollo guiado por pruebas# es pura y
e(clusivamente una t*cnica e(trema de -ngenier"a
-nversa que plantea pensar primero en lo que se
quiere lograr /es decir el qu*!0 y partiendo de
pseudo'prototipos /que a veces no son ms que el
resultado hardcodeado de un ejemplo de lo que se
desea lograr0 ir implementando el m"nimo c$digo
necesario para que dicho pseudo'prototipo deje de
serlo. 9 para escribir el m"nimo c$digo necesario#
propone utilizar 2est'6irst 7rogramming c$mo t*cnica
para la implementaci$n de las pruebas unitarias.
&$or 'u( de)imos 'ue la t()ni)a de "DD es
*ngenier+a *nversa pura,
7orque para que *sta est* bien implementada# se
debe partir el desarrollo desde lo que se quiere lograr
para alcanzar de a poco el c$mo lograrlo.
COMPRENDIENDOEL QU: COMENZAR POR EL RESULTADO
& lo largo de los aos he notado que lo que ms le cuesta entender a todas las personas es qu* es
e(actamente a lo que nos referimos cuando hablamos de resultado!# es decir# qu* es e(actamente el qu*!.
9 de verdad# que de tan simple que me resulta# a veces creo que esa obviedad es la que lo hace tan dif"cil de
entender como quizs tambi*n de e(plicar. El resultado es e-a)tamente lo 'ue esperas ver )uando
ha.as terminado tu apli)a)i/n . la utili)es por primera ve01
7aso a paso# un ejemplo muy sencillo y de fcil comprensi$n sobre c$mo se implementar"a la -ngenier"a
-nversa en el desarrollo de %oftware# podr"a ser el siguiente,
:. Se identi2i)a lo 'ue se 'uiere al)an0ar3
por ejemplo# un generador de formularios de contacto1
21 Se identi2i)a a'uello 'ue produ)ir4 nuestro So2t5are terminado3
por ejemplo# un formulario .24L1
31 Se )rea un prototipo del produ)to de nuestra apli)a)i/n3
es decir# se crea un archivo .24L con un formulario de contacto a modo de ejemplo1
61 Se implementa el m+nimo )/digo ne)esario para 'ue ese 2ormulario sea retornado3
por ejemplo# desde el lenguaje de programaci$n en el que se vaya a desarrollar la aplicaci$n# se
proceder"a a crear una funci$n que lea el contenido del archivo .24L y lo retorne. & continuaci$n# una
instrucci$n# llamar"a a dicha funci$n imprimiendo en pantalla el valor de retorno1
71 Se pro)eder+a a repetir el paso 68 de a un +tem por ve03
esto se har# hasta lograr que el formulario .24L sea generado de forma :;;< dinmica1
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
6
=uando adems# se implementa "DD como t*cnica para lograr el paso ># la di2eren)ia )on la gu+a
anterior8 es 'ue tras el paso 38 se apli)a Test-First Programming para lograr el paso >.
TROUBLESHOOTING: INGENIERA INVERSA
)ste subt"tulo fue puesto e( profeso a fin de que a trav*s del humor ' considerando a la -ngenier"a -nversa un
problema a resolver! ' se puedan plantear formas amenas y humanas! de llevar a cabo tal t*cnica.
$rolema3 se )on2unde el 'u( )on el )/mo
3escripci$n del problema,
?eneralmente# el primer problema al que uno se enfrenta es saber identificar el qu* sin pensar en el c$mo. 9
esto# se soluciona solo y +nicamente con un cambio radical de actitud.
@bjetivo,
7erderle el miedo a lo desconocido1
&prender a convivir con la incertidumbre y aceptar que el c$mo llegar a su debido momento1
&ceptar que lo simple es preferible a lo complejo y lo complejo es preferible a lo complicado1
.acerse a la idea de que todo es posible y que alcanzar objetivos no es un problema, el problema es
identificarlos1
%oluci$n,
:. 3efinir lo que se quiere lograr a modo de .istoria de 5suario, como AusuarioB puedo Aacci$nB1
C. 7ensar en la acci$n de la .istoria de 5suario como en una aplicaci$n completa /un todo01
D. .acerse la pregunta Equ* voy a obtener cuando la funcionalidad est* operativaF 9 responder a ella con
una sola frase corta utilizando la menor cantidad de calificativos y de verbos posibles. Lo ideal es
centrarse en los sustantivos.
$rolema3 se tiende a pensar en 9el )/mo: )omo un todo . en ve0 de )omen0ar el desarrollo por
el 2inal se )omien0a por el prin)ipio
3escripci$n del problema,
@tro de los problemas ms frecuentes es que una vez hallado el qu*! no se logra implementar un desarrollo
inverso y por el contrario# se comienza a escribir el c$digo de la manera que se lo har"a tradicionalmente. )sto
genera un estancamiento en el desarrollo y consecuente falta de prolijidad en el c$digo generado.
@bjetivo,
&prender a pensar lateralmente1
-mplementar la l$gica y el pensamiento lateral en paralelo para aplicar la -ngenier"a -nversa de forma
correcta.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
7
%oluci$n,
4ientras que en pasos anteriores se defini$ de forma lineal lo que se pretend"a lograr# ahora es
momento de razonar de manera l$gica para obtener el siguiente paso /como si se tratase de una
secuencia a la que se quiere dar continuidad0. )s decir# el siguiente paso consiste en escribir el m"nimo
c$digo necesario para sustituir algo!. )se algo! es el que debe estar desencadenado por una
secuencia l$gica1
7ara encontrar dicha secuencia# una gran parte de las veces# puede ser necesario mirar el problema!
desde diversos ngulos# es decir# analizar lo que se tiene de forma lateral1
.allada la secuencia# se debe elegir uno y solo un! punto de partida y concentrarse solo y
+nicamente en escribir el c$digo que resuelva ese 'y no otro' "tem# evitando pensar en otros "tem o en
lo que se necesitar resolver ms adelante.
Es importante comprender que la Ingeniera Inversa demandar hacer un uso
continuo del Refactoring y tomar la no-necesidad de refactorizacin del
cdigo como un error de diseo prcticamente asegurado.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
8
PYTHON SCRIPTING:
MANIPULAR ARCHIVOS DE
CONFIGURACIN MEDIANTE
CONFIGPARSER
EL MDULO CONFIGPARSER
DE PYTHON RESULTAR DE
UNA GRAN AYUDA PARA
DESARROLLAR SCRIPTS QUE
NOS PERMITAN AUTOMATIZAR
TAREAS GENERALMENTE
RELACIONADAS CON LA
INSTALACIN DE
APLICACIONES EN LAS
CUALES, TANTO LA
CONFIGURACIN COMO LA
OPTIMIZACIN Y
ASEGURAMIENTO DE LAS
MISMAS, CUMPLA UN PAPEL
PRCTICAMENTE
PROTAGNICO.
esde herramientas como failCban hasta aplicaciones como
4y%GL y 7.7# utilizan archivos de configuraci$n basados
en secciones y# nada ms usual# que la necesidad de crear
scripts automatizados que ayuden a los administradores de
sistemas o especialistas en seguridad /o .acHers Iticos si eres de
os que disfruta los eufemismos marketineros0 a configurar de forma
$ptima estos archivos.
3
?eneralmente# como programadores# resolvemos esta necesidad
haciendo malabares!# utilizando e(presiones regulares#
reemplazando archivos y un sinf"n de alternativas que si bien
solucionan el problema# claramente nos dan hartos dolores de
cabeza.
%in embargo# desde hace much"simo tiempo# 7ython nos provee en
su librer"a estndar un m$dulo cuya responsabilidad# es justamente#
la de permitirnos la manipulaci$n de archivos de configuraci$n
basados en secciones. %e trata del m$dulo ConfigParser
/renombrado a configparser en 7ython D0.
)l m$dulo =onfig7arser permite tanto la lectura como edici$n de
archivos de configuraci$n basados en secciones. =omo bien
coment* al inicio# ejemplo de este tipo de archivos# podr"an ser
fail2ban.conf de failCban# my.cnf de 4y%GL o php.ini de
7.7# entre otros tantos.
Jo obstante# ConfigParser no ser +nicamente un m$dulo destinado solo a un p+blico relacionado a la
administraci$n del sistema1 tambi*n puede ser una buena alternativa# para que los programadores
implementen sistemas de configuraci$n a sus propias aplicaciones. -ncluso hasta puede ser sumamente +til
para implementar en aplicaciones Keb en las cules se requieran interfaces en m+ltiples idiomas.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
9
)n estos casos# los archivos de configuraci$n podr"an servir para definir te(tos estticos en los diversos
idiomas que la aplicaci$n requiera y toda alternativa de personalizaci$n que se le quiera permitir al usuario#
podr"a realizarse de forma sencilla# evitando el consumo de recursos producido por la implementaci$n de
bases de datos. 7or ejemplo# suponiendo una aplicaci$n Keb en espaol# ingl*s y cataln# podr"an tenerse tres
archivos,
textos.es
textos.ca
textos.en
9 cada uno de ellos# contar con las mismas secciones y variables /reconocidas por ConfigParser como
opciones!0# pero por supuesto# diferentes valores,
; Archivo textos.es
[modulos]
clientes = Clientes
proveedores = Proveedores
[acciones]
administrar = Administrar
editar = Modificar
eliminar = liminar
; Archivo textos.en
[modulos]
clientes = Clients
proveedores = !uppliers
[acciones]
administrar = Manage
editar = dit
eliminar = "elete
=omo se puede ver# la finalidad de ConfigParser es directamente proporcional a la cantidad de usos que se
le puede dar a los archivos de configuraci$n basados en secciones y el +nico l"mite# est en la imaginaci$n y
creatividad del programador.
CREAR ARCHIVOS DE CONFIGURACIN CON CONFIGPARSER
=uando se trata de efectuar tareas de administraci$n yLo de seguridad# dif"cilmente se necesiten crear los
archivos de configuraci$n de las aplicaciones que se estn optimizando. ?eneralmente# la )rea)i/n de estos
ar)hivos8 ser4 ;til )uando se los re'uiera para apli)a)iones propias1
La no inclusin de archivos de configuracin por defecto en
aplicaciones propias, puede utilizarse como parmetro condicional
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
10
deductivo para la lgica de instalacin
7or supuesto# que estos archivos podr"an incluirse por defecto en la aplicaci$n# pero la no inclusi$n# podr"a
utilizarse como parmetro deductivo en la l$gica de instalaci$n, si el ar)hivo no e-iste8 la instala)i/n no
se ha )on)luido.
ConfigParser fue renombrado a configparser desde Python 3. La herramienta
2to3 efecta el cambio de nombre automtico en la importacin del mdulo, al
momento de convertir el cdigo fuente.
5n ejemplo bsico de c$mo crear un archivo de configuraci$n desde ConfigParser aplicando una l$gica
deductiva# podr"a verse como el siguiente,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ConfigParser import RawConfigParser
from os import path
# Si el rchivo de configurci!n no existe
if path.exists('myapp.conf') is False:
# "regunto si se lo dese crer
print #$a aplicaci%n a&n no se ha configurado correctamente#
continuar = ra'(input)#*"esea configurarla ahora+ ),-n. #.
# #reo el rchivo de configurci!n
if continuar.lo'er). == #y#/
cparser = RawConfigParser() # Se cre el ob$eto #onfig"rser
'ith open)#myapp.conf#0 #'b#. as archivo/
cparser.write(archivo) # Se escribe el rchivo de configurci!n
else/
exit). # %inli&o l plicci!n si el usurio eligi! no concluir l instlci!n
print #Contin&o con la e1ecuci%n...#
2a'ConfigParser es el objeto de configuraci$n bsico que utiliza ConfigParser. %in embargo# el objeto
SafeConfigParser tambi*n se encuentra disponible,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ConfigParser import SafeConfigParser
#...
if continuar.lo'er). == #y#/
cparser = SafeConfigParser()
'ith open)#myapp.conf#0 #'b#. as archivo/
cparser.'rite)archivo.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
11
& simple vista# no se puede notar ninguna di2eren)ia entre RawConfigParser . SafeConfigParser# sin
embargo# este +ltimo cuenta con una caracter"stica que lo convierte en mgico!, permite la interpolaci$n de
variables en los archivos de configuraci$n.
A diferencia de '(#onfig"rser, SafeConfigParser
permite la interpolacin de variables en los arcivos de configuracin
; Archivo de configurci!n
; )$e*plo de interpolci!n de vribles
[miseccion]
carga(maxima(permitida = 344 (!ni"a"#"e#me"i"a)s
!ni"a"#"e#me"i"a = M5
; el valor de carga_maxima_permitida ser +,, conctendo l vlor de unidd-de-*edid
; es decir: 100 MB
%e debe tener en cuenta que la interpolaci$n anterior# solo ser posible si se utiliza !afeConfigParser.
)n el ejemplo anterior# nos limitamos a crear un archivo de configuraci$n en blanco# lo cual claramente# no
tendr"a mucho sentido. %in embargo# completar el archivo# no es nada dif"cil. Basta con agregar las
se))iones con a""#section)#nombre(de(la(seccion#. e in)luir variales y valores con
set)#seccion#0 #variable#0 #valor#.. & continuaci$n# un sencillo ejemplo que lo aclarar todo,
67-usr-bin-env python
6 898 coding/ utf8: 898
from ConfigParser import SafeConfigParser
from os import path
if path.exists)#myapp.conf#. is ;alse/
print #$a aplicaci%n a&n no se ha configurado correctamente#
continuar = ra'(input)#*"esea configurarla ahora+ ),-n. #.
if continuar.lo'er). == #y#/
cparser = SafeConfigParser()
cparser.a""#section('$ccesos')
cparser.set('$ccesos'% 'servi"or'% '&'(.)*+.,-../')
cparser.set('$ccesos'% '!s!ario'% 'pepegrillo')
cparser.set('$ccesos'% 'p!erto'% '&//&')
'ith open)#myapp.conf#0 #'b#. as archivo/
cparser.write(archivo)
else/
exit).
# ...
Lo anterior# generar el siguiente archivo de configuraci$n,
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
12
[Accesos]
servidor = 32<.=>?.@:.A4
usuario = pepegrillo
puerto = 3443
Male aclarar que una forma de crear el mismo archivo de forma personalizada# podr"a haber sido la utilizaci$n
de ra'(input para asignar los valores de cada variable,
cparser.add(section)#Accesos#.
cparser.set)#Accesos#0 #servidor#0 raw#inp!t('Servi"or: ').
cparser.set)#Accesos#0 #usuario#0 raw#inp!t('0s!ario: ').
cparser.set)#Accesos#0 #puerto#0 raw#inp!t('P!erto: ').
OBTENIENDO VALORES
%upongo que a esta altura# e(istiendo un m*todo set).# la obviedad de que seguramente se dispone de un
m*todo get).# no ser necesaria mencionarla. 7ues como siempre sucede en 7ython# la l$gica# el sentido
com+n# la intuici$n y por sobre todo# la prolijidad y la coherencia# van de la mano.
Antes de poder obtener un valor concreto es necesario leer el archivo con el
mtodo read
Lo +nico que se necesita &J2)% de invocar al m*todo get('secci1n'% 'varia2le') /ya sea de
2a'ConfigParser como de !afeConfigParser0 es leer! el archivo de configuraci$n. 9 para ello#
disponemos de un m*todo rea"(),
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ConfigParser import !afeConfigParser
from os import path
cparser = SafeConfigParser()
if path.exists)#myapp.conf#. is ;alse/
print #$a aplicaci%n a&n no se ha configurado correctamente#
continuar = ra'(input)#*"esea configurarla ahora+ ),-n. #.
if continuar.lo'er). == #y#/
cparser.add(section)#Accesos#.
cparser.set)#Accesos#0 #servidor#0 #32<.=>?.@:.A4#.
cparser.set)#Accesos#0 #usuario#0 #pepegrillo#.
cparser.set)#Accesos#0 #puerto#0 #3443#.
'ith open)#myapp.conf#0 #'b#. as archivo/
cparser.'rite)archivo.
else/
exit).
else/
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
13
cparser.rea"('myapp.conf')
print cparser.get('$ccesos'% '!s!ario')
Lo anterior /siguiendo los mismos ejemplos que al crear el archivo0# arrojar pepegrillo como salida en caso
que el archivo de configuraci$n ya e(ista.
@tras opciones para obtener valores mediante ConfigParser son los m*todos sections). y options).
que retornan la lista de secciones y variables /opciones0 del archivo de configuraci$n le"do# respectivamente,
from ConfigParser import !afeConfigParser
cparser = !afeConfigParser).
cparser.read)#myapp.conf#.
for seccion in cparser.sections()/
print seccion
print cparser.options(seccion)
Lo anterior# retornar"a,
Accesos
[#servidor#0 #usuario#0 #puerto#]
%in embargo# es muy probable que se desee no solo obtener las variables )options. sino tambi*n sus
valores. 5na forma de lograrlo# es mediante el m*todo items).# similar a options). pero que agrega los
valores al elemento de retorno# en forma de tuplas,
from ConfigParser import !afeConfigParser
cparser = !afeConfigParser).
cparser.read)#myapp.conf#.
for seccion in cparser.sections)./
print seccion
print cparser.items)seccion.
# . slid de lo nterior ser/:
# Accesos
# 012servidor23 2+45.67.898.:,2;3 12usurio23 2pepegrillo2;3 12puerto23 2+,,+2;<
6inalmente# es posible que se necesite verificar las variables obteniendo errores si no se cumple con el tipo de
datos esperado. 7ara ello# D m*todos se encuentran disponibles, getint).# getfloat). y getboolean).#
aunque es importante entender que el uso de estos tres m(todos8 solo se <usti2i)ar4 si se desea
otener error en )aso de 'ue el elemento soli)itado no se )orresponda al tipo de datos pedido,
cparser.getboolean)#Accesos#0 #puerto#. # =lue)rror: >ot boolen: +,,+
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
14
%i bien los m*todos generan error cuando el tipo de datos no es el esperado# no fallan cuando la conversi$n
previa es posible,
cparser.getfloat)#Accesos#0 #puerto#. # +,,+.,
AGREGAR SECCIONES Y/U OPCIONES
=uando se desea agregar una o ms secciones a un archivo de configuraci$n# se realiza e(actamente de la
misma forma en la que se ha efectuado el agregado al momento de la creaci$n del archivo. )sta regla aplica
tambi*n# como es de esperarse# cuando lo que se desea agregar son opciones a las secciones que se estn
incorporando.
%in embargo# si se quieren agregar opciones a secciones e(istentes# la invocaci$n al m*todo read). se har
necesaria,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ConfigParser import !afeConfigParser
from os import path
cparser = !afeConfigParser).
if path.exists)#myapp.conf#. is ;alse/
print #$a aplicaci%n a&n no se ha configurado correctamente#
continuar = ra'(input)#*"esea configurarla ahora+ ),-n. #.
if continuar.lo'er). == #y#/
# Se agrega nueva seccin y nuevas opciones
cparser.add(section)#Accesos#.
cparser.set)#Accesos#0 #servidor#0 #32<.=>?.@:.A4#.
cparser.set)#Accesos#0 #usuario#0 #pepegrillo#.
cparser.set)#Accesos#0 #puerto#0 #3443#.
else/
exit).
else/
# Para agregar nuevas opciones a secciones existentes
# primero se lee el arcivo y luego se reali!a la agregacin
cparser.rea"('myapp.conf')
cparser.set)#Accesos#0 #rsa(file(path#0 ra'(input)#2uta llave 2!A/ #..
'ith open)#myapp.conf#0 #'b#. as archivo/
cparser.'rite)archivo.
ANALIZAR O EVALUAR EL CONTENIDO DE UN ARCHIVO DE
CONFIGURACIN
&lgo tan simple como verificar si una determinada secci$n u opci$n se encuentra presente en un archivo de
configuraci$n antes de ejecutar una instrucci$n concreta# es posible gracias a los m*todos has#section y
has#option,
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
15
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ConfigParser import !afeConfigParser
from os import path

cparser = !afeConfigParser).
if path.exists)#myapp.conf#. is ;alse/
print #$a aplicaci%n a&n no se ha configurado correctamente#
continuar = ra'(input)#*"esea configurarla ahora+ ),-n. #.
if continuar.lo'er). == #y#/
cparser.add(section)#Accesos#.
cparser.set)#Accesos#0 #servidor#0 #32<.=>?.@:.A4#.
cparser.set)#Accesos#0 #usuario#0 #pepegrillo#.
cparser.set)#Accesos#0 #puerto#0 #3443#.
else/
exit).
else/
cparser.read)#myapp.conf#.
# "ntes de agregar una nueva opcin# verifica si la seccin existe$
if cparser.has#section('$ccesos'):
# % &ue la opcin a agregar no se encuentre ya presente
if not cparser.has#option('$ccesos'% 'rsa#file#path'):
cparser.set)#Accesos#0 #rsa(file(path#0 ra'(input)#2uta llave 2!A/ #..
'ith open)#myapp.conf#0 #'b#. as archivo/
cparser.'rite)archivo.
MODIFICAR VALORES DE OPCIONES EXISTENTES
)n este caso# con tan solo mezclar un poco de read). con algo de set).! ser suficiente. %iempre que se
desee modificar un valor puntual# debe primero leerse el archivo y recurrir al m*todo set). para modificar el
valor de una variable. )sto puede hacernos llegar a la conclusi$n que,
al invocar al mtodo set si la opcin pasada por parmetro existe, modifica
su valor; en caso contrario, la crea.
)n el siguiente ejemplo# si la secci$n &ccesos! e(iste# se modificar el valor de la variable rsa(file(path
en caso que e(ista o se crear la opci$n# en caso contrario,
#...
if cparser.has(section)#Accesos#./
cparser.set('$ccesos'% 'rsa#file#path'% raw#inp!t('R!ta llave RS$: '))
#...
ELIMINAR SECCIONES U OPCIONES
6inalmente# lo que nos faltaba para poder manipular archivos de configuraci$n de forma completa# era una
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
16
forma de eliminar secciones yLu opciones.
7ara lograrlo# primero necesitaremos leer el archivo de configuraci$n# luego# invocar a los m*todos
remove#section)#secci%n#. o remove#option)#secci%n#0 #variable#. para eliminar una secci$n
u opci$n respectivamente y por +ltimo# guardar el archivo,
# )li*in tod l secci!n Accesos
cparser.remove(section)#Accesos#.
# )li*in solo l opci!n rs-file-pth de l secci!n Accesos
cparser.remove(option)#Accesos#0 #rsa(file(path#.
Es muy importante saber que si la seccin u opcin pasada a remove_section o
remove_option no existe, ninguno de los dos mtodos arrojar un error.
RESUMEN DE CONFIGPARSER
# ?*portci!n del *!dulo en "ython 4.x
from ConfigParser import !afeConfigParser # "r soporte de interpolci!n
from ConfigParser import 2a'ConfigParser # Sin soporte de interpolci!n
# ?*portci!n del *!dulo en "ython 5.x
from configparser import !afeConfigParser # "r soporte de interpolci!n
from configparser import 2a'ConfigParser # Sin soporte de interpolci!n
# ?nicili&r el prser
cparser = !afeConfigParser). # #on soporte de interpolci!n
cparser = 2a'ConfigParser). # Sin soporte de interpolci!n
# .eer el rchivo )@#)"AB si se lo v crer
cparser.read)#-ruta-al-archivo#.
# Agregr secciones
cparser.add(section)#!ecci%n#.
# Agregr o *odificr opciones
cparser.set)#!ecci%n#0 #Bariable#0 #Balor#.
# Bbtener vlores:
# Bbtener un opci!n:
cparser.get)#!ecci%n#0 #Bariable#.
# Bbtener un opci!n especificndo el tipo de dtos pr ser convertido o
# fllndo en cso de error
cparser.getint)#!eccion#0 #variable#.
cparser.getfloat)#!eccion#0 #variable#.
cparser.getboolean)#!eccion#0 #variable#.
# Bbtener un list con tods ls secciones
cparser.sections).
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
17
# Bbtener un list con tods ls opciones de un secci!n
cparser.options)#!ecci%n#.
# Bbtener un list con ls opciones y vlores de un secci!n3 dentro de tupls
cparser.items)#!ecci%n#.
# Sber si un secci!n existe
cparser.has(section)#!ecci%n#.
# Sber si un opci!n existe
cparser.has(option)#!ecci%n#0 #variable#.
# Curdr un rchivo de configurci!n
'ith open)#-ruta-al-archivo#0 #'b#. as archivo/
cparser.'rite)archivo.
# )li*inr un secci!n
cparser.remove(section)#!ecci%n#.
# )li*inr un opci!n
cparser.remove(option)#!ecci%n#0 #variable#.
FORMATO DE LOS ARCHIVOS DE CONFIGURACIN
; co*entrios inicidos por punto y co*
# t*biDn son ignords lEnes inicids con el signo nu*erl
[Combre de la !ecci%n]
opci%n = valor tipo string
entero = 3444
flotante = 3A.>
booleano = Drue
; opciones interpolds
; reFuieren Sfe#onfig"rser
variable = !e hicieron E)horas.i horas extras
horas = 32
; el vlor de vrible ser/: Se hicieron +4 hors extrs
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
18
INGENIERA DE SOFTWARE:
AGREGADO DE ARCHIVOS
CRON Y EJECUCIN
PERIDICA DE PROCESOS EN
LOS PAQUETES .DEB
ESTA SERIE DE PAPERS QUE
COMENZ EN LA EDICIN
NRO. 11 DE LA REVISTA
HACKERS D & EVELOPERS
MAGAZINE EXPLICANDO
CMO CREAR PAQUETES
DEBIAN Y CONTINU EN LA
EDICIN ANTERIOR DE THE
ORIGINAL HACKER HABLANDO
ACERCA DE CMO
DESARROLLAR ARCHIVOS PRE
Y POST INSTALACIN
PROPIOS, COMIENZA A
LLEGAR A SU FIN EN ESTA
ENTREGA, EN LA QUE ME
CONCENTRAR EN LA
NECESIDAD DE NUESTRAS
APLICACIONES DE INCLUIR
LA EJECUCIN PERIDICA
DE PROCESOS QUE PARA
CORRER, REQUIERAN
ALMACENARSE EN LOS
DIRECTORIOS /ETC/CRON.9
uando desarrollamos aplicaciones# frecuentemente
incluimos instrucciones# sugerencias y hasta incluso
directivas de mantenimiento en archivos N)&34) o en la
documentaci$n de nuestro %oftware. %in embargo# incluso aunque
el p+blico objetivo de nuestros desarrollos sean profesionales de los
sectores -2# toda instrucci$n# directiva o sugerencia que requiera
ser ejecutada post'instalaci$n# suele ser ignorada# sobre todo# si la
misma necesita ser llevada a cabo en ms de una oportunidad.
=
"anto Deian )omo sus distros derivadas8 son )apa)es de
e<e)utar tareas espe)+2i)as de 2orma peri/di)a# que van m4s
all4 de la programaci$n de tareas mediante cronta2.
3ichas tareas son ejecutadas por el propio %istema @perativo# cada
hora# diaria# semanal o mensualmente y las mimas# se encuentran
especificadas en guiones de shell e<e)utales# alojados en los
directorios -etc-cron.hourly# -etc-cron.daily#
-etc-cron.'eeFly y -etc-cron.monthly.
3e all" que# por ejemplo# tareas de limpieza# depuraci$n y
mantenimiento de la base de datos de una aplicaci$n (como la que
vimos en el artculo de emulacin de tokens temporales
1
en la
edicin pasada)# tranquilamente podr"an efectuarse mediante un
cron.daily ' agregado al paquete .deb '# liberando as" al usuario
de tener que programar dicha tarea manualmente.
: &rt"culo 9Emula)i/n de to=ens de seguridad temporales para el
registro de usuarios: /2he @riginal .acHer JO :0,
http,LLlibrary.originalhacHer.orgLbibliotecaLarticuloLverL::8
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
19
LOS ARCHIVOS CRON.* Y SU FORMATO
Los archivos cron.9# como coment* unos prrafos ms arriba# son guiones de shell ejecutables. )stos
archivos se alojan en las diversas carpetas -etc-cron.9 bajo el nombre de la aplicaci$n.
)s as"# que por ejemplo# en la carpeta -etc-cron.daily encontraremos archivos cuyos nombres sern
apache20 dpFg0 sendmail o apt# entre otros.
=ada carpeta cron.9 est destinada a almacenar guiones que se ejecutarn bajo un mismo per"odo de
tiempo. 4uy intuitivamente# la relaci$n carpeta'per"odo es la siguiente,
-etc-cron.hourly cada hora
-etc-cron.daily diariamente
-etc-cron.'eeFly semanalmente
-etc-cron.monthly mensualmente
.aciendo un cat a cualquiera de los archivos alojados dentro de alguna de estas carpetas cron.9# podremos
comprobar que efectivamente se trata de guiones de shell,
eugeniaGcococha8gnucita/3etc3cron."aily4 cat passw"
#!/bin/sh
cd -var-bacFups HH exit 4
for ;I$ in pass'd group shado' gshado'J do
test 8f -etc-K;I$ HH continue
cmp 8s K;I$.baF -etc-K;I$ LL continue
cp 8p -etc-K;I$ K;I$.baF LL chmod ?44 K;I$.baF
done
eugeniaGcococha8gnucita/-etc-cron.dailyK
!ualquier guin de sell es v"lido para ser agregado como arcivo
cron#$
EXCEPCIONES CRON.D
La +nica e-)ep)i/n a todo lo anterior# son los archivos cuyo destino ser el directorio 3etc3cron.". Los
archivos alojados en este directorio# tendrn un formato diferente y adems# solo se deben utilizar cuando el
per"odo de ejecuci$n difiera de cualquiera de los anteriores.
5n claro e<emplo de uso )orre)to de cron."8 es el ar)hivo php7 en)argado de eliminar las sesiones
ina)tivas. E& que no te lo esperabasF %in buscarlo# de pronto encuentras la respuesta a &)/mo ha)e $>$
para eliminar las sesiones ina)tivas tras un per+odo de tiempo determinado,. 9 la respuesta
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
20
justamente# es que $>$ agrega un ar)hivo php* a 3etc3cron." indicando como per"odo de ejecuci$n
/formato crontab. el indicado en la directiva session.gc(maxlifetime del archivo php.ini y
procediendo a ejecutar la instrucci$n encargada de destruir toda sesi$n cuyo per"odo de inactividad# supere el
mencionado.
eugeniaGcococha8gnucita/3etc3cron."4 cat php*
# /etc/cron.d/php7: crontb frg*ent for php7
# Ahis purges session files older thn @3 (here @ is defined in seconds
# s the lrgest vlue of session.gc-*xlifeti*e fro* ll your php.ini
# files3 or 46 *inutes if not defined. See /usr/lib/php7/*xlifeti*e
# .ooG for nd purge old sessions every 5, *inutes
4A0<A 9 9 9 9 root [ 8x -usr-lib-php>-maxlifetime ] LL [ 8d -var-lib-php> ] LL
find -var-lib-php>- 8depth 8mindepth 3 8maxdepth 3 8type f 8cmin MK
)-usr-lib-php>-maxlifetime. 7 8execdir fuser 8s NO 2P-dev-null QJ 8delete
Los arcivos cron.d deben tener el formato requerido por crontab
para poder ser ejecutados por el sistema de forma satisfactoria
ESPECIFICACIONES DEBIAN
=omo especificaciones puntuales para los paquetes 3ebian /.deb0# se deben tener en cuenta sus normas. Los
archivos cuyo destino sean las carpetas -etc-cron.9 seguirn estas pautas,
)l 2ormato del ar)hivo debe ser un gui$n de shell para todos los casos e(cepto para cron.d en el
que debe tener el formato sugerido por crontab1
Los archivos deben tener permisos de e<e)u)i/n /se debe hacer un chmod Mx a cada archivo
.cron.901
Los archivos deen guardarse en la )arpeta DEB*AN del paquete1
)l nomre de ar)hivo debe tener el formato, no*bre-del-pFuete.cron.9 d$nde,
nom2re#"el#pa5!ete ser el de la aplicaci$n. 7or ejemplo# apache2
6 ser hourly# daily# 'eeFly0 monthly o d seg+n corresponda.
7or ejemplo# un archivo 789:$;3apache'.cron."aily se alojar en -etc-cron.daily-apache2 y ser
ejecutado diariamente.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
21
EUROPIO ENGINE LAB:
CMO SE HICIERON LOS
ABM DE LA WEB THE
ORIGINAL HACKER
LIBRARY?
EN LA EDICIN ANTERIOR,
VIMOS QUE CREAR
FORMULARIOS Y LISTADOS
CON EUROPIO ENGINE, ERA
SUMAMENTE RPIDO Y
SENCILLO SI SE
UTILIZABAN LOS
COMPLEMENTOS DISPONIBLES
PARA ESTOS FINES. EN
ESTA ENTREGA, VAMOS A
COMPLETAR EL LABORATORIO
VIENDO COMO CREAR UN
ABM, PUEDE CONVERTIRSE
EN UNA TAREA QUE SE
PUEDA EJECUTAR CON LOS
OJOS CERRADOS.
uando lanc* la Keb "he ?riginal >a)=er @irar.
2
# uno de
los comentarios que ms recib"# fue referido a la gran
cantidad de trabajo que el desarrollo de la plataforma me
deb"a haber consumido. %in embargo# solo tuve 'ue invertir
unos )uantos minutos. 7ero el poco trabajo# no fue producto de
las magias! de una herramienta# sino de algo tan sencillo como
tener un core /n+cleo0 bien resuelto.
=
Mientras que el ncleo de una
aplicacin sea lo suficientemente
genrico para adaptarse a
cualquier requerimiento % lo
necesariamente flexible para que
lo genrico no se transforme en
m"gico, toda la ciencia de un
ABM es desmitificada por la
propia arquitectura de la
aplicacin % el dise&o del 'istema#
7ara e(plicar como crear un sencillo &B4# tomar* como ejemplo de
objeto a 2evista# por ser un objeto muy completo, se compone de
una colecci$n de objetos Articulo que a la vez# se componen de
un objeto Autor. 7asemos a e(plicarlo.
C http,LLlibrary.originalhacHer.org
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
22
DE LAS HISTORIAS DE USUARIO A LOS OBJETOS, SUS
RELACIONES Y DATOS ANEXOS...
Como administradora puedo agregar una nueva revista
Como administradora puedo agregar artculos a una revista
3e los criterios de aceptaci$n de las .istorias de 5suario# surgieron todos los objetos /aparecen subrayados y
en letra cursiva0,
Como administradora puedo agregar art+)ulos a una revista
P.
5n mismo artculo no puede agregarse a ms de una revista
=ada art"culo puede contener un solo autor
P.
)l anlisis de la rela)i/n entre los o<etos# fue sumamente simple,
La revista tiene una colecci$n de art"culos
)l art"culo tiene un autor
=on una relaci$n de objetos pura# ya estaba en condiciones de armar mi diagrama de clases y de paso# pensar
en qu* datos /ms all de las propiedades de cada objeto0# podr"a necesitar. 9 as"# surgi$ el siguiente h"brido
objetos'datos,
Diagrama !A@ realizado con Dia https,LLprojects.gnome.orgLdiaL /%oftware Libre0
StandardObject y ComposerObject son dos objetos provistos por Europio Engine
!tandardRb1ect# como su nombre lo indica# es un objeto estndar del cual heredarn la mayor"a de los
objetos a no ser que tengan caracter"sticas especiales como es el caso de los objetos de pertenencia /o
compositores e(clusivos0# que deben heredar de ComposerRb1ect.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
23
&D/nde otener ma.or in2orma)i/n sore Stan"ar"<2=ect . Composer<2=ect,
7ara mayor informaci$n de Stan"ar"<2=ect puedes leer la documentaci$n oficial en
www.europio.orgLdocsLstandardobject.
Lo relativo a Composer<2=ect# puedes encontrarlo en www.europio.orgLdocsLcomposerobject y
www.europio.orgLdocsLmanyCone.
%i necesitas obtener in2orma)i/n te/ri)o-)on)eptual sobre los objetos estndar y compositor# en el
libro "eor+a sint4)ti)o-gramati)al de o<etos# doy una e(plicaci$n detallada con ejemplos tanto en
7.7 como en 7ython. 7ara obtener el libro# puedes ingresar en
http,LLwww.buboH.esLlibrosLC:QCRRL2eoria'sintacticogramatical'de'objetos.
CREACIN DE ARCHIVOS PARA LOS MODELOS, LAS VISTAS Y LOS
CONTROLADORES
& fin de evitar los t"picos errores humanos# cre* estos archivos con la =L- (Command Line Interace) de )uropio
)ngine. 7ara ello# navegu* hasta la carpeta core-cli y cre* primero# las carpetas para el m$dulo al cul
llam* biblioteca,
eugeniaGcococha8gnucita/S-'ebpro1ects-library-core-cliK .3e!ropio >c 2i2lioteca'
M%dulo biblioteca creado con Txito
eugeniaGcococha8gnucita/S-'ebpro1ects-library-core-cliK
9 luego s"# ejecut* el comando para crear cada uno de los archivos# pasando como argumento el nombre de
cada =lase principal del modelo /adems del nombre del m$dulo0,
eugeniaGcococha8gnucita/S-'ebpro1ects-library-core-cliK .3e!ropio >f 2i2lioteca $!tor
$isto7
eugeniaGcococha8gnucita/S-'ebpro1ects-library-core-cliK .3e!ropio >f 2i2lioteca Revista
$isto7
eugeniaGcococha8gnucita/S-'ebpro1ects-library-core-cliK .3e!ropio >f 2i2lioteca $rt?c!lo
$isto7
LOS MODELOS
%in dudas# un paso sencillo ya que previamente hab"a armado el diagrama de clases. %olo era necesario
agregar las propiedades y los m*todos de agregaci$n en los casos que correspondiese,
# Archivo: pp*odules/bibliotec/*odels/utor.php
class Autor extends !tandardRb1ect N
public function ((construct). N
Kthis8Pautor(id = 4J
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
24
Kthis8Pnombre = ##J
O
O
# Archivo: pp*odules/bibliotec/*odels/rticulo.php
import)#appmodules.biblioteca.models.autor#.J
class Articulo extends ComposerRb1ect N
public function ((construct)Autor Kautor=CU$$. N
Kthis8Particulo(id = 4J
Kthis8Ptitulo = ##J
Kthis8Pautor = KautorJ
Kthis8Pseccion = ##J
Kthis8Prevista = 4J
O
O
# Archivo: pp*odules/bibliotec/*odels/revist.php
import)#appmodules.biblioteca.models.articulo#.J
class 2evista extends !tandardRb1ect N
public function ((construct). N
Kthis8Prevista(id = 4J
Kthis8Pfecha = ##J 6 date
Kthis8Pnumero = 4J
Kthis8Particulo(collection = array).J
O

public function add(articulo)Articulo Karticulo. N
Kthis8Particulo(collection[] = KarticuloJ
O
O
5na vez completos estos archivos# para concluir este paso solo restaba,
4apear los modelos creados1
?enerar las tablas en la base de datos1
)n el caso particular de estos objetos# no ser"a necesario recurrir a )uropio =L- para crear tablas# ya que
ning+n conector l$gico intervendr"a en la relaci$n. &s" que el resultado del mapeo manual fue verdaderamente
simple,
-- Archivo: bibliotec.sFl
U! database(nameJ
-- tbl utor pr persistenci de ob$etos Autor
C2AD DA5$ autor )
autor(id ICD)33. CRD CU$$ AUDR(ICC2MCD P2IMA2, V,
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
25
0 nombre BA2CWA2):4.
. CXIC=Inno"5J
-- tbl revist pr persistenci de ob$etos 'evist
C2AD DA5$ revista )
revista(id ICD)33. CRD CU$$ AUDR(ICC2MCD P2IMA2, V,
0 fecha "AD
0 numero ICD)<.
. CXIC=Inno"5J
-- tbl rticulo pr persistenci de ob$etos Articulo
C2AD DA5$ articulo )
articulo(id ICD)33. CRD CU$$ AUDR(ICC2MCD P2IMA2, V,
0 titulo BA2CWA2)344.
0 seccion BA2CWA2)>4.
0 revista ICD)33. CRD CU$$
0 ;R2IXC V, )revista.
2;2CC! revista )revista(id.
RC "$D CA!CA"
0 IC"Y )revista.
0 autor ICD)33.
0 ;R2IXC V, )autor.
2;2CC! autor )autor(id.
RC "$D !D CU$$
0 IC"Y )autor.
. CXIC=Inno"5J
6inalmente# import* el archivo para crear las tablas,
eugeniaGcococha8gnucita/S-'ebpro1ects-libraryK mys5l >! usuario >p @ 2i2lioteca.s5l
COMPLETANDO RECURSOS: AGREGAR
&l fin le lleg$ el momento a las vistas y a los controladores. Lo primero que hice# fue crear los recursos
agregar de cada uno de los modelos# para lo cual utilic* el plug'in Zeb;orm en cada una de las vistas,
# "rcivo$ appmodules'(i(lioteca'vie)s'autor*pp
# 'ee*pl&o del *Dtodo gregr1; de l vist de Autor=ie(
public function agregar). N
Kform = ne' Zeb;orm)#-biblioteca-autor-guardar#.J
Kform8Padd(text)#nombre#.J
Kform8Padd(submit).J
print Demplate)#Agregar Autor#.8Psho')Kform8Psho')..J
O
# "rcivo$ appmodules'(i(lioteca'vie)s'revista*pp
# 'ee*pl&o del *Dtodo gregr1; de l vist de 'evist=ie(
public function agregar). N
Kform = ne' Zeb;orm)#-biblioteca-revista-guardar#.J
Kform8Padd(text)#fecha#0 #;echa de publicaci%n#.J
Kform8Padd(text)#numero#.J
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
26
Kform8Padd(submit).J
print Demplate)#Agregar 2evista#.8Psho')Kform8Psho')..J
O
7ara el caso de ArticuloBie'# modifiqu* adems el recurso agregar del controlador# a fin de que *ste# le
entregara a la vista las colecciones de Autor y 2evista para que pudiesen mostrarse en dos listas
desplegables,
# "rcivo$ appmodules'(i(lioteca'controllers'articulo*pp
# 'ee*pl&o del *Dtodo gregr1; de l vist de Articulo#ontroller
public function agregar). N
Kautor(collector = Collector<2=ect::get('$!tor')A
Kautores = Kautor(collector8PcollectionJ
Krevista(collector = Collector<2=ect::get('Revista')A
Krevistas = Krevista(collector8PcollectionJ
4this>Bview>Bagregar(4a!tores% 4revistas)A
C
# "rcivo$ appmodules'(i(lioteca'vie)s'articulo*pp
# 'ee*pl&o del *Dtodo gregr1; de l vist de Articulo=ie(
public function agregar)Kautores0 Krevistas. N
4this>Bprepare#collection(4a!tores% 'nom2re')A
4this>Bprepare#collection(4revistas% 'n!mero')A
Kform = ne' Zeb;orm)#-biblioteca-articulo-guardar#.J
Kform8Padd(text)#titulo#.J
Kform8Padd(text)#seccion#.J
Kform8Padd(select)#autor#0 Kautores.J
Kform8Padd(select)#revista#0 Krevistas.J
Kform8Padd(submit).J
print Demplate)#Agregar Art[culo#.8Psho')Kform8Psho')..J
O
private f!nction prepare#collection(D4coleccion% 4text) E
Kidproperty = strtolo'er)get(class)Kcoleccion[4].. . \(id\J
foreach)Kcoleccion as LKob1. N
Kob18Pvalue = Kob18PKidpropertyJ
Kob18Ptext = Kob18PKtextJ
O
O
)l m*todo privado prepare(collection). en realidad solo lo cre* para no tener que estar escribiendo
c$digo redundante y as"# evitar ensuciar el m*todo agregar.
)ste m*todo# como se puede ver# modi2i)a por re2eren)ia la colecci$n de objetos que se le pasa por
parmetro# agregando dos propiedades /text y value0 que son las que Zeb;orm//add(select utilizar
como text y value de los option respectivamente. Male aclarar que lo correcto si se quisiera ser estricto#
hubiese sido convertir los objetos a arra!s mediante settype). y agregar text y value como claves en vez
de hacerlo como propiedades# ya que por un lado# en realidad son solo datos y por el otro#
Zeb;orm//add(select). est preparado tanto para renderi"ar objetos como arra!s asociativos.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
27
)l segundo parmetro que recibe este m*todo# es el nombre de la propiedad que se utilizar para el valor del
te(to de cada una de las opciones de la lista desplegable.
EL RECURSO GUARDAR
Le toca el turno a los recursos guardar de cada uno de los modelos. Basndome en los campos de formulario
que gener* en los m*todos anteriores# simplemente modifiqu* las propiedades de cada objeto de forma
directa# con lo recibido desde los formularios.
Por favor, notar que ningn input ha sido filtrado y/o verificado en el
cdigo fuente de los controladores, ya que implement un plug-in en fase
experimental, que filtra el array $_POST de forma automtica. Para mayor
informacin, leer el artculo sobre Seguridad Informtica de esta edicin.
%olo se completaron los recursos guardar). en los controladores de Articulo0 Autor y 2evista0 sin ser
necesario modificar ning+n otro archivo. Los recursos guardar0 finalmente# quedaron como los que siguen,
# "rcivo$ appmodules'(i(lioteca'controllers'autor*pp
public function guardar). N
Kid = )isset)K(PR!D[#id#].. + K(PR!D[#id#] / 4J # Si es ,3 greg un nuevo ob$eto
# sino edit el ob$eto con dich id
Kthis8Pmodel8Pautor(id = KidJ
Kthis8Pmodel8Pnombre = K(PR!D[#nombre#]J
Kthis8Pmodel8Psave).J
WDDPWelper//go)\-biblioteca-autor-listar\.J # Helper de )uropio pr redirecciones
O
# "rcivo$ appmodules'(i(lioteca'controllers'revista*pp
public function guardar). N
Kid = )isset)K(PR!D[#id#].. + K(PR!D[#id#] / 4J
Kthis8Pmodel8Prevista(id = KidJ
Kthis8Pmodel8Pfecha = K(PR!D[#fecha#]J
Kthis8Pmodel8Pnumero = )int.K(PR!D[#numero#]J
Kthis8Pmodel8Psave).J
WDDPWelper//go)\-biblioteca-revista-listar\.J
O
# "rcivo$ appmodules'(i(lioteca'controllers'articulo*pp
public function guardar). N
/*
"ttern es un clse provist por )uropio )ngine cuy finlidd es l de proveer
*Dtodos est/ticos Fue i*ple*enten diversos ptrones de diseIo3 entre ellos3 fctory3
Fuien crer/ un ob$eto del tipo especificdo co*o pri*er pr/*etro y cuy ?J coincid
con el vlor envido co*o segundo rgu*ento. "r *yor infor*ci!n3 se puede cceder
l docu*entci!n oficil ingresndo en http://europio.org/docs/pttern
*/
Kid = )isset)K(PR!D[#id#].. + K(PR!D[#id#] / 4J
Kthis8Pmodel8Particulo(id = KidJ
Kthis8Pmodel8Ptitulo = K(PR!D[#titulo#]J
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
28
Kthis8Pmodel8Pseccion = K(PR!D[#seccion#]J
Kthis8Pmodel8Pautor = Pattern//factory)#Autor#0 K(PR!D[#autor#].J
Kthis8Pmodel8Prevista = )int.K(PR!D[#revista#]J
Kthis8Pmodel8Psave).J
WDDPWelper//go)\-biblioteca-articulo-listar\.J
O
EL MTODO LISTAR
5no de los recursos ms simples de todos es listar# el cual es solicitado por la redirecci$n de los m*todos
guardar).. )l recurso listar /en el controlador0# ya fue creado por )uropio =L- y no hizo falta modificar
absolutamente nada. %olo fue necesario adaptar los m*todos en las vistas# para lo cual# los sustitu"
vali*ndome del plug'in CollectorBie'er /del que habl* en la edici$n anterior0 y el resultado fue el
siguiente,
# Archivo: appmodules'(i(lioteca'vie)s'autor*pp
public function listar)Kcoleccion=array).. N
# Solo si es d*inistrdor3 *uestr los botones editr y eli*inr
Kboton = )K(!!!IRC[#level#] == 3. + Drue / ;alseJ
Ktabla = CollectorBie'er)Kcoleccion0 #biblioteca#0 #autor#0 Drue0
Kboton0 Kboton.8Pget(table).J
print Demplate)#Autores#.8Psho')Ktabla.J
O
# Archivo: appmodules'(i(lioteca'vie)s'revista*pp
public function listar)Kcoleccion=array).. N
foreach)Kcoleccion as LKob1. N
unset)Kob18Particulo(collection.J # )li*ino lo Fue no deseo *ostrr
Krevista = \Dhe Rriginal WacFer\J
unset)Kob18Pnumero.J # )li*ino lo Fue no deseo *ostrr
O
Kboton = )K(!!!IRC[#level#] == 3. + Drue / ;alseJ
Ktabla = CollectorBie'er)Kcoleccion0 #biblioteca#0 #revista#0 Drue0
Kboton0 Kboton.8Pget(table).J
print Demplate)\Colecci%n de 2evistas\.8Psho')Ktabla.J
O
# Archivo: appmodules'(i(lioteca'vie)s'articulo*pp
public function listar)Kcoleccion=array).. N
Kboton = )K(!!!IRC[#level#] == 3. + Drue / ;alseJ
Ktabla = CollectorBie'er)Kcoleccion0 #biblioteca#0 #articulo#0 Drue0
Kboton0 Kboton.8Pget(table).J
print Demplate)Ktitulo.8Psho')Ktabla.J
O
RECURSOS FINALES: EDITAR Y ELIMINAR
Llegamos al final del &B4. )n el caso particular del recurso eliminar no tendremos que hacer nada# ya que
se encuentra creado en los controladores de cada modelo /de ello se encarg$ la =L- de )uropio )ngine al
momento de crear los archivos0. Guien nos dar un poco ms de trabajo es el recurso editar). el cul nos
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
29
demandar# en algunos casos# hacer pequeas modificaciones en los controladores y# sin e(cepci$n alguna#
sustituir todos los m*todos hom$nimos en las vistas. & continuaci$n# colocar* los c$digos organizados por
pares de controladorLvista para cada modelo.
# Archivo: appmodules'(i(lioteca'vie)s'autor*pp
# Autor no reFuiere c*bios en el controldor
public function editar)Kob1=array).. N # )l ob$eto nos lo envE el controldor
Kform = ne' Zeb;orm)#-biblioteca-autor-guardar#.J
Kform8Padd(hidden)#id#0 Kob18Pautor(id.J # >ecesit*os l ?J en el for*ulrio
Kform8Padd(text)#nombre#0 null0 Kob18Pnombre.J
Kform8Padd(submit).J
print Demplate)#ditar Autor#.8Psho')Kform8Psho')..J
O
# Archivo: appmodules'(i(lioteca'vie)s'revista*pp
# 'evist no reFuiere c*bios en el controldor
public function editar)Kob1=array).. N
Kform = ne' Zeb;orm)#-biblioteca-revista-guardar#.J
Kform8Padd(hidden)#id#0 Kob18Prevista(id.J
Kform8Padd(text)#fecha#0 #;echa de publicaci%n#0 Kob18Pfecha.J
Kform8Padd(text)#numero#0 #C&mero de edici%n#0 Kob18Pnumero.J
Kform8Padd(submit).J
print Demplate)#ditar 2evista#.8Psho')Kform8Psho')..J
O
# Archivo: appmodules'(i(lioteca'controllers'articulo*pp
public function editar)Kid=4. N
Kthis8Pmodel8Particulo(id = KidJ
Kthis8Pmodel8Pget).J
# Arer colecci!n de utores
Kcoleccion = CollectorRb1ect//get)#Autor#.J
Kautores = Kcoleccion8PcollectionJ
# Arer colecci!n de revists
Kcoleccion = CollectorRb1ect//get)#2evista#.J
Krevistas = Kcoleccion8PcollectionJ
Kthis8Pvie'8Peditar)Kthis8Pmodel0 Kautores0 Krevistas.J
O
&ntes de pasar a la vista de art"culo es necesario mencionar un pequeo hack que se me ocurri$ implementar
para que al mostrar el select de autores y revistas# aparezca seleccionado por defecto el autor y revista
asignado al art"culo que se est* editando.
&nteriormente# se cre$ un m*todo privado llamado prepare(collection al que se le enviaba una colecci$n
de objetos ms el nombre de la propiedad de la cual se e(traer"a el valor a mostrar en las opciones /option0
de la lista de desplegable /select0. &provech* este m*todo para incorporar la verificaci$n de la -3 del objeto
contrastndola con cada una de las -3 de la colecci$n y decidir si la propiedad extras! tendr"a un valor
vac"o /para no seleccionar nada0 o S selected# si se trataba de -ds coincidentes. )l resultado de dicha
modificaci$n fue el siguiente /remarco los cambios en negritas a fin de que sea ms fcil implementarlos0,
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
30
# "rcivo$ appmodules'(i(lioteca'vie)s'articulo*pp
# Kodificci!n del *Dtodo privdo prepre-collection
private function prepare(collection)LKcoleccion0 Ktext% 4i"=/. N
Kidproperty = strtolo'er)get(class)Kcoleccion[4].. . \(id\J
foreach)Kcoleccion as LKob1. N
Kob18Pvalue = Kob18PKidpropertyJ
Kob18Ptext = Kob18PKtextJ
4o2=>Bextras = (4o2=>B4i"property == 4i") F ' selecte"' : ''A
O
O
7or favor# notar que al tercer argumento /Kid0 le agregu* un valor por omisi$n /cero0 a fin de que no sea necesario realizar cambios a las
llamadas previas a esta modificaci$n# dado que un valor de I" solo es requerido para los m*todos de edici$n pero no# para los recursos agregar.
6inalmente# el m*todo editar de la vista ArticuloBie'0 qued$ as",
# Archivo: appmodules'(i(lioteca'vie)s'articulo*pp
public function editar)Kob10 Kautores0 Krevistas. N
Kthis8Pprepare(collection)Kautores0 #nombre#0 Kob18Pautor8Pautor(id.J
Kthis8Pprepare(collection)Krevistas0 #numero#0 Kob18Prevista.J
Kform = ne' Zeb;orm)#-biblioteca-articulo-guardar#.J
Kform8Padd(hidden)#id#0 Kob18Particulo(id.J
Kform8Padd(text)#titulo#0 null0 Kob18Ptitulo.J
Kform8Padd(text)#seccion#0 null0 Kob18Pseccion.J
Kform8Padd(select)#autor#0 Kautores.J
Kform8Padd(select)#revista#0 Krevistas.J
Kform8Padd(submit).J
print Demplate)#ditar Articulo#.8Psho')Kform8Psho')..J
O
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
31
SEGURIDAD INFORMTICA:
CAPAS DE SEGURIDAD
INTELIGENTES EN PHP
SANEAMIENTO DEL ARRAY
SUPERGLOBAL $_POST
LA SIGUIENTE
PUBLICACIN, CORRESPONDE
A LOS RESULTADOS
OBTENIDOS HASTA EL
MOMENTO, SOBRE UNA
INVESTIGACIN QUE ME
ENCUENTRO REALIZANDO
ACTUALMENTE, CUYO
OBJETIVO ES HALLAR UNA
FORMA INEQUVOCA DE
SANEAR, FILTRAR Y
LIMPIAR DATOS ENVIADOS
POR HTTP POST, MEDIANTE
UNA CAPA DE SEGURIDAD DE
ACTIVACIN AUTOMTICA.
n varias ediciones de la revista .acHers T 3evelopers
4agazine# he dado sugerencias alternativas para el
saneamiento de los datos recibidos desde formularios. )n
http,LLlibrary.originalhacHer.org se puede acceder a cada uno de los
art"culos sobre el tema y descargarlos en formato 736.
)
7ero lo que hoy quiero mostrarles# no es en referencia a qu* datos
deben filtrarse# qu* riesgos corremos a causa de cules
vulnerabilidades conocidas ni qu* herramientas e(isten para
prevenir estos problemas.
.oy# quiero hablarles sobre una investiga)i/n 'ue vengo
llevando a )ao en los ;ltimos meses# mediante la cual#
vali(ndome de una )ara)ter+sti)a de $>$ que personalmente
no logra convencerme . de las ra+)es m4s 4si)as de la
inteligen)ia arti2i)ial# es posible )rear )apas de seguridad en
nuestras aplicaciones# 'ue se a)tiven de 2orma autom4ti)a y
'ue sean )apa)es de re)ono)er el tipo de in2orma)i/n que el
programador espera y sobre ese anlisis# procedan a limpiar! el
arra! superglo#al K(PR!D de forma tal que al ser accedido por el
programador# ya haya atravesado toda acci$n de saneamiento.
MUTABILIDAD DEL ARRAY $_POST
)n el prrafo anterior comentaba acerca de una caracter"stica de 7.7 que a+n no lograba convencerme. %in
embargo# al final de este documento# probablemente termine reconociendo lo contrario 'o no'. %e trata de la
)apa)idad mutale del array superglobal 4#P<SG.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
32
5no podr"a esperar que se tratase de una variable de solo lectura# pero no lo es. 3e hecho# 4#P<SG no
alma)ena los datos en )rudo enviados mediante >""$ $?S"# sino que lo hace habi*ndolos tratado
previamente. !n )laro e<emplo de esto8 es lo 'ue antiguamente su)ed+a )on los datos )uando las
2amosas )omillas m4gi)as se en)ontraan a)tivadas1 3e forma automtica# los datos enviados
mediante .227 7@%2 llegaban al arra! superglo#al K(PR!D con las comillas dobles# simples# barras invertidas
y valores nulos ya escapados con su barra invertida correspondiente.
Netomando el caso de mutabilidad de este arra!# la misma nos permite# por ejemplo# agregar nuevas claves al
arra!# como se muestra a continuaci$n,
K(PR!D[#esto(no(era(un(campo(del(form#] = #foo#J
9 como era de esperarse# tambi*n nos permite modificar un valor e(istente,
K(PR!D[#campo(del(form#] = htmlentities)K(PR!D[#campo(del(form#].J
)sta +ltima caracter"stica# es la que ms nos interesa. ?racias a esta falta de inmutabilidad del arra!#
podremos hacer que est* disponible con los datos ya saneados.
AUTOMATIZACIN
7ara que el proceso de saneamiento que se lleve a cabo se active de forma automtica# *ste deber"a ser
invocado desde un archivo com+n a toda la aplicaci$n# que siempre se encuentre disponible y que tenga
relaci$n directa con esta capa. 7or ejemplo# una clase Demplate siempre podr"a estar disponible y sin
embargo# no tendr"a ninguna relaci$n con una capa de seguridad.
3espu*s de mucho pensar# conclu" en que deb"a ser la propia capa de seguridad quien se active a s" misma.
3e esta forma# al momento de ser importada /por ejemplo# desde un settings0# ya estar"a actuando de
forma natural.
Jo obstante# tambi*n not* la necesidad de poder decidir la desactivaci$n de esta capa si fuese requerido sin
tener que estar comentando o eliminando la l"nea de importanci$n. &s" fue que lo ms coherente# me pareci$
que ser"a definir una constante #ooleana en un archivo settings y dependiendo de su valor# se activara o no
la capa.
DISPONIBILIDAD DE LOS DATOS ORIGINALES
La inteligencia artificial y la l$gica de negocio de una aplicaci$n# deben siempre estar al servicio de las
personas y jams deber"a darse el caso contrario /aunque lamentablemente# se da en ms del R;< de las
aplicaciones# pero eso# ya no es tema de debate en este art"culo0.
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
33
3espu*s de probar m+ltiples alternativas# analizarlas una a una y descubrir que ninguna me terminaba de
convencer# decid" recorrer la documentaci$n de 7.7 de punta a punta. 9a hab"a descartado el uso de la
variable KWDDP(2AZ(PR!D("ADA puesto que depend"a del valor de la directiva
al'ays(populate(ra'(post(data del archivo php.ini y realmente# me resultaba poco l$gico e inviable#
tener que modificar esto para poder disponer de los datos .227 7@%2 puros. Leyendo sobre esta directiva# fue
que la soluci$n lleg$ a mis manos, php:33inp!t# una envoltura de 2lu<o de solo le)tura.
%in embargo# cabe destacar que php/--input cuenta con algunas restricciones interesantes# como por
ejemplo# su no disponibilidad cuando el tipo de codificaci$n del formulario es declarado como
multipart-form8data.
php://input NO FUNCIONA con enctype=multipart/form-data
7or favor# recordemos que el tipo de contenido multipart-form8data# es el que nos permite en un
formulario# enviar grandes cantidades de datos sobre todo binarios y con codificaci$n diferente a &%=--.
7ara mayor informaci$n sobre este tema# recomiendo dirigirse a
http,LLwww.wD.orgL2NLhtml>;:LinteractLforms.htmlUdid('multipartform'data y
http,LLwww.ietf.orgLrfcLrfcCDRR.t(t.
& pesar de todo lo anterior# esta soluci$n resulta la ms acertada posible. =uando php/--input no se
encuentre disponible# habr"a que pensar entonces# en recurrir como +ltima alternativa# a la variable
KWDDP(2AZ(PR!D("AD que podr"a tambi*n no estar disponible si la directiva
al'ays(populate(ra'(post(data del archivo php.ini fuese ;alse.
(ara ser onesta, en ()( no e*iste una forma inequvoca % e*acta de
poder recuperar los datos enviados a travs de )++( (,'+ sin previo
tratamiento#
%i se quisiera trabajar con php/--input# deber"a hacerse mediante fopen y fgets como se muestra en el
siguiente ejemplo,
Kfp = fopen)#php/--input#0 #r#.J
4"ata = fgets(4fp)A
fclose)Kfp.J
# Jonde l vrible Ldt3 podrE retornr lgo co*o:
foo=WolaMmundoE23Lbar=4.?>
# )Fuivlente hber envido por "BSA:
foo = Wola mundo7
bar = 4.?>
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
34
INTELIGENCIA ARTIFICIAL
7ara saber c$mo se deber"a filtrar cada uno de los campos y qu* filtros aplicar# podemos recurrir a las ra"ces
ms bsicas de la inteligencia artificial, los diccionarios de nombres. 3e esta forma# podemos deducir que un
campo que solicite un e'mail al usuario# podr"a tener como parte del nombre# la cadena mail!. &s"# campos
llamados email!# mailVaddress! o repeatVemail! coincidir"an con la cadena mail!. La misma l$gica# podr"a
aplicarse a otros tipos de campo,
IP ip
U2$ url0 uri0 site0 'eb
Combre de usuario uname0 username0 user0 usuario
Contrase]a pass )coincidir[a adem^s con pass'd y pass'ord.0 p'd0 clave
etc.
=laro que esta l$gica no debe ser demasiado minuciosa. )s decir# la mayor"a de los campos sern campos de
te(to /strings0 que no van a necesitar de comprobaciones de formatos especiales.
3e esta forma# creando diccionarios y aplicando a cada caso los filtros correspondientes# se podr"a abarcar un
gran n+mero de posibilidades que podr"an sanear de forma predeterminada a decenas de miles de
aplicaciones.
*mplementa)i/n de la *A
9a en muchos documentos anteriores me dediqu* a hablar de los filtros que se deben aplicar en cada caso y
en cada tipo de campo# as" que aqu" solo me concentrar* en poner en c$digo todo lo que e(pliqu*
anteriormente referido a la -&.
3ado un diccionario como el siguiente,
Kdiccionarios = array)
#e8mail# =P array)#mail#.0
#contrase]a# =P array)#pass#0 #clave#.
.J
9 suponiendo un formulario con los siguientes campos y valores,
K(PR!D = array)
#email(address# =P #fooGbar#0
#pass'd# =P #32<=>?#0
#pass'd2# =P #32<=>?#
.J
)l siguiente algoritmo podr"a utilizarse para detectar a qu* tipo de dato se corresponder"a cada uno de los
campos,
The Original Hacker www.originalhacker.org
2013 Eugenia Bahit www.eugeniabahit.com Bajo Licencia Creative Commons BY-NC-SA
35
foreach)K(PR!D as KFey=PKvalue. N
foreach)Kdiccionarios as Ktipo=PKdiccionario. N
foreach)Kdiccionario as Kentrada. N
if)strpos)KFey0 Kentrada. 7== ;alse. N
print \l campo NKFeyO es de tipo NKtipoO\ . chr)34.J
O
O
O
O
@bteniendo un resultado como el siguiente,
l campo email(address es de tipo e8mail
l campo pass'd es de tipo contrase]a
l campo pass'd2 es de tipo contrase]a
Luego# basados en el tipo de campo# solo es cuesti$n de aplicar los filtros que correspondan en cada caso.
MS INFORMACIN
7ara conocer ms sobre filtros en 7.7# recomiendo leer las siguientes pginas del manual,
;unci%n filter(input/
http/--us<.php.net-manual-es-function.filter8input.php
;iltros disponibles/
http/--us<.php.net-manual-es-filter.filters.php
;unci%n strip(tags/
http/--us<.php.net-manual-es-function.strip8tags.php
;unci%n htmlentities/
http/--us<.php.net-manual-es-function.htmlentities.php
;unci%n htmlspecialchars/
http/--php.net-manual-es-function.htmlspecialchars.php
1311309459833
1311309459833
2
1 311309 459833

También podría gustarte