sqlitecmd: acceso a bases de datos SQLite desde línea de comandos
Programando un sistemita en python que utiliza SQLite, me topé con la necesidad de acceder a la base de datos haciendo consultas SQL directas, y no encontré ninguna herramienta que me permita hacerlo. Gracias a la potencia de python, necesité de tan solo un par de horas para crear mi propio acceso por consola a este tipo de base de datos. La mayor parte del tiempo se fue formateando la salida para que se vea como en los clientes mysql =P
Espero que les sea de utilidad, o que al menos sirva de ejemplo de programación en python =)

NOTA: Luego haber programado la herramienta, encontré en la misma página de sqlite que existe una interfaz de línea de comandos similar, pero el formato de la salida es bastante feo...

Tengan en cuenta que no me tomé ni un minuto en optimizar el script y que tampoco lo revisé demasiado... es decir, puede fallar =P

El script requiere un solo parámetro, la dirección del archivo que contiene la base de datos. Luego pueden ejecutar cualquier comando que SQLite les permita. Para salir, simplemente aprieten Ctrl+c

#!/usr/bin/python

######################################################
# Created by: d3m4s1@d0v1v0
# Date: 2010-09-30
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License v2 as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
######################################################

import sys
import os
import sqlite3

import readline

if(len(sys.argv)<2):
print "usage: "+sys.argv[0]+" <database-file>"
quit(-1)

sto_file=sys.argv[1]

print "SQLite command line shell by d3m4s1@d0v1v0"

if(not os.path.exists(sto_file)):
print "database file "+sto_file+" doesn't exists!\nexiting...."
quit(-1)

try:
sqlconn = sqlite3.connect(sto_file)
sqlconn.row_factory = sqlite3.Row
sqlcursor = sqlconn.cursor()
except Exception as detail:
print "something happend!"
print detail
quit(-2)

history = []

while (True):
try:
query = raw_input("> ")

result = sqlcursor.execute(query).fetchall()

c = 0
colsize = []
col_names = []
for col_name in sqlcursor.description:
col_names.append(str(col_name[0]))
colsize.append(len(str(col_name[0])))

for row in result:
c = 0
for cell in row:
if(len(str(cell))>colsize[c]):
colsize[c] = len(str(cell))
c += 1

hyphenrow = ''
for s in colsize:
hyphenrow += "+"+"-"*(s+2)
hyphenrow += "+\n"

c = 0
sys.stdout.write(hyphenrow)
for col in col_names:
sys.stdout.write("| "+col+" "*(colsize[c] - len(col))+" ")
c += 1
sys.stdout.write("|\n")
output = ""
for row in result:
c = 0
output += hyphenrow
for cell in row:
output += "| "+str(cell)+" "*(colsize[c] - len(str(cell)))+" "
c += 1
output += "|\n"
output += hyphenrow
print output
except sqlite3.OperationalError as detail:
print detail
pass
except KeyboardInterrupt:
print "exiting..."
sqlcursor.close()
quit(1)

Ejemplo de uso:
$ sqlite.py crawled_db.dat
> select * from ip_domain LIMIT 3 OFFSET 1
+----------------+-----------------------+
| ip | domain |
+----------------+-----------------------+
| 207.200.74.91 | search.dmoz.org |
+----------------+-----------------------+
| 205.188.101.23 | blog.dmoz.org |
+----------------+-----------------------+
| 207.200.81.151 | report-abuse.dmoz.org |
+----------------+-----------------------+
Listar usuarios, grupos y permisos desde línea de comandos en Windows
Cuando auditamos sistemas Windows Active Directory, necesitamos conocer listados de usuarios, grupos de usuarios y los permisos de cada usuario. Uno puede ver usuarios y grupos logueandose en un Domain Controller y utilizando la herramienta de gestión de usuarios. Los permisos los podemos ver con el clásico click derecho sobre la carpeta.
El problema está en que este mecanismo es muy ineficiente. Supongan que les piden los permisos asociados a 10 carpetas... debemos hacer click derecho sobre cada carpeta. Cómo guardamos esta información? si es con screenshots, con suerte necesitamos hacer dos screenshots por cada carpeta (no entran todos los permisos en un solo screenshot...), si es escribiendo los permisos en un archivo, también es muy ineficiente.
Lo mismo sucede con listar usuarios, listar los grupos de un usuario y listar los usuarios en un grupo. Todas son tareas que hacerlas gráficamente es extremadamente molesto.

Fue así como di (gracias a nuestro administrador de dominio), con el paquete "Resource Kit" para Windows. Este paquete incorpora todas las herramientas que un servidor Windows debería traer, pero que los ratas de MS no incorporaron y vendían aparte (si, el "Resource Kit" es de MS y lo vendían por separado)...
En fin, este set de herramientas es muy útil y permiten administrar el dominio de forma rápida y automatizada desde programitas de consola, volcar información en archivos de texto y varias cosas más.
Como dije en la introducción, me interesa la parte de listar permisos y usuarios, así que describiré cómo hacerlo con la herramienta correspondiente del "Resource Kit".


Listar permisos de un directorio

Para esto utilizamos el programa showacls. showacls muestra los permisos utilizando la siguiente terminología:
A Generic All
R Generic Read
W Generic Write
X Generic Execute
w File Write
fx File Execute
rE Read EA
l List Directory
d Read Data
S Synchronize
r File Read
a File Append
D Delete
rW Write EA
El uso de este programa es el siguiente:
showacls /s /u:domain\user filespec /?
donde:
/s incluye sub-directories.
/u especifica el usuario (y el dominio) del cual se mostrará la información
filespec especifica los archivos y directorios en los cuales el usuario tiene permisos
/? muestra la ayuda
Ej:
showacls \\servidor\C$


Listar miembros de un grupo

En este caso usamos el programa showmbrs. El uso es el siguiente:
showmbrs dominio\grupo o
showmbrs \\dominio\grupo o
showmbrs grupo
Ej:
showmbrs midominio\”Domain Admins”


Listar miembros de grupos locales de una máquina

Aca nos da una mano el programa "local" del paquete "Resource Kit". El uso es el siguiente:
local group_name domain_name | \\server

group_name el nombre del grupo local a listar los miembros
domain_name el nombre del dominio
\\server el nombre del servidor
Ej:
local Administrators \\192.168.1.1


Listar grupos a los que pertenece un usuario

Finalmente utilizando el programa showgrps podemos listar los grupos de un usuario. El uso es el siguiente:
showgrps [/A] dominio\usuario o
showgrps [/A] usuario

/A – checkear todos los dominios confiables
Ej:
showgrps midominio\miusuario


Flexibilidad

Utilizar programas desde consola nos brinda gran flexibilidad. Si bien la consola de Windows es asquerosamente limitada, nos permite funciones básicas que nos ayudan. Por un lado podemos redirigir la salida a archivos al igual que en Linux con el caracter ">". Por ej, podemos guardar en un archivo los permisos de una dada carpeta de la siguiente forma:
showacls \\servidor\C$ > permisos.txt
Además es posible crear scripts que realicen tareas programadas para cierto día. Tal vez listar los usuarios el último día del mes.
Por otra parte, por suerte MS creó una shell más completa que el clásico cmd.exe, llamada PowerShell. Igual no llega a los talones a ninguna de las shells *nix, como bash o ksh, pero bueno, algo es algo.


Trabajo Futuro

Mi idea inicial era utilizar herramientas de GNU/Linux como ldapsearch para obtener esta información, pero desgraciadamente no pude arreglar un problema de binding con el server ldap... seguiré buscando alguna alternativa que me sirva. Voy a probar un poco el paquete python-ldap y ver si puedo programar algo propio.
Si alguno conoce una alternativa GNU/Linux que cubra las necesidades planteadas en el artículo, por favor dejenme un comentario, o escriban en el "muro" de facebook
Acceder dispositivos Cisco desde GNU/Linux con minicom
Cuando necesitamos configurar un dispositivo al cual debemos acceder por una conexión serie, debemos tener un programa que emule una terminal. El clásico ejemplo son los dispositivos Cisco (routers, switchs, access points, etc), para los cuales, si bien muchas veces cuentan con configuración por Web, no hay nada más flexible que el acceso por consola.

La terminal que trae Windows (HyperTerminal) es, increíblemente, bastante buena y fácil de configurar. Pero nosotros utilizamos GNU/Linux y necesitamos una alternativa. Si bien existen alternativas gráficas como gtkterm o cutecom, siempre es conveniente conocer un programa que funcione por consola, y en este caso contamos con minicom. Si no cuentan con minicom, lo pueden instalar con un simple:
# apt-get install minicom
o bien
# yum install minicom
A primera vista minicom es totalmente arcaico y complicado de configurar (a segunda vista también =P), pero una vez que lo configuramos, no necesitamos tocarlo y funciona perfectamente.
Para poder configurar la conexión, necesitamos saber cuál es el dispositivo asociado a nuestro puerto serie. Esto lo podemos ver ejecutando dmesg:
$ dmesg | grep tty
Por si nunca configuraron una conexión a dispositivos Cisco, les comento que tiene las siguientes características:
- 8 bits de datos
- sin paridad
- 1 stop bit
- sin control de flujo
Las opciones de minicom se pueden acceder ejecutando CTRL+A Z (CTRL+A y luego pulsar Z). Las que seguramente les interesarán son:
- O para configurar minicom
- X para salir y resetear
- Q para salir sin resetear la conexión
- C para limpiar la pantalla
Una vez que sabemos qué dispositivo utilizar y las características de la conexión, podemos configurar minicom. Se puede acceder a la configuración de dos formas:
opción 1:
# minicom -s (usar la opción "-c on" si queremos la terminal con colores)
opción 2:
# minicom
CTRL+A Z O (entramos a la opción de configuración desde minicom)
Ya en el modo configuración, debemos ir a la opción "Serial port setup" y realizar los siguientes pasos (la letra indica la opción elegida):
- con A configuramos el path al dispositivo (obtenido con dmesg, puede ser algo como /dev/ttyS0)
- con E entramos a la configuración de la conexión, donde usamos las siguientes letras:
- C para elegir la velocidad de 9600bps
- Q para elegir 8 bits de datos, paridad none y 1 bit de parada. Esto también se puede configurar eligiendo las siguientes opciones por separado:
- L para elegir paridad none
- V para 8 bits
- W para 1 bit de stop
- con F ponemos en "No" el control de flujo por hardware.
Una vez que terminamos, elegir "Save as dfl" para guardar la configuración como default.

Eso es todo. Ahora al enchufar un dispositivo y ejecutar minicom veremos la consola y podremos configurar el equipo. Para salir, apretamos CTRL+A Z Q.


Referencias
- Linux / UNIX minicom Serial Communication Program
- How to connect to Cisco routers using Minicom
Localizar físicamente dispositivos conectados a la red a partir de su IP o MAC
En redes de gran tamaño y con movimiento constante de dispositivos, es complejo saber en qué lugar está conectado cada uno en cada momento. En ocasiones es necesario conocer la ubicación debido a que el dispositivo presenta alguna falla, o bien se está utilizando para realizar tareas indebidas en la red.
Como monitoreador de la red, podemos detectar una IP atacante, y si sabemos dónde está conectada esa máquina, podemos ir a ver quién es.

Por ello creé un procedimiento que permite ubicar dónde está conectado un dispositivo a partir de su dirección IP o MAC. Para lograrlo, debemos tener la red debidamente documentada. Es decir, necesitamos saber cómo es la conexión entre switches y routers (uplinks), y la ubicación física de estos dispositivos.
Si bien el procedimiento está pensado en redes con equipamiento Cisco, debe existir el comando equivalente en otros equipos de red.

Entonces, las herramientas necesarias son:
- Switches con IOS que soporte el comando “show mac-address-table address <dirección>” (o similar).
- Documentación de las conexiones entre switches y routers (i.e. uplinks).
- Documentación de la dirección IP de cada switch/router.
- Documentación de la ubicación física de cada switch/router.
- Documentación de las bocas de red patcheadas a cada switch.
Si se posee la IP, primero es necesario conocer la dirección MAC de la placa de red del dispositivo. Suponiendo que la IP es 192.168.1.10, la MAC se puede obtener haciendo un ping y luego viendo la cache arp con el comando arp (tanto en Windows como en Linux es igual):
$ ping 192.168.1.10
$ arp -a
Con esto se obtiene la dirección MAC asociada, por ejemplo: 00:11:22:33:44:55.
sugerencia: en GNU/Linux se puede utilizar el comando $ arping <IP>
Una vez obtenida la dirección MAC, el procedimiento es el siguiente:
1. Conectarse (ssh o telnet, dependiendo que tipo de conexión acepte) a alguno de los switches de la red. Si se sospecha en que switch puede estar conectado el dispositivo, comenzar con el mismo para ahorrar tiempo de búsqueda. Igualmente el mecanismo funciona aunque se comience desde cualquier otro switch.

2. Ejecutar el comando:
switch #show mac-address-table address 0011.2233.4455
para obtener en que port del switch se encuentra el dispositivo.

3. Utilizar el documento de uplinks para reconocer si el port es un uplink o una conexión directa a una máquina. Si el port no es un uplink ya obtuvimos el switch y port que buscábamos, ir a 5. Sino, ir a 4.

4. Si el port es un uplink, a partir del documento de uplinks y de IPs, obtener la dirección IP del switch al que está conectado. Conectarse a dicho switch y repetir desde el paso 2.

5. Mirar el documento con el mapeo de links -> localización física para saber dónde se encuentra el switch.

6. Ver a que boca de red se encuentra patcheado el port del switch.

7. A partir de la documentación de las bocas de red, obtener en qué lugar del edificio se encuentra el puesto conectado al port del switch.
De esta forma podemos encontrar rápidamente el dispositivo que buscamos. Imaginen que esto en redes con muchos puestos, muchos switches y routers, poder determinar donde se encuentra un dispositivo a partir de una IP es extremadamente útil.