Publicar en Facebook las entradas de este sitio usando Python

Enlaces en Página de Facebook

Ya anticipamos esta entrada hace un par de semanas en Extraer enlaces de una página web. Allí hablábamos de formatear una entrada de este sitio (u otro que proporcione RSS) para publicarla en Facebook (o donde nos parezca, claro). También en Publicar en Twitter las entradas de este sitio usando Python vimos algunas ideas sobre este tema, entonces para Twitter.

En este caso utilizamos el API oficial de Facebook y un paquete no oficial que la implenenta en Python, Facebook Python SDK.

Podemos instalarlo

fernand0@aqui:~$ sudo pip install facebook-sdk

Para su correcto funcionamiento necesita BeautifulSoup y requests y tal vez algunos módulos más. Si no están instalados en nuestro sistema, recibiremos las ‘quejas’ correspondientes.

Para obtener las credenciales tenemos que registrar nuestra aplicación en Facebook My Apps. Hace falta ir al menú avanzado (es más fácil registrar aplicaciones web, la verdad) y se nos asignarán algunos identificadores (fundamentalmente el token OAUTH, que podemos mirar en https://developers.facebook.com/tools/explorer/APPID/?method=GET&path=me%3Ffields%3Did%2Cname&version=v2.2, donde APPID es el que nos hayan asignado), que en nuestro caso almacenamos en ~/.rssFacebook y leeremos desde el programa.

El programa es muy sencillo, se puede descargar en rssToPages.py V.2015-01-26 (enlazo a la versión actual por si en el futuro hago algún cambio).

Como decíamos arriba, empezamos leyendo la configuración relativa a los blogs de los que queremos leer para elegir uno. Si sólo hubiera uno se elegiría directamente:

config = ConfigParser.ConfigParser()

config.read([os.path.expanduser('~/.rssBlogs')])

print "Configured blogs:"

i=1
for section in config.sections():
	print str(i), ')', section, config.get(section, "rssFeed")
	i = i + 1

if (int(i)>1):
	i = raw_input ('Select one: ')
else:
	i = 1

print "You have chosen ", config.get("Blog"+str(i), "rssFeed")

Esta configuración debe contener una sección por blog y para cada uno de ellos contendrá la fuente RSS, el nombre de la cuenta de Twitter y el nombre de la cuenta de Facebook. Para este sitio tendría el siguiente aspecto:

[Blog1]
rssFeed:http://fernand0.github.io/feed.xml
twitterAc:mbpfernand0
pageFB:fernand0.github.io

También puede contener un campo más, linksToAvoid que se usa en el programa de extraer los enlaces para evitar algunos de ellos (lo uso en otro blog para eliminar los enlaces a las categorías).

if (config.has_option("Blog"+str(i), "linksToAvoid")):
	linksToAvoid = config.get("Blog"+str(i), "linksToAvoid")
else:
	linksToAvoid = ""

Leemos la última entrada del blog y extraemos el texto y los enlaces de manera similar a como hacíamos en Extraer enlaces de una página web.

Y para evitar los enlaces que no queríamos a la hora de generar el contenido de la página:

		print linksToAvoid
		print re.escape(linksToAvoid)
		print str(link['href'])
		print re.search(linksToAvoid, link['href'])
		if ((linksToAvoid =="") 
			or (not re.search(linksToAvoid, link['href']))):
			link.append(" ["+str(j)+"]")
			linksTxt = linksTxt + "["+str(j)+"] " + link.contents[0] + "\n"
			linksTxt = linksTxt + "    " + link['href'] + "\n"
			j =  j + 1

Finalmente, buscamos si la entrada contiene alguna imagen. Si no la hay no pondremos nada, pero Facebook lo hará su cuenta (puede ser nuestra foto, un botón, lo primero que haya). Tal vez podríamos configurar una por defecto cuando nuestra entrada no tenga una, si no nos gusta la que sale por defecto (en mi caso es mi foto; como no me gusta verla allí esto me obliga siempre a pensar en una foto para el post):

pageImage = soup.findAll("img")
#  Only the first one
if len(pageImage) > 0:
	imageLink = (pageImage[0]["src"])
else:
	imageLine = ""

Leemos la configuración para Facebook y empezamos a trabajar, solicitando la lista de páginas de las que somos administradores (el nombre de la página en la que queremos publicar lo habremos puesto en ~/.rssBlogs):

config.read([os.path.expanduser('~/.rssFacebook')])
oauth_access_token= config.get("Facebook", "oauth_access_token")

graph = facebook.GraphAPI(oauth_access_token)
pages = graph.get_connections("me", "accounts")

El fichero de configuración tiene este aspecto en este caso:

[Facebook]
oauth_access_token:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Podría haber más cuentas de Facebook, pero no lo he probado así que no garantizo que todo vaya a funcionar correctamente.

De las páginas que gestionamos se elige la que queremos (que se pone en el apartado de configuración del blog, ~/.rssBlogs).

for i in range(len(pages['data'])):
	if (pages['data'][i]['name'] == pageFB):
		print "Writing in... ", pages['data'][i]['name']
		graph2 = facebook.GraphAPI(pages['data'][i]['access_token'])
		graph2.put_object(pages['data'][i]['id'], 
			"feed", message = theSummary, link=theLink, 
			picture = imageLink, 
			name=theTitle, caption='',
			description=theSummary.encode('utf-8'))

statusTxt = "Publicado: "+theTitle+" "+theLink

Ya llevo más de un mes probando con un par de blogs y la solución parece que funciona bastante bien. Lo más molesto fue conseguir las credenciales y dar de alta la aplicación (con un ‘falso’ paso a producción; falso porque no la usa nadie más, al ser de escritorio).

Dudas, comenarios, ideas… ¡Hazme un pull request o un issue!

Técnicas para evitar ataques comunes a la memoria

Vale, no es memoria, pero la analogía me sirve

Un texto interesante en Software defense: mitigating common exploitation techniques sobre diversas técnicas que los sistemas Windows ofrecen para proteger nuestros programas frente a ciertos ataques comunes, en particular relacionadas con la gestión de la memoria y dificultar a un atacante la posibilida de encontrar los datos en lugares predecibles.

De la misma serie también se pueden leer:

Una introducción a la criptografía elíptica

El escondido

La criptografía es de mis temas ‘menos’ favoritos en seguridad. Siempre nos avisan de que es algo difícil de hacer bien. Por lo tanto nos relega al papel de meros consumidores, eso sí, tratando de estar al día en los tamaños de claves, algoritmos criptográficos y esas cuestiones.

En A (relatively easy to understand) primer on elliptic curve cryptography se publicaba hace algunos meses justamente lo que dice el título: una introducción a la criptografía de curvas elípticas que puede servirnos como introducción para recordar/ponernos al día en este tema.

Empiezan hablando de RSA y las propiedades que lo hacen interesante (la factorización es costosa -lenta- y la multiplicación es rápida).

The RSA algorithm is the most popular and best understood public key cryptography system. Its security relies on the fact that factoring is slow and multiplication is fast. What follows is a quick walk-through of what a small RSA system looks like and how it works.

Incluso muestran un pequeño ejemplo:

Let’s make this more concrete with an example. Take the prime numbers 13 and 7. Their product gives us our maximum value of 91. Let’s take our public encryption key to be the number 5. Then using the fact that we know 7 and 13 are the factors of 91 and applying an algorithm called the Extended Euclidean Algorithm, we get that the private key is the number >29.

Y sigue…

Luego, entra más a fondo en la criptografía de curvas elípticas:

An elliptic curve cryptosystem can be defined by picking a prime number as a maximum, a curve equation, and a public point on the curve. A private key is a number priv, and a public key is the public point dotted with itself priv times. Computing the private key from the public key in this kind of cryptosystem is called the elliptic curve discrete logarithm function. This turns out to be the trapdoor function we were looking for.

Interesante.

Atacando a un jugador de póquer

Ordenador

Ya habíamos hablado de ataques dirigidos a personas concretas (por ejemplo: Ataques dirigidos: el caso de Facebook).

En Sharking: High-Rollers in the Crosshairs contaban el caso de un ataque a un jugador profesional de póquer. En su hotel de Barcelona le robaron el portátil y lo infectaron con un troyano que les permitía ver las jugadas cuando se conectaba a sitios de juego en línea. En este caso el ataque dirigido consiste en un robo físico, aprovechando la presencia en un hotel y que el propietario no tomó precauciones al salir de la habitación.

Fundamentos de gestión de cuentas

Defensa

Aunque sólo se trata de una hipotética conversación entre un desarrollador y el experto en seguridad Troy Hunt podemos leer en Introducing the “Secure Account Management Fundamentals” course on Pluralsight un resumen de bastantes de las cuestiones que hay que tener en cuenta a la hora de desarrollar o poner en funcionamiento un sistema de gestión de cuentas para nuestra aplicación web, algunas bastante sutiles.

Avisos, almacenamiento de las contraseñas, recuperación de las mismas, correos de registro, reputación, sesiones, bloqueo ante ataques, cambios,…

En clase solemos decir que parece más fácil de lo que realmente resulta ser al final.

PCI y desarrollo seguro

Donde vive el dinero

Una de las cosas que nos gustó ver cuando nació PCI Data Security Standards fue su atención al desarrollo seguro de programas. En particular el punto 6 y algunos otros inciden en ese tema. En 2013 se anunció la versión 3.0 y este año debería ser la transición de la versión 2.0 que sigue vigente a la nueva.

Nada más salir, en 2013 PCI Standards se comentaban los cambios y novedades del estándar en el punto relativo al desarrollo de programas.

There is plenty of discussion elsewhere about the new standards, so I thought I would focus on the PCI DSS changes in Requirement 6 (Develop and Maintain Secure Systems and Applications):

  • 6.1 & 6.2 Switched the order of requirements 6.1 and 6.2. Requirement 6.1 is now for identifying and risk ranking new vulnerabilities and 6.2 is for patching critical vulnerabilities. Clarified how risk ranking process (6.1) aligns with patching process (6.2) and also clarified that the latter applies to “applicable” patches.
  • 6.3 Added a note to clarify that the requirement for written software development processes applies to all internally- developed software and bespoke software, and now mentions “industry standards” as well as “industry best practice”.
  • 6.3.1 Added “development/test accounts” to “custom accounts” to clarify intent of requirement
  • 6.4 & 6.4.1-6.4.4 Enhanced, more specific, testing procedures to include document reviews for all requirements.
  • 6.4.1 Aligned language between requirement and testing procedures to clarify that separation of production/ development environments is enforced with access controls.
  • 6.5 Updated developer training to include how to avoid common coding vulnerabilities, and to understand how sensitive data is handled in memory.
  • 6.5.x Updated requirements to reflect current and emerging coding vulnerabilities and secure coding guidelines. Updated testing procedures to clarify how the coding techniques address the vulnerabilities.
  • 6.5.10 New requirement for coding practices to protect against broken authentication and session management.
  • 6.6 Increased flexibility by specifying automated technical solution that detects and prevents web-based attacks rather than “web-application firewall.” Added note to clarify that this assessment is not the same as vulnerability scans required at 11.2.

Se puede descargar de la Sección de documentos de la web de PCI.

Extraer enlaces de una página web

Enlaces en Página de Facebook

Hace algunas semanas hablábamos de Publicar en Twitter las entradas de este sitio usando Python y prometíamos hacer lo mismo con Facebook.

Echando un vistazo al API de Facebook y haciendo algunas pruebas me encontré con que no podía publicar enlaces con su texto (Facebook los transforma para que podamos pinchar en ellos, pero no permite -o no encontré la forma- que los pongamos con su texto y esas cosas). Por otro lado, quería experimentar con la posibilidad de publicar las entradas de esta bitácora completas allí; Facebook no favorece que introduzcamos textos largos porque nos muestra un trocito y permite abrir ‘el resto’.

Siempre me ha llamado la atención la ‘netiqueta’ de algunas listas de correo donde suele ponerse al lado del texto de los enlaces un número y al final del mensaje la lista de esos enlaces, cada uno asociado al número correspondiente.

Esto fue lo que decidí hacer para publicar en la página de Facebook de fernand0.github.io (y otras, claro). El programa que traemos hoy hace justamente eso, como paso previo a la publicación en la página de Facebook (y, tal vez, ¿para poder enviar las entradas por correo a los interesados?).

El programa puede verse en rssToLinks.py (apuntamos, como siempre, la versión actual por si hubiera cambios en algún momento).

Algunas formas de extraer los enlaces serían: buscarlos con expresiones regulares, o también con algún parser de HTML (en el Blogómetro hace años utilizábamos el Simple SGML parser. Buscando un poco encontré el proyecto Beautiful Soup que presume de ser una manera rápida de recorrer el contenido de una página web y decidí darle una oportunidad.

Para utilizarlo incluímos los módulos necesarios. Para obtener el contenido utilizamos la fuente RSS, así que también necesitaremos feedparser:

import feedparser
from bs4 import BeautifulSoup
from bs4 import NavigableString
from bs4 import Tag

Leemos la fuente RSS y vamos recorriendo las entradas:

feed = feedparser.parse(url)

for i in range(len(feed.entries)):

Y empieza la ‘magia’ de Beautiful Soup:

        soup = BeautifulSoup(feed.entries[i].summary)
        links = soup("a")

Esto es, le pasamos los datos al analizador, y lanzamos la pregunta de lo que queremos extraer. En este caso tenemos una entrada en el summary y queremos obtener los enlaces (etiqueta a) para la entrada que ocupa la posición i. Nos devolverá una lista de elementos html que incluyen dicha etiqueta.

En algunas entradas ponemos imágenes, que no queremos que aparezcan en el texto, así que utilizamos isinstance para comprobar si dentro del contenido del enlace hay otra etiqueta para evitarla (¿es posible que encontremos algún caso más adelante que sea problemático?). Recorremos la lista de enlaces (que vienen con las etiquetas y todo, claro). Ademas utilizamos el contador j para ir asociándoles números a los sucesivos enlaces (en el HTML original, todavía no lo hemos eliminado):

	j = 0
	linksTxt = ""
	for link in links:
		if not isinstance(link.contents[0], Tag):
			# We want to avoid embdeded tags (mainly <img ... )
			link.append(" ["+str(j)+"]")
			j =  j + 1

El contenido del enlace (ahora que ya sabemos que no es una etiqueta HTML) estará en link.contents[0] (puede haber más contenido, nuestros enlaces suelen ser ‘sencillos’).

	linksTxt = linksTxt + "["+str(j)+"] " + link.contents[0] + "\n"

El enlace está en link['href'].

	linksTxt = linksTxt + "    " + link['href'] + "\n"

Ahora necesitamos el texto del HTML:

	print soup.get_text()

En algunos casos el texto puede tener muchos saltos de línea, espacios, … Se podrían eliminar. Nuestras entradas suelen estar bien estructuradas y no aparece ese problema.

Ahora, si había algún enlace (¿publicaremos alguna vez una entrada sin ningún enlace?), lo añadimos al final:

	if linksTxt != "":
		print
		print "Links :"
		print linksTxt

Números aleatorios seguros en Java

Azar

El tema de los números aleatorios de calidad para aplicaciones con requerimientos de seguridad no aparece habitualmente más que en los comentarios más técnicos. En Proper use of Java’s SecureRandom hay un texto donde se comenta el uso del generador de números seudo aleatorios seguro de Java.

When generating random numbers in Java for cryptographic purposes, many developers often use the java.security.SecureRandom class. And while the java.security.SecureRandom class is designed to generate cryptographically secure random numbers, there are a few subtleties in the API, and if it is used improperly the output can become predictable. At Cigital we have witnessed a number of cases where this is true. The following is a guide to the proper use of Java’s java.security.SecureRandom class.

Los consejos:

  • Always specify the exact PRNG and provider that you wish to use. If you just use the default PRNG, you may end up with different PRNGs on different installations of your application that may need to be called differently in order to work properly. Using the following code to get a PRNG instance is appropriate: SecureRandom sr = SecureRandom.getInstance(“SHA1PRNG”, “SUN”);
  • When using the SHA1PRNG, always call java.security.SecureRandom.nextBytes(byte[]) immediately after creating a new instance of the PRNG. This will force the PRNG to seed itself securely. If for testing purposes, you need predictable output, ignoring this rule and seeding the PRNG with hard-coded/predictable values may be appropriate.
  • Use at least JRE 1.4.1 on Windows and at least JRE 1.4.2 on Solaris and Linux. Earlier versions do not seed the SHA1PRNG securely.
  • Periodically reseed your PRNG as observing a large amount of PRNG output generated using one seed may allow the attacker to determine the seed and thus predict all future outputs.

Esto es, especificar el generador que se va a utilizar explícitamente (para evitar terminar utilizando diferentes generadores en diferentes configuraciones e instalaciones); cuidado con que la incialización se haga de manera correcta (e imprendecible); las versiones recomendadas eran en aquel momento JRE 1.4.1 para Windows y JRE 1.4.2 para Solaris y Linux por lo menos; reinicializar la semilla del PRNG para reducir la utilidad de la información generada.

El otro día hablábamos del Generador de números aleatorios de Intel y allí se pueden encontrar un par de enlaces más sobre el tema.

Una introducción a la autentificación basada en riesgos

Acciones posibles en Facebook

La autentificación parece ser el gran problema de los últimos tiempos: elegimos malas contraseñas, picamos con facilidad en muchos sitios que nos engañan para que las divulguemos ….

Las soluciones tecnológicas existen, y se pueden utilizar: pero en muchas ocasiones estaremos consiguiendo molestar a nuestros usuarios, que reutilicen contraseñas o que hagan todo lo posible para no seguir nuestras directrices (o peor: irse con la competencia).

Por eso me gustó Risk-based Authentication: A Primer donde se introduce la idea de mezclar la autentificación con una estimación del riesgo (que es, por otra parte, lo que creo que están haciendo últimamente muchos sistemas de uso masivo): se asocia a la sesión una ‘puntuación’ que determina si nuestros parámtros son ‘normales’.

Esto es, mira la localización geográfica, datos de conexión, pautas de comportamiento… Se trata, en definitiva, de ver si todo parece razonable o hay algo que no se ajusta a lo habitual y en caso de que haya motivos para desconfiar se toman medidas adicionales:

If the risk score for a user’s access attempt exceeds the system’s risk threshold, authentication controls are automatically elevated, and the user may be required to provide a higher level of authentication, such as a PIN or token. If the risk score is too high, it may be rejected outright.

Coches y ataques

Ya hemos hablado en vidas anteriores de la seguridad y los coches: es el caso típico de una cierta configuración, pensada en un contexto que de pronto (o poco a poco) cambia sin adaptarse a los nuevos riesgos. Esta vez traemos un artículo generalista de divulgación, Car hackers mess with speedos, odometers, alarms and locks.

Control

Por ejemplo, acceso a la red de comunicación interna:

… they gained access to the CAN and began fuzzing against to identitfy which of the arbitration ID packets were sent to particular components of the vehicle such as the speedometre, brakes and dashboard indicators.

Incluso poniendo a disposición de otros una herramienta:

The trio were keen for others to enter the hacking field and have produced a $25 open-modular source hardware tool for reading CANs that has the capability of those worth tens of thousands.

Como decía, hemos hablado más veces de este tipo de ataques a coches:

¿Pueden atacar tu coche?

Más ataques a coches

Seguridad ‘hogareña’

El coche, el mp3 y cosas malas que pueden suceder

Ataques a los sistemas de arranque sin llave en coches

Los sistemas de inmovilización de coches no funcionan bien