viernes, 26 de junio de 2009

Accediendo un servidor ftp con python usando ftplib

Es común necesitar automatizar ciertas tareas al interactuar con un servidor ftp. Por lo tanto tenemos una fácil opción de interactuar desde nuestro script python con el servidor remoto con una librería estándar muy util: ftplib. No debemos tener problemas con instalación o cualquier otra configuración pues esta librería viene por defecto con la instalación básica de python.

Para importar el objeto ftp simplemente usaremos

from ftplib import FTP


el primer método con el que nos veremos relacionados es el constructor que en el cual podemos llevar acabo toda la conexión, su sintaxis es la siguiente:

class ftplib.FTP([host[, user[, passwd[, acct[, timeout]]]]])

hacemos la conexion:

host = “ftp.host.org”
user = “juan”
passwd= “secreto”
tp = FTP(host, user, passwd)

Y hemos entablado la comunicación con el servidor ftp. Ahora veamos algunos métodos comunes en el manejo ftp.


Para crear un nuevo directorio remoto

ftp.mkd('galeria')

Para cambiar a un nuevo directorio de trabajo remoto
ftp.cwd('galeria')

pwd nos muestra el directorio actual en el que nos encontramos.
ftp.pwd()
/htdocs/galeria


Finalmente el famoso dir, que nos mostrara el contenido del directorio actual en la salida estándar de nuestro prompt
ftp.dir()

Ahora bien, para cargar un archivo de forma binaria se utiliza:

f = open('imagen.png', 'rb')
ftp.storbinary('STOR imagen.png', f)
f.close()

Y para descargar un archivo en forma binaria al directorio de trabajo local actual:

ftp.retrbinary('RETR imagen.png', open('imagen2.png', 'wb').write)

Finalmente, para eliminar un archivo remoto:

ftp.delete('imagen.png')

Y para eliminar un directorio

ftp.rmd('galeria')

espero este breve recorrido por el uso de los comandos ftp haya sido útil para todos...

viernes, 12 de junio de 2009

Algoritmos de Ordenamiento

Comparto con ustedes un programa en C ANSI 89 que muestra la implementación de cuatro algoritmos de ordenamient: Burbuja, Selección, Inerción y una implementación básica de Quicksort son optimizaciones. Espero este ejemplo siva a todos los estudiantes para ver la aplicación de estos algoritmos.
La licencia es GPL 3 así que ya saben, pueden copiar y pegar sin problema siempre y cuando el nuevo código esté disponible bajo GPL 3 o superior.

