Un blog de Seguridad Informática, desde un punto de vista tecnológico

Documentación

Creating your Go HTTP API easily with goa

Using the great and simple Go http package is more than enough (and what I use) to expose simple HTTP endpoints. But when you need to build a HTTP API with lots of endpoints and user/media types, you have a lot of work ahead.

I found that using goa was a good solutions in those cases, because:

  • You design your API using a design language (DSL).
  • Lot of things are generated for you (useful code, swagger documentation, a client for the API, etc.).
  • You get a Single Source of Trust (SSoT), so for example your swagger documentation is always updated with your controllers.

But I’ll be easier to show it with a quick tutorial, so let’s go 🙂

Requirements

$ go version
go version go1.8.1 darwin/amd64
$ echo $GOPATH
/Users/Redsadic

(I like to use my $HOME as my GOPATH)

  • Install goa.
$ go get -v github.com/goadesign/goa
  • Create your new Go project in the $GOPATH/src directory.
$ mkdir -p $GOPATH/src/github.com/julianvilas/dummy-secrets
$ cd $GOPATH/src/github.com/julianvilas/dummy-secrets

Now let’s start with the fun 🙂

Design

First of all, we need to define the API using the goa DSL. Let’s create a dummy API to share secrets using One-Time links (OTL). It’s not the case of a complex API but it’s easy to show how to work with goa.

We will have 2 endpoints:

  1. To store a new secret returning the corresponding OTL.
  2. To retrieve a secret using its OTL.

To define the API create a package called design:

$ mkdir -p $GOPATH/src/github.com/julianvilas/dummy-secrets/design

And edit the file design.go (can be named as you want, e.g. api.go or split in different files).

package design

import (
 . "github.com/goadesign/goa/design"
 . "github.com/goadesign/goa/design/apidsl"
)

var _ = API("dummy-secrets", func() {
 Title("Dummy secrets")
 Description("Share your secrets using a dummy API")
 Version("1.0")
 BasePath("/v1")
 Scheme("http")
 Host("localhost:8080")
 Consumes("application/json")
})

By now we have added some basic information of the API. The BasePath will affect the URLs of all the resources we are going to add later, and the Scheme, Host and Consumes will affect both the client and the swagger documentation.

Now we can bootstrap the API running:

$ goagen bootstrap -d github.com/julianvilas/dummy-secrets/design
app
app/contexts.go
app/controllers.go
app/hrefs.go
app/media_types.go
app/user_types.go
main.go
tool/dummy-secrets-cli
tool/dummy-secrets-cli/main.go
tool/cli
tool/cli/commands.go
client
client/client.go
client/user_types.go
client/media_types.go
swagger
swagger/swagger.json
swagger/swagger.yaml
$ ll
total 8
drwxr-xr-x 7 Redsadic staff 238B 1 may 18:14 app/
drwxr-xr-x 5 Redsadic staff 170B 1 may 18:14 client/
drwxr-xr-x 4 Redsadic staff 136B 1 may 18:14 design/
-rw-r--r-- 1 Redsadic staff 555B 1 may 18:14 main.go
drwxr-xr-x 4 Redsadic staff 136B 1 may 18:14 swagger/
drwxr-xr-x 4 Redsadic staff 136B 1 may 18:14 tool/

As can be seen, some files have been generated:

  • The directory tool will contain a cli to interact with the API.
  • The client will contain a SDK, used by the cli, to interact with the API.
  • The app will implement all the needed low-level HTTP functions.
  • The swagger will contain the autogenerated documentation.
  • In the root directory, the main.go will start the HTTP server will all the API controllers (0 by now). That one, with the design package are the only we should modify. The others from above are auto-generated and shouldn’t be edited by hand.

Let’s take a look at the main.go:

//go:generate goagen bootstrap -d github.com/julianvilas/dummy-secrets/design

package main

import (
 "github.com/goadesign/goa"
 "github.com/goadesign/goa/middleware"
)

func main() {
 // Create service
 service := goa.New("dummy-secrets")

 // Mount middleware
 service.Use(middleware.RequestID())
 service.Use(middleware.LogRequest(true))
 service.Use(middleware.ErrorHandler(service, true))
 service.Use(middleware.Recover())

 // Start service
 if err := service.ListenAndServe(":8080"); err != nil {
 service.LogError("startup", "err", err)
 }

}

A new goa service is created, applying some useful middleware to it. And then the HTTP server is run listening at the port 8080 we defined in the design.go.

Now we can build, install and run it typing:

$ go install ./...
$ dummy-secrets
dummy-secrets dummy-secrets-cli
$ dummy-secrets
2017/05/01 18:33:04 [INFO] listen transport=http addr=:8080

Now we have a really dummy API, because we haven’t defined yet any resource. So let’s add the endpoints we mentioned.

Edit the design/design.go file and add:

var _ = Resource("Secrets", func() {
 BasePath("/secrets")

 Response(Created, func() {
 Status(201)
 Headers(func() {
 Header("Location", String, "Resource location", func() {
 Pattern("/secrets/[-a-zA-Z0-9]+")
 })
 })
 })

 Action("create", func() {
 Routing(POST("/"))
 Description("Store a new Secret")
 Payload(SecretPayload)
 Response(Created)
 Response(InternalServerError, ErrorMedia)
 Response(BadRequest)
 })

 Action("show", func() {
 Routing(GET("/:id"))
 Params(func() {
 Param("id", UUID)
 })
 Description("Get a Secret by its ID")
 Response(OK, SecretMedia)
 Response(NotFound)
 Response(InternalServerError, ErrorMedia)
 Response(BadRequest)
 })
})

var SecretPayload = Type("SecretPayload", func() {
 Attribute("secret", String, func() {
 Description("A secret to be shared with someone.")
 Example(`I'm a secret, share me with someone safely please.`)
 MinLength(1)
 MaxLength(255)
 Pattern("^[[:print:]]+")
 })
 Required("secret")
})

var SecretMedia = MediaType("application/vnd.secret+json", func() {
 Reference(SecretPayload)

 Attributes(func() {
 Attribute("secret")
 Required("secret")
 })

 View("default", func() {
 Attribute("secret")
 })
})

We have created a new Resource “Secrets”, with path /v1/secrets. Then we have defined two actions for it:

  • create: receives a payload like '{ "secret" : "I am a dummy secret"}' and returns an HTTP Created response, with a Location header pointing to the secret.
  • show: retrieves a secret by its ID and returns the SecretMedia.

As you see we have defined the attributes (with validation requirements), the responses and the data we expect from the users.

Now, let’s bootstrap again (we can delete the main.go file first to let it be generated again).

$ rm main.go
$ goagen bootstrap -d github.com/julianvilas/dummy-secrets/design
app
app/contexts.go
app/controllers.go
app/hrefs.go
app/media_types.go
app/user_types.go
app/test
app/test/secrets_testing.go
main.go
secrets.go
tool/cli
tool/cli/commands.go
client
client/client.go
client/secrets.go
client/user_types.go
client/media_types.go
swagger
swagger/swagger.json
swagger/swagger.yaml

Now we see that some more stuff has been generated:

  • a secrets.go file that contains the secrets controller.
  • a helper under app to create tests for the controller.

Tne new main.go now contains this new content, that is used to mount the controller into the goa service:

 // Mount "Secrets" controller
 c := NewSecretsController(service)
 app.MountSecretsController(service, c)

And the secrets.go contains:

package main

import (
 "github.com/goadesign/goa"
 "github.com/julianvilas/dummy-secrets/app"
)

// SecretsController implements the Secrets resource.
type SecretsController struct {
 *goa.Controller
}

// NewSecretsController creates a Secrets controller.
func NewSecretsController(service *goa.Service) *SecretsController {
 return &SecretsController{Controller: service.NewController("SecretsController")}
}

// Create runs the create action.
func (c *SecretsController) Create(ctx *app.CreateSecretsContext) error {
 // SecretsController_Create: start_implement

 // Put your logic here

 // SecretsController_Create: end_implement
 return nil
}

// Show runs the show action.
func (c *SecretsController) Show(ctx *app.ShowSecretsContext) error {
 // SecretsController_Show: start_implement

 // Put your logic here

 // SecretsController_Show: end_implement
 res := &app.Secret{}
 return ctx.OK(res)
}

 

Now we have to implement the logic of these two controllers.

Implement

First we need to create a storage where secrets can be stored and retrieved. In order to make things easy to test or replace and well organized, we will define a Persister interface. Let’s put it in its own package persister.

$ mkdir persister
$ touch persister/persister.go

Edit the persister.go and add:

package persister

import (
 uuid "github.com/satori/go.uuid"
)

type Persister interface {
 Store(secret string) uuid.UUID
 Retrieve(id uuid.UUID) (string, error)
}

 

And add also a implementation for the Persister interface:

type MemPersister struct {
 storage map[string]string
 mux sync.RWMutex
}

func NewMemPersister() *MemPersister {
 return &MemPersister{
 storage: make(map[string]string),
 }
}

func (mp *MemPersister) Store(secret string) uuid.UUID {
 id := uuid.NewV4()

 mp.mux.Lock()
 defer mp.mux.Unlock()

 mp.storage[id.String()] = secret

 return id
}

func (mp *MemPersister) Retrieve(id uuid.UUID) (string, error) {
 mp.mux.RLock()
 defer mp.mux.RUnlock()

 secret, ok := mp.storage[id.String()]
 if !ok {
 return "", fmt.Errorf("error: a secret with id %v doesn't exist.", id)
 }
 delete(mp.storage, id.String())

 return secret, nil
}

 

Now we need to do two things:

  1. Add a Persister to the secrets controller, and implement the logic.
  2. Inject the MemPersister in the main.

First we modify the secrets.go:

package main

import (
 "github.com/goadesign/goa"
 "github.com/julianvilas/dummy-secrets/app"
 "github.com/julianvilas/dummy-secrets/persister"
)

// SecretsController implements the Secrets resource.
type SecretsController struct {
 *goa.Controller
 storage persister.Persister
}

// NewSecretsController creates a Secrets controller.
func NewSecretsController(service *goa.Service, st persister.Persister) *SecretsController {
 return &SecretsController{
 Controller: service.NewController("SecretsController"),
 storage: st,
 }
}

// Create runs the create action.
func (c *SecretsController) Create(ctx *app.CreateSecretsContext) error {
 secret := ctx.Payload.Secret
 id := c.storage.Store(secret)

 ctx.ResponseData.Header().Set("Location", app.SecretsHref(id.String()))

 return ctx.Created()
}

// Show runs the show action.
func (c *SecretsController) Show(ctx *app.ShowSecretsContext) error {
 id := ctx.ID
 secret, err := c.storage.Retrieve(id)
 if err != nil {
 goa.LogError(ctx, err.Error())
 return ctx.NotFound()
 }

 res := &app.Secret{secret}
 if err := res.Validate(); err != nil {
 goa.LogError(ctx, err.Error())
 return ctx.InternalServerError(goa.ErrInternal(err))

 }

 return ctx.OK(res)
}

 

And finally the main.go:

//go:generate goagen bootstrap -d github.com/julianvilas/dummy-secrets/design

package main

import (
 "github.com/goadesign/goa"
 "github.com/goadesign/goa/middleware"
 "github.com/julianvilas/dummy-secrets/app"
 "github.com/julianvilas/dummy-secrets/persister"
)

func main() {
 // Create service
 service := goa.New("dummy-secrets")

 // Mount middleware
 service.Use(middleware.RequestID())
 service.Use(middleware.LogRequest(true))
 service.Use(middleware.ErrorHandler(service, true))
 service.Use(middleware.Recover())

 // Mount "Secrets" controller
 mp := persister.NewMemPersister()
 c := NewSecretsController(service, mp)
 app.MountSecretsController(service, c)

 // Start service
 if err := service.ListenAndServe(":8080"); err != nil {
 service.LogError("startup", "err", err)
 }

}

 

Run

Let’s test what we did. First of all, build and install again with go install ./....

Now use the cli to store a secret and the retrieve it:

$ dummy-secrets-cli
CLI client for the dummy-secrets service

Usage:
 dummy-secrets-cli [command]

Available Commands:
 create Store a new Secret
 help Help about any command
 show Get a Secret by its ID

Flags:
 --dump Dump HTTP request and response.
 -H, --host string API hostname (default "localhost:8080")
 -s, --scheme string Set the requests scheme
 -t, --timeout duration Set the request timeout (default 20s)

Use "dummy-secrets-cli [command] --help" for more information about a command.

 

Start the service:

$ dummy-secrets
2017/05/01 20:03:21 [INFO] mount ctrl=Secrets action=Create route=POST /v1/secrets
2017/05/01 20:03:21 [INFO] mount ctrl=Secrets action=Show route=GET /v1/secrets/:id
2017/05/01 20:03:21 [INFO] listen transport=http addr=:8080

 

Store a secret:

$ dummy-secrets-cli create secrets --payload '{ "secret" : "a dummy secret" }' --dump
2017/05/01 20:05:30 [INFO] started id=OIBa7E5P POST=http://localhost:8080/v1/secrets
2017/05/01 20:05:30 [INFO] request headers Content-Type=application/json User-Agent=dummy-secrets-cli/1.0
2017/05/01 20:05:30 [INFO] request body={"secret":"a dummy secret"}
2017/05/01 20:05:30 [INFO] completed id=OIBa7E5P status=201 time=3.515675ms
2017/05/01 20:05:30 [INFO] response headers Date=Mon, 01 May 2017 18:05:30 GMT Content-Length=0 Content-Type=text/plain; charset=utf-8 Location=/v1/secrets/614dcf25-02e2-43dd-9809-e189abb7d8a7

In the last line of the log can be seen the Location header where the ID of the secret is returned:

Location=/v1/secrets/614dcf25-02e2-43dd-9809-e189abb7d8a7

Now retrieve the secret using the ID:

$ dummy-secrets-cli show secrets --id 614dcf25-02e2-43dd-9809-e189abb7d8a7 --pp
2017/05/01 20:08:28 [INFO] started id=0VBkwhgo GET=http://localhost:8080/v1/secrets/614dcf25-02e2-43dd-9809-e189abb7d8a7
2017/05/01 20:08:28 [INFO] completed id=0VBkwhgo status=200 time=4.074434ms
{
 "secret": "a dummy secret"
}

If you try to run it again, you’ll see that the secret is no longer available, as we implemented it as an OTL.

You can test it also with curl:

$ curl -vvv -X POST --data '{ "secret" : "a dummy secret" }' http://localhost:8080/v1/secrets
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /v1/secrets HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.51.0
> Accept: */*
> Content-Length: 31
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 31 out of 31 bytes
< HTTP/1.1 201 Created
< Location: /v1/secrets/e293bf3a-5b0b-487c-841c-a4ad17e4bbe9
< Date: Mon, 01 May 2017 18:13:25 GMT
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
<
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

$ curl -vvv http://localhost:8080/v1/secrets/e293bf3a-5b0b-487c-841c-a4ad17e4bbe9
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /v1/secrets/e293bf3a-5b0b-487c-841c-a4ad17e4bbe9 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/vnd.secret+json
< Date: Mon, 01 May 2017 18:14:58 GMT
< Content-Length: 28
<
{"secret":"a dummy secret"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
$ curl -vvv http://localhost:8080/v1/secrets/e293bf3a-5b0b-487c-841c-a4ad17e4bbe9
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /v1/secrets/e293bf3a-5b0b-487c-841c-a4ad17e4bbe9 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Mon, 01 May 2017 18:15:00 GMT
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
<
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

 

And that was all! We got it running 🙂

You got the example in github, just:

$ go get -v github.com/julianvilas/dummy-secrets

Also you can see the swagger doc in http://swagger.goa.design/?url=julianvilas/dummy-secrets/design.

Improvements

  1. Create a FilePersister and to store in files instead of memory (or a S3Persister, it’s easy to replace the Persister as we created it as an interface).
  2. Create tests! You can use the app/test helpers goa generated for you.
  3. Create documentation.

References

 


Cuando las ballenas vuelan (episodio II) – Creando un entorno de análisis GSM usando Docker (parte 1)

Esta entrada surge inspirada por ésta otra de Fox Glove Security: When Whales Fly – Building a Wireless Pentest Environment using Docker donde se explica cómo utilizar contenedores Docker para hacer más fácil el uso de algunas herramientas de pentesting WiFi. En este caso lo que se ha querido “contenizar” son herramientas para analizar comunicaciones GSM.

Aunque en esa entrada hay un excelente resumen sobre contenedores, Docker, imágenes y la filosofía de trabajo, aquí rescatamos algunos aspectos importantes para los que no sepan de que va el tema:

  • A nivel usuario, Docker (o LXC) no deja de comportarse como una especie de hypervisor, aunque son conceptos diferentes. Una analogía que me ayudó a entender la diferencia en el aislamiento que proporcionan es: cuando se virtualiza con un hypervisor “clásico” las máquinas virtuales son como casa individuales; los contenedores, en cambio, se parecen más a los apartamentos de un mismo edificio (Containers are not VMs).
  • Docker es el motor sobre el que corren los contenedores y estos comparten recursos, a través del kernel, con el host y con los otros contenedores.
  • Docker permite ejecutar versiones específicas de aplicaciones sin la penalización de rendimiento que suponen las máquinas virtuales.
  • Las imágenes Docker serían el equivalente a los binarios tradicionales en los SO, a partir de ellas se pueden crear contenedores (el equivalente a los procesos en los SO tradicionales).
  • Los contenedores pueden ser efímeros o perdurar tanto como quiera el usuario.
  • Los contenedores se pueden ejecutar de forma interactiva o como servicios.

Toda la información sobre Docker puede encontrarse en su propia sección de documentación:

Software Defined Radio

Contenedor base

El primer paso ha sido crear un contenedor con las herramientas básicas para trabajar con SDRs (Software Defined Radio), como por ejemplo los basados en hardware RTL, y con soporte para ejecutar aplicaciones gráficas aceleradas por hardware. El motivo para crear este contenedor base es poder aprovecharlo a la hora de trabajar con aplicaciones para otros protocolos de radio.

Nota: RTL-SDR es un tipo de SDR muy barato que utiliza dongles USB basados en el xip RTL2832U pensados para ver la TV y escuchar la radio. Mediante los esfuerzos combinados de Antti Palosaari, Eric Fry y Osmocom se descubrió que era posible acceder directamente a los datos de la señal I/Q de estos dispositivos, lo que permitió convertirlos en SDRs mediante un nuevo driver.

El código para crear la imagen Docker está en este repositorio:

Así como ésta ya compilada en Docker Hub:

docker pull pachulo/xenial-gnuradio-rtl-toolkit

Como se puede ver en el Dockerfile la imagen:

Una vez compilada la imagen o descargada de Docker Hub, ya podremos realizar las primeras pruebas: por ejemplo, para comprobar que podemos acceder al dispositivo RTL desde el contenedor, podemos ejecutar el comando rtl_test dentro de un contenedor efímero:

docker run --rm --device=/dev/bus/usb/002 --entrypoint rtl_test pachulo/xenial-gnuradio-rtl-toolkit

Nota: una forma fácil de averiguar en que HUB USB hemos conectado nuestro dispositivo es ejecutar el comando dmesg justo después de conectarlo. Para el ejemplo de arriba me he guiado por esta información:

...
[10891.158562] usb 2-1.3: new high-speed USB device number 14 using ehci-pci
[10891.279033] usb 2-1.3: New USB device found, idVendor=0bda, idProduct=2838
[10891.279039] usb 2-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10891.279041] usb 2-1.3: Product: RTL2838UHIDIR
[10891.279043] usb 2-1.3: Manufacturer: Realtek
[10891.279045] usb 2-1.3: SerialNumber: 00000001
...

GR-GSM

Basado en la anterior se ha creado una imagen con gr-gsm, un software basado en GNURadio y cuyo objetivo es (según su propio autor):

The aim is to provide set of tools for receiving information transmitted by GSM equipment/devices.

En el siguiente enlace su pueden obtener los ficheros para compilar la imagen Docker:

Así como ésta ya compilada en Docker Hub:

docker pull pachulo/xenial-gr-gsm

Tal y como se puede observar en el Dockerfile, para crear la imagen se compila el software desde el código fuente y se copian un par de archivos para su correcto funcionamiento.

Antes de poder utilizar la imagen habrá que explicar un par de cosas sobre ejecutar aplicaciones basadas en X11 dentro de contenedores.

Aplicaciones gráficas dentro de contenedores

Ejecutar aplicaciones con GUI dentro de contenedores es un problema que ya se ha abordado anteriormente y para el que existen varias soluciones. Y si queremos obtener aceleración por hardware para utilizar aplicaciones OpenGL (como por ejemplo GNURadio) la cosa se complica un poco más, tal y como se explica en HW accelerated GUI apps on Docker.

Además de todo esto, si el sistema utiliza una tarjeta gráfica NVIDIA con el driver privativo, hará falta instalar en el host nvidia-docker, una utilidad de NVIDIA para crear y ejecutar imágenes Docker con acceso a sus GPUs (el porqué es necesaria la utilidad está explicado en su wiki).

La solución que se ha utilizado para este caso es la siguiente:

  • Antes de crear el contenedor:
  • Y al crearlo:
    • Se monta el nuevo fichero Xauthority dentro del contenedor.
    • Se configura la variable de entorno XAUTH en el contenedor para que apunte al nuevo fichero Xauthority.
    • Se pasa la variable de entorno DISPLAY al contenedor con el mismo valor que la del host.
    • Se monta el fichero que hará de socket X dentro del contenedor.
    • Se monta el fichero de caracteres que representa a la tarjeta gráfica dentro del contenedor (de esto se encarga nvidia-docker para GPUs NVIDIA).

Ya que creo que ofrece suficiente aislamiento: el contenedor solo tendrá acceso de lectura-escritura al socket X y al fichero Xauthority y solo se podrá acceder al servidor X11 con la cookie creada para el nuevo fichero Xauthority, además de funcionar con la aceleración por hardware.

Nota: El contenedor creado funciona en mi máquina Ubuntu, que utiliza una tarjeta NVIDIA y el driver privativo, con nvidia-docker pero lo suyo sería ver si en otros sistemas basados en Linux con gráficas Intel y ATI también funciona (utilizando los drivers basados en MESA en esos casos, tal y como se explica aquí). Los usuarios de Windows y MacOS pueden probar alguna de las cosas que se comentan en este issue de Docker.

gr-gsm livemon

Una vez compilada o descargada la imagen y instalado nvidia-docker en el host ya se podrá realizar alguna prueba, como por ejemplo sintonizar el canal de broadcast (BCCH) de estaciones base próximas con la aplicación grgsm_livemon, ejecutando el siguiente script:

# Video support
XAUTH=/tmp/.docker.xauth
touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
XSOCK=/tmp/.X11-unix

# Launch container
nvidia-docker run \
 --volume $XAUTH:$XAUTH \
 --env XAUTHORITY=$XAUTH \
 --env DISPLAY \
 --volume $XSOCK:$XSOCK \
 --env="QT_X11_NO_MITSHM=1" \
 --device=/dev/bus/usb/002 \
 --rm \
 --entrypoint grgsm_livemon \
 pachulo/xenial-gr-gsm

Si todo ha ido bien, se tendría que abrir una ventana como esta:

OsmocomBB

Otra de las imágenes que se ha creado ha sido una con OsmocomBB listo para usar. Toda la información sobre OsmocomBB se puede encontrar en su wiki, pero básicamente:

OsmocomBB is an Free Software / Open Source GSM Baseband software implementation. It
intends to completely replace the need for a proprietary GSM baseband software, such as
– drivers for the GSM analog and digital baseband (integrated and external) peripherals
– the GSM phone-side protocol stack, from layer 1 up to layer 3
In short: By using OsmocomBB on a compatible phone, you will be able
to make and receive phone calls, send and receive SMS, etc. based on Free Software only.

En el siguiente enlace su pueden obtener los ficheros para compilar la imagen Docker:

Así como ésta ya compilada en Docker Hub:

docker pull pachulo/xenial-osmocombb

Nota: Para poder utilizar esta imagen hará falta un teléfono compatible y un cable/adaptador USB-serie.

Cargar firmware y ejecutar la aplicación mobile

Una vez descargada (o compilada) la imagen y conectado el teléfono con el adaptador USB-serie, podemos arrancar un contenedor con la misma:

docker run --device=/dev/ttyUSB0 --rm -it --name test-osmocombb pachulo/xenial-osmocombb

Podemos probar a cargar un firmware en el teléfono ejecutando el comando osmocon dentro del contenedor:

cd /osmocom-bb/src/host/osmocon && ./osmocon -p /dev/ttyUSB0 -m c123xor ../../target/firmware/board/compal_e88/layer1.compalram.bin

Y haciendo una pulsación corta del botón de encendido del teléfono.

Si el firmware se ha cargado de forma correcta, el siguiente paso será conectarnos al contenedor desde otro terminal y ejecutar “mobile”, la implementación de la funcionalidad de un teléfono móvil normal que correrá en el contenedor:

docker exec -ti test-osmocombb /bin/bash
cd /osmocom-bb/src/host/layer23/src/mobile && ./mobile -i 127.0.0.1

Y que nos permitirá conectarnos y interactuar con el teléfono a través de telnet:

docker exec -ti test-osmocombb /bin/bash
telnet 127.0.0.1 4247

Kraken

Otra de las herramientas que se utilizan para el análisis de seguridad de redes GSM es Kraken, un software que:

… allows the ‘cracking’ of A5/1 keys used to secure GSM 2G calls and SMS.

Nota: Para poder ejecutar esta herramienta será necesario un disco de 2TB para almacenar las rainbow tables (y unos 1.8TB de espacio de disco en otro sitio para descargarlas y poder volcarlas luego). Todo el proceso está explicado en Passive GSM interception Part 1. Para el volcado de las tablas se puede utilizar el contenedor.

Los ficheros para compilar la imagen están aquí:

Así como ésta ya compilada en Docker Hub:

docker pull pachulo/xenial-kraken

Para ejecutarla necesitaremos clonar el repositorio:

git clone https://github.com/pachulo/docker-xenial-kraken

Y después ejecutar el contenedor con algo similar a esto:

docker run -ti --rm --device=/dev/disk/by-id/wwn-0x5000c50091dc385d-part2:/dev/xvdc2 -v /media/$USER/DRIZZLECHAIR/kraken/indexes/:/kraken/indexes/ pachulo/xenial-kraken

Conclusión

En la continuación de esta entrada veremos cómo ejecutar algunos escenarios de análisis y ataque en GSM utilizando estos contenedores.


Explotación en Android y SET

En relación con la presentación de SMS Spoofing, nos ha llegado alguna petición sobre el material relacionado con la demo explotación de Android.

Lo primero, comentar que todo lo utilizado para la demo de explotación de Android está basado en el trabajo de Javier Moreno y Eloi Sanfélix, presentado en la Rooted CON 2010,  Seguridad y explotación nativa en Android. Los autores publicaron material sobre la presentación en sus respectivos blogs:

Para información sobre explotación nativa en Android os referenciamos pues, a dicho material :).

Sin embargo, ponemos a vuestra disposición el siguiente material, que utilizamos durante la presentación de SMS Spoofing:

android_stack_tb.rb: El exploit original de Eloi Sanfelix y Javier Moreno, con la
“Ret” modificada para obtener el control con el desbordamiento en nuestro entorno Android 1.6 (API level 4).

(más…)


Uso de SMS Spoofing desde SET

menu_principal

Aprovechando la publicación de los vídeos de la NcN, para aquellos que estén interesados, comentamos que durante la charla se realizó una demostración del uso de la funcionalidad de “SMS Spoofing” que se ha añadido a la versión 1.0 de Social Engineering Toolkit (SET). Por cierto, aprovechamos tambén para agradecer a Dave Keneddy la “acogida” de la aportación al framework de SET. Ha sido un auténtico placer poder colaborar con este proyecto.

En este post nos gustaría acabar de repasar las diferentes opciones disponibles des de la funcionalidad de “SMS Spoofing”.
Tras ejecutar SET, se puede acceder a las opciones de “SMS Spoofing” desde el menú principal, con la opción “7”:

(más…)


No cON Name 2010

El pasado 21 de Octubre de 2010 se celebró la edición 2010 del congreso de las NcN 2010. Durante ésta tuve el placer de compartir, junto con mis compañeros Juan y Pau, el resultado de la investigación realizada sobre el SMSspoofing y sus riesgos derivados en la actualidad.

La investigación se ha llevado a cabo gracias a la colaboración y apoyo de la empresa en la que trabajo, TB·Security.

En ella hemos tenido la oportunidad de analizar el estado del arte de SMSspoofing, así como para ampliar las funcionalidades de SET (Social Engineering Toolkit) para:

  • El envío de SMS mediante proveedores de envío de mensajes (spoofeables)
  • La explotación de vulnerabilidades en terminales móviles
  • La incorporación y creación de plantillas para mensajes SMS enviados

En posteriores entradas iremos profundizando en los detalles de la investigación realizada, compartiendo nuestras experiencias y descubrimientos. Por lo de pronto queremos haceros llegar la presentación realizada 🙂

Por último felicitar y agradecer a la asociación No cON Name por el evento, en el que personalmente me lo pasé genial. Felicitar también a los ponentes, que dieron unas charlas de lo más interesante y agradecer a TB·Security su gran apoyo y colaboración.

Hasta pronto!

Presentacion-NCN_2010