Translate

sábado, 24 de septiembre de 2016

SEGURIDAD Y CODIGO ABIERTO

En Internet podemos obtener funciones e incluso aplicaciones completas ( blogs, foros, comercio electrónico, etc.) desarrolladas en los lenguajes de programación más extendidos. Este código prefabricado nos puede ahorrar mucho tiempo de desarrollo, y aunque se utiliza de forma casi exclusiva en entornos no empresariales, estas aplicaciones prefabricadas tienen un riesgo.

Un fallo en el código puede permitir el acceso a nuestro servidor. Cuando se utiliza código desarrollado por terceros y de acceso público, cualquiera puede analizar el código en profundidad y encontrar brechas de seguridad. El siguiente paso sería buscar dónde se ha instalado y el resultado es fácil de imaginar.

La seguridad es un aspecto más a tener en cuenta en el desarrollo de aplicaciones, pero en el caso del software abierto, debemos tener en cuenta que el usuario es el eslabón más débil de cualquier sistema de seguridad.

Riesgos clásicos

La seguridad se verá amenazada si no se ha previsto implementar las mejores prácticas para cerrar posibles brechas.

Desde el punto de vista de un servidor web existen riesgos evidentes como la subida de archivos, es necesario validar si se trata de una imagen o no, no es suficiente validar sólo la extensión del archivo.

Todos los datos que se transmiten a la aplicación a través de formularios pueden ser peligrosos y con el objetivo de provocar fallos. Se deben verificar los datos entrantes, independientemente de lo que haya podido hacer nuestro código JavaScript en el cliente. En el servidor hay que volver a validar los datos recibidos.

Una sentencia SQL no protegida puede ser un problema clásico en el robo de datos.

No existe servidor WEB a salvo de hackers, por tanto es un aspecto a tener muy presente en su desarrollo.

Tipo de ataques a la seguridad


  • XSS ( Cross Site Scripting) : Consiste en insertar scripts maliciosos en páginas web en las que confía el usuario, con el objetivo de robar información.
  • CSRF ( Cross-site request forgery) Consiste en enviar una petición a un servidor vulnerable a través de un usuario validado. Explota la confianza que un servidor tiene en un usuario en particular.
  • DDOS o Denegación de servicio : Su objetivo es colapsar los recursos del servidor (ancho de banda, procesador o memoria), puede producir resultados que van desde lentitud en la carga de las páginas hasta un bloqueo completo del tráfico legítimo al sitio. Es uno de los más complicados en evitar.
  • SPAM o envío masivo de mensajes: Busca enviar mensajes no solicitados de forma masiva.
  • SPOOFING: Es el intento de asumir la identidad de otro usuario o enmascarar su acceso desde una IP que no es la real.
  • PHISHING: Es una variedad de SPOOFING, obteniendo los datos personales o confidenciales de modo fraudulento.
  •  HIJACKING: Intenta tomar el control de una sesión web que corresponde a otro usuario debidamente autenticado.
  • MAN-in-the-MIDDLE, MitM o JANUS: Es un ataque de intermediario, donde se lee, inserta o modifica la información transmitida entre dos partes, sin que ninguna de las dos partes lo detecte. Se emplea en redes LAN y WLAN.

Cómo evitar ataques


Para evitar tipos de ataques es necesario utilizar una serie de contramedidas:


XSS : Comprobar los ficheros y los datos recibidos a través de formularios, ya que pueden contener código malicioso, siendo necesaria su validación. No confiar nunca en datos que obtengas de los usuarios o de cualquier fuente de datos externa.Saneando los datos evitamos que se introduzca codificación en los datos. Por ejemplo: código HTML en el nombre de un usuario.Escapando los datos recibidos evitamos que se ejecuten o evalúen como código.


CSRF : Es posible evitar este tipo de ataques mediante la SESSION del usuario, insertando un CSRF_TOKEN en el HEADER de la página solicitada, y transmitiendo el valor CSRF_TOKEN con cada petición POST o AJAX que se cotejará con la SESSION en el servidor. 

Se incrementará más la seguridad si el valor CSRF_TOKEN es recalculado con cada solicitud de página por parte del usuario.

SPOOFING / PHISHING: Además de implementar las acciones anteriores, mediante SESSION debemos recordar desde qué IP se están realizando las solicitudes, bloqueando al usuario si durante el proceso de peticiones al servidor, se modifica su IP.

Se puede incrementar más la seguridad bloqueando IP que no procedan de regiones permitidas.

Ya que la causa es un mal diseño del protocolo TCP/IP, una buena estrategia es implantar  IPv6.

Conclusiones

No existe una solución 100% efectiva, ya que los métodos de ataque evolucionan constantemente, pero es posible combinar varios sistemas que contrarresten los ataques de una forma eficaz.

Este artículo no sería de mucha utilidad si la evolución de los atacantes no se contrarrestara con otras medidas futuras, por tanto, esta información se actualizará de una forma dinámica según la evolución de las contramedidas.


jueves, 15 de septiembre de 2016

El patrón SINGLETON o cómo obtener una instancia única de un proceso en Python

Un Singleton es un patrón de un proceso que solo tiene una instancia única y compartida entre todos los procesos que lo han instanciado y que se ejecutan en un hilo.

Se entiende mejor con un ejemplo sencillo (PYTHON 2.7) :


class A:
    # _instance es un atributo que conoce el Singleton
    _instance = None
    def foo(self):
        return id(self)

def Singleton(cls):
    # cls identifica la clase que solo debe instanciarse una vez por proceso
    if not cls._instance:
        print 'primera instancia del Singleton'
        cls._instance = cls()
    return cls._instance

# subclase A
class B(A):
    pass

b = Singleton(A)
c = Singleton(B)
d = Singleton(A)

print id(b),b.foo()
print id(c),c.foo()
print id(d),d.foo()


En este caso deseamos que la clase A se instancie una sola vez y esa instancia se comparta entre todos los procesos que la instanciarán posteriormente. Al instanciar la clase A con b=Singleton(A) creamos una primera instancia que se compartirá con las siguientes inicialización de la clase :  c= Singleton(B) y d=Singleton(A).

Posteriormente comprobamos el id de cada clase, siendo el mismo identificador :

primera instancia del singleton
32730128 32730128
32730128 32730128
32730128 32730128


A continuación crearemos otro ejemplo sobreescribiendo el método __new__ de una clase, convirtiéndola en Singleton :


class A(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(A, cls).__new__(cls, *args, **kwargs)
        return cls._instance

if __name__ == '__main__':
    b = A()
    c = A()
    if (id(b) == id(c)):
        print "Igual instancia"
    else:
        print "Diferente instancia"


En este caso, comprueba que también existe _instance como una variable de clase, igual que en ejemplo anterior, que almacena la instancia de clase. _instance se inicializa con la primera instancia de clase y devolverá el mismo valor de instancia a cada inicialización de clase que realizan los posteriores procesos.

A continuación mostramos otro ejemplo Singletón con decorador :


def singleton(cls):
    obj = cls()
    # Siempre devuelve el mismo objeto
    cls.__new__ = staticmethod(lambda cls: obj)
    # Desabilita __init__
    try:
        del cls.__init__
    except AttributeError:
        pass
    return cls

@singleton
class A(object):
    pass

if A() is A():
    print "Es lo mismo!"
else:
    print "Es diferente!"


Hasta aquí he querido poner algo de luz sobre el patrón SINGLETON.