/*
* Escrito por Jesús Manuel Mager Hois
* el 27 de abril de 2009, tomando referencias
* de Wikipedia.
*
* Descripción: Programa que genera listas
* aleatorias para después
* ordenarlas con los algoritmos
* de burbuja, selección,
* inserción y quicksort.
*
* Todos los algoritmos son simples,
* y representan únicamente
* las ideas básicas detrás de
* cada algoritmo.
*
* Lenguaje: ANSI C
*
* Bajo licencia GPL 3
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define V_SIZE 10

int cont;

// Herramientas
void gen_rand(int v[], int size);
void print_vect(int v[], int size);
void swap(int v[], int o, int d);

//Algoritmos
void bubble_sort(int v[], int size);
void insert_sort(int v[], int size);
void select_sort(int v[], int size);
void quick_sort(int v[], int size);
void q_sort(int v[], int left, int right);
//void quick_sort(int v[], int size);

int main(int argc, char *argv[])
{
int v[V_SIZE];

printf("---------------------------------------------------\n");
printf("UNAM FCA SUA\n");
printf("Materia: Informática III\n");
printf("Alumno: Jesús Manuel Mager Hois\n");
printf("---------------------------------------------------\n");
printf("Este programa genera listas aleatorias que son\n");
printf("ordenadas por los siguientes algoritmos: bubblesort\n");
printf("insert sort, selecction sort y quicksort. Todos\n");
printf("son ejemplos sencillos que solo pretenden mostrar\n");
printf("los conecpts básicos de cada uno.\n");
printf("Por J. M. 2009 Bajo GPL 3. (ver código fuente)\n");
printf("############ Ordenando con Burbuja ############\n");
gen_rand(v, V_SIZE);
printf("No. Aleatorios: ");
print_vect(v, V_SIZE);

bubble_sort(v, V_SIZE);
printf("No. Ordenados : ");
print_vect(v, V_SIZE);

printf("############ Ordenando por Inserción ##########\n");
gen_rand(v, V_SIZE);
printf("No. Aleatorios: ");
print_vect(v, V_SIZE);

insert_sort(v, V_SIZE);
printf("No. Ordenados : ");
print_vect(v, V_SIZE);

printf("############ Ordenando por Selección ##########\n");
gen_rand(v, V_SIZE);
printf("No. Aleatorios: ");
print_vect(v, V_SIZE);

select_sort(v, V_SIZE);
printf("No. Ordenados : ");
print_vect(v, V_SIZE);

printf("############ Ordenando por Quicksort ##########\n");
gen_rand(v, V_SIZE);
printf("No. Aleatorios: ");
print_vect(v, V_SIZE);

quick_sort(v, V_SIZE);
printf("No. Ordenados : ");
print_vect(v, V_SIZE);



return 0;
}


void gen_rand(int v[], int size)
{
int i;

cont = cont + 1;
srand(time(NULL)*cont);
for(i=0; i<size; i++)
v[i]=rand()%100;
}


void print_vect(int v[], int size)
{
int i;
printf("[ ");
for(i=0; i<size; i++)
printf("%d ", v[i]);
printf("]\n");
}

void swap(int v[], int o, int d)
{
int temp;
temp=v[d];
v[d]=v[o];
v[o]=temp;
}

void bubble_sort(int v[], int size)
{
int i, j;
for (j=0; j<size; j++)
for (i=0; i<size-1; i++)
if(v[i]>v[i+1])
swap(v, i, i+1);
}

void insert_sort(int v[], int size)
{
int i, j, temp;
for(i=0; i<size; i++)
{
temp=v[i];
j=i-1;
while(j>=0 && v[j] >temp)
{
v[j+1] = v[j];
j--;
}

v[j+1] = temp;
}
}

void select_sort(int v[], int size)
{
int i, j, min;
for (i=0; i<size; i++)
{
min=i;

for(j=i+1; j< size; j++)
if(v[min]>v[j])
min=j;

swap(v, min, i);
}
}

void quick_sort(int v[], int size)
{
q_sort(v, 0, size-1);
}

void q_sort(int v[], int left, int right)
{

int pivot, lTmp, rTmp;
lTmp=left;
rTmp=right;
pivot=v[left];

while ( left < right )
{
while((v[right] >= pivot) && (left < right))
right--;
if(left != right)
{
v[left]=v[right];
left++;
}
while ((v[left] <= pivot) && (left<right))
left++;
if(left!=right)
{
v[right]=v[left];
right--;
}
}
v[left]=pivot;
pivot=left;
left=lTmp;
right=rTmp;

if(left<pivot)
q_sort(v, left, pivot-1);
if(right>pivot)
q_sort(v, pivot+1, right);
}



martes, 9 de junio de 2009

Scanners y NMap

Los scanner son herramientas que son utilizadas para poder encontrar ciertas características del objetivo sobre el cual se dirigen. Pueden encontrar desde los servicios con los que cuenta un determinado servidor, hasta “mapear” la red objetivo. Se suelen usar estas herramientas para las auditorias de seguridad, como herramientas para administradores de res, y como instrumentos para encontrar posibles vulnerabilidades de un servidor dado.


Como primer ejemplo de un scanner encontramos a la herramienta libre NMap, que es usada como un explorador de redes y como un scanner de servicios. Es muy usado en el mundo de la seguridad y cuenta con muchas técnicas de escaneo. Se puede configurar desde el tipo de escaneo como TCP o UDP, hasta técnicas de evasión contra sistemas de detección de intrusos.


Se diseñó para analizar rápidamente grandes redes, aunque funciona muy bien contra equipos individuales. Nmap utiliza paquetes IP “raw” en formas originales para determinar qué equipos se encuentran disponibles en una red, qué servicios (nombre y versión de la aplicación) ofrecen, qué sistemas operativos (y sus versiones) ejecutan, qué tipo de filtros de paquetes o cortafuegos se están utilizando así como docenas de otras características.


Con el resultado de escaneo se lista en primer la guara la llamada información primordial en la “tabla de puertos interesantes” donde se muestra la lista de número de puerto y protocolo, el nombre del servicio que se debería proporcionar en dicho puerto y su estado(filtrado, abierto, cerrado, no filtrado), donde filtrado indica un firewall impidiendo un acceso.


Si hacemos un escaneo del servidor de la página web de la FCA, sin ninguna técnica especial de escaneo, con el objeto de encontrar la “tabla de puertos interesantes”, nmap genera la siguiente salida:

usuario-desktop:nmap-4.85BETA9 usuarios$ nmap -v -A www.algunhost.com

Starting Nmap 4.85BETA9 ( http://nmap.org ) at 2009-06-03 18:40 CDT
Warning: File ./nmap-services exists, but Nmap is using /usr/local/share/nmap/nmap-services for security and consistency reasons. set NMAPDIR=. to give priority to files in your local directory (may affect the other data files too).
NSE: Loaded 28 scripts for scanning.
Initiating Ping Scan at 18:40
Scanning 132.248.xx.xx [1 port]
Completed Ping Scan at 18:40, 0.03s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 18:40
Completed Parallel DNS resolution of 1 host. at 18:40, 0.04s elapsed
Initiating Connect Scan at 18:40
Scanning www.algunhost.com (132.248.xx.xx) [1000 ports]
Discovered open port 443/tcp on 132.248.xx.xx
Discovered open port 3306/tcp on 132.248.xx.xx
Discovered open port 80/tcp on 132.248.xx.xx
Discovered open port 22/tcp on 132.248.xx.xx
Discovered open port 111/tcp on 132.248.xx.xx
Discovered open port 2008/tcp on 132.248.xx.xx
Completed Connect Scan at 18:40, 18.25s elapsed (1000 total ports)
Initiating Service scan at 18:40
Scanning 6 services on www.algunhost.com (132.248.xx.xx)
Completed Service scan at 18:42, 116.89s elapsed (6 services on 1 host)
NSE: Script scanning 132.248.18.65.
NSE: Starting runlevel 1 scan
Initiating NSE at 18:42
Completed NSE at 18:43, 31.63s elapsed
NSE: Script Scanning completed.
Host www.algunhost.com (132.248.xx.xx) is up (0.26s latency).
Interesting ports on www.algunhost.com (132.248.xx.xx):
Not shown: 993 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.3 (protocol 2.0)
|_ ssh-hostkey: 1024 d6:fa:ad:91:51:b8:f1:9b:a4:c1:f2:40:d0:90:16:77 (DSA)
80/tcp open http Apache httpd 2.2.2 ((Fedora))
|_ html-title: Esto es algunhost cualquiera
111/tcp open rpcbind
| rpcinfo:
| 100000 2 111/udp rpcbind
| 100024 1 32768/udp status
| 100000 2 111/tcp rpcbind
|_ 100024 1 42551/tcp status
443/tcp open ssl/http Apache httpd 2.2.2 ((Fedora))
| html-title: Esto es algunhost cualquiera
|_ Requested resource was http://www.algunhost.com/home/
1080/tcp filtered socks
2008/tcp open conf?
3306/tcp open mysql?

Read data files from: /usr/local/share/nmap
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 166.96 seconds



El escaneo nos indica que el servidor proporciona servicios ssh, en concreto OpenSSH 4.3, servicio Web a través del puerto 80 con un Servidor apache 2.2.2 precompilado para sistemas Fedora, un servicio rpcbind en el puerto 111, una conexión http encriptada mediante ssh/http como conocida como https en el puerto 443. También no se puede indentidicar bien la versión del servidor MySQL en el puerto 3306, además de un puerto de socket filtrado en 1080.


Esto nos ayuda a encontrar la vulnerabilidades del sistema, como por ejemplo la información de que el servidor corre un servidor OpenSSH de versión 4.3 nos indica que es posiblemente vulnerable a un ataque de denegación de servicios: OpenSSH <= 4.3 p1 (Duplicated Block) Remote Denial of Service Exploit. Sin embargo no es el caso ya que la vulnerabilidad solo afecta al protocolo 1 y no al 2 como indica la información de NMap. De esta forma se pueden encontrar vulnerabilidades del sistema en cuestión.


En otro post pondremos un manual básico de comandos NMap.

domingo, 7 de junio de 2009

Inyección SQL

La inyección SQL es la segunda vulnerabilidad más común en aplicaciones web, y es muy similar a XSS. Pero no solo puede suceder en aplicaciones web, si no en toda aplicación que utilice SQL dentro de sus dominios, usando cualquier lenguaje de programación. Esta vulnerabilidad es un error de una clase más general de vulnerabilidades que puede ocurrir cuando un lenguaje de programación o de script que esté incrustado dentro de otro. Las diferentes sintaxis de cada lenguaje permiten jugar con ellos, de tal forma que al introducir cierto valor a un lenguaje éste valor puede ser manipulado para ser interpretado por el lenguaje de script de una forma tal que se pueda abusar de estas sentencias. O como lo dice wikipedia: Una inyección SQL sucede cuando se inserta o "inyecta" un código SQL "invasor" dentro de otro código SQL para alterar su funcionamiento normal, y hacer que se ejecute maliciosamente el código "invasor" en la base de datos.

Esta vulnerabilidad puede ser evitada por el programador, comprobando y manipulando la cadena entrante, para poder detectar cualquier abuso en el uso de la información entrante. Lo que se puede entender a partir de esto es que este tipo de errores se generan por la falta de conocimientos del programador, por el descuido en la programación, o en las malas costumbres de programación.

Veamos como se da este proceso de ataque y mala programación en un script PHP haciendo interfaz con MySQL y utilizando un form HTML.

El primer contacto del usuario con la aplicación es la interfaz HTML y en concreto la FORM de éste. Se pueden agregar ciertas restricciones a la entrada de tal forma que pareciera segura la aplicación:



< form action=”process.php” method=”POST” >
Seleccione el color:
< select name=”color” >
< option value=”red” > rojo< /option >
< option value=”verde” > verde< /option >
< option value=”azul” > azul< /option >
< /select >
< input type=”submit” / >
< /form >


Sin embargo, sabemos que no sería suficiente con esta restricción, pues es posible ingresar directamente los valores al script process.php sin la necesidad de limitarnos a las opciones antes vistas.

process.php?color=morado

hasta este punto llega el ataque XSS, donde se introduce código mailicioso dentro de las entradas que no se suponen que puedan ser distintas, pero ahora veamos como se da esto en una entrada donde la cadena será usada en una sentencia SQL.

Supongamos el siguiente script PHP:


Si el usuario es una perosona bien intencionada introducirá su usuario y si password sin que pase nada. La sentencia SQL sería:

SELECT count(*)
FROM users
WHERE username = ‘juan’
AND password=’eselmejor’”;

y Juan accesará a su cuenta sin mayor problema.

Pero el pasado script es vulnerable, pues no comprueba la entrada que llega del método POST. Supongamos que el atacante sabe que -- es el comando SQL para comentario, entonces, todo lo que se introduzca después de los dos guiones no será reconocido por el SQL y se evita automáticamente la comprobación del password, dando acceso total el invasor. Con la siguiente entrada de usuario será:

Juan’--

Se ejecutará la siguiente sentncia:

SELECT count(*)
FROM users
WHERE username = ‘juan’--‘
AND password=’eselmejor’”;

Pero como AND password=… es un comentario no será tomado en cuenta será ejecutado:

SELECT count(*)
FROM users
WHERE username = ‘juan’

Entrando a la cuenta de Juan sin permiso y evitando la comprobación de password.

Veamos que otros posibles abusos pueden ser cometidos con Inyección SQL. Hace búsqueda de fuerza bruta del password del un usuario con una cierta dirección de correo electrónico:

SELECT email, passwd, login_id, full_name
FROM members
WHERE email = 'bob@example.com' AND passwd = 'hello123';


Elimina una tabla de la base de datos:

SELECT email, passwd, login_id, full_name
FROM members
WHERE email = 'x'; DROP TABLE members; --'; -- Boom!

Crea una nueva cuenta papra poder acceder a la base de datos in mayor problema:

SELECT email, passwd, login_id, full_name
FROM members
WHERE email = 'x';
INSERT INTO members ('email','passwd','login_id','full_name')
VALUES ('steve@unixwiz.net','hello','steve','Steve Friedl');--';

Y así se podría continuar hasta que la imaginación lo permita. Pero ahora surge la preunta: ¿Cómo se debió haber programado el script PHP desde el principio para poder evitar estos ataques?

Se debe comprobar la cadena entrante de la siguiente forma:

prepare(‘ SELECT count(*)
FROM users
WHERE username =:username’
AND password=:hash’);

$sql->bindParam( ‘:username’,
$clean[‘username’],
PDO_PARAM_STRING,
32);

$sql->bindParam( ‘:hash’,
$hash($_POST[‘password’]),
PDO_PARAM_STRING,
32);
.......

?>


Referencia:

Rasmus Lerdorf, Kevin Tatroe & Meter MacIntyre. Programming PHP, Segunda edición abril 2006, Estados Unidos ed.: O’Reilly Media.

http://unixwiz.net/techtips/sql-injection.html

http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL