Cómo ejecutar comandos externos desde Perl

Si empleas GNU/Linux para trabajar, saber Perl y Python suele ser interesante ya que te permite crear pequeños script que interaccione muy directamente con el sistema. Además de todo eso, Perl es un gran lenguaje de programación, permite realizar numerosas tareas en pocas líneas y por lo general es simple de manejar y comprender.
Hoy tuve la necesidad, en un script perl de procesamiento de correos, de ejecutar comandos externos y tocó realizar una búsqueda en Google de cómo realizar lo que me interesaba. Yo necesitaba ejecutar un comando y obtener la salida del mismo en una variable. Finalmente lo realicé con backticks, pero aproveché para recordar otros métodos de ejecución de comandos que voy a continuación a compartir con vosotros.
  • system
    Se emplea para ejecutar comandos del sistema en los que no interesa capturar la salida del mismo.
    system acepta el paso de un comando con argumentos directamente, así como el paso de variables como argumentos a la hora de ejecución. Aunque no captura la salida del comando, sí permite saber si éste se ejecutó correctamente o no (variable $?) y en caso de fallo, saber el error devuelto (variable $!).
    ...
    system($command, @args);
    if ($?) {
       print "command failed: $!\n";
    }
    ...
    
  • exec
    Ejecuta el comando especificado, pero a diferencia de system, exec nunca devuelve al programa de llamada, excepto que la llamada falle por que el comando no exista.
    Al igual que system, los argumentos pueden ser un array.
    ...
    if (($pid = fork()) == 0) {
       exec($command, @args);
    }
    waitpid($pid, 0);
    ...
    
  • open
    Se emplea si quieres que tu script importe o exporte datos externos mediante un pipe. Existen dos formas de ejecutarlo,
    • open("command | ")
      Para capturar datos desde la ejecución de un comando.
    • open(" | command")
      Para enviar datos a un programa externo desde Perl.
    ...
    open (DST, '-|', $pdftk, @pdf, 'cat', 'output', $final);
    close DST;
    ...
    
  • backticks
    Hay que emplear este método en caso de que deseemos capturar a una variable la ejecución de un comando del sistema. En método de funcionamiento es similar al mismo empleo en bash. Al igual en systema, $? almacena el estado de salida del comando.
    ...
    $random = `< /dev/urandom tr -dc A-Za-z0-9_.,@ | head -c12; echo n`;
    ...
    
Leer más

sudo sin terminal

¿Empleas sudo habitualmente para las tareas en tus equipos? Cada vez hay más gente que lo usa, especialmente en sistemas compartidas en los que el administrador siempre intenta, o debería de intentar, restringir al máximo los permisos que ofrece a cada usuario. Pues bien, dentro de este modelo de restricción de permisos, puede darse el caso de que desde un programa que hayamos ejecutado o desde un script que hayamos lanzado nos aparezca el siguiente mensaje,



root : sorry, you must have a tty to run sudo ; TTY=unknown ; PWD=/home/javier ; USER=javier ; COMMAND=/usr/local/bin/test
Este mensaje de error aparece por que estamos intentando lanzar un sudo desde otro proceso que no tiene acceso a la shell. Puesto que sudo por defecto quiere acceso a la shell, si no deseamos tener este tipo de fallos, habrá que editar la configuración (/etc/sudoers) y eliminar la línea,
...
Defaults    requiretty
...
Al eliminar esta línea, ya se permite la ejecución de comandos sudo sin la necesidad de un terminal.
Si el equipo es compartido quizás no sea tan buena idea sacar esta línea, así que mejor sólo permitirle el uso de sudo sin tty al usuario que lo necesite, tal que así.
Defaults:javier   !requiretty

La entrada sudo sin terminal la puede leer en Puppet Linux.
Leer más

SEO: Optimización de entradas

No soy un experto ni mucho menos en técnicas SEO, pero dicen que la lectura hace al hombre completo y aprovechando que estoy leyendo en ratos muertos libros e información sobre técnicas SEO, quiero seguir compartiéndola con vosotros. Dicha información no es novedosa ni nada que no se haya escrito antes, ya que realmente estas técnicas ya está escritas y perfectamente documentadas, especialmente en todo lo referente a Blogger y entradas en Blog's. Sin embargo, sí puede resultar de cierto interés para algunos refrescarlas y con ello conseguir más visitas a sus entradas y ganar un par de posiciones en los buscadores.
Antes de seguir, hay que dejar claro que nunca vas a encontrar una fórmula mágica que haga que Google te coloque en la primera posición en una búsqueda. Eso depende de muchas variables, algunas sí controlables, como las que ya vimos o las que vamos a ver a continuación y otras que establece el motor de búsqueda y que no son directamente controlables.
Cuando escribimos una entrada o un artículo que se vaya a publicar en la red, algunos de los factores que sí están en nuestras manos para poder mejorar su posicionamiento son,
  1. Palabras clave
    Se entiende por palabras clave aquellas palabras o frases que cualquier persona busca en la red a la hora de querer acceder a la información. Por lo tanto, cuando escribamos algo tenemos que centrarnos y hacer hincapié en dichas palabras, para que los buscadores las indexen y tengan relevancia. Algo muy importante sobre el uso de esta palabras clave es el no abuso de las mismas. Esto quiere decir que no podemos, ni debemos escribirlas continuamente sino, en vez de favorecer lo que hará será desfavorecer y bajar la prioridad del contenido.
    Así que ya sabéis, escribir inteligentemente, pero sin abusar.
  2. Uso de sinónimos
    Creo que esta parte ya no tiene ni que explicarse. Si en la vida real o en cualquier redacción siempre nos aconsejaban escribir con sinónimos  lo mismo es aplicándolo a la red. Cada posible visitante tiene su forma de expresarse y de buscar, por lo tanto, el empleo de sinónimos para definir una misma cosa es útil y necesario. A mayores, el empleo de sinónimos da una mayor fortaleza al texto escrito, lo que a la vez ayuda en su posicionamiento.
  3. Negritas y cursivas
    Las frases o palabras clave deben resaltarse para que el lector centre su mirada sobre ellas. De la misma forma que en un texto escrito esto se hace de forma directa, un buscador también es capaz de realizarlo. Aunque en la mayoría de las webs actuales, cada vez más se emplean CSS's para dar formato, para que un buscador tenga en cuentas las negritas y cursivas, se deben emplear las etiquetas HTML, <b>, <strong> y <i>. Es importante no abusar con el empleo de formato en el texto para no dejarlo muy sobrecargado y las palabras más destacadas emplear <strong> para establecer la negrita y en el resto de los casos, <b>.
  4. Ortografía y expresión escrita
    Si es importante el empleo de sinónimos, más todavía una buena ortografía. Es muy importante no escribir con faltas ni emplear palabras coloquiales. Aunque puede ser que para la entrada quede bonito, para el posicionamiento no y para el lector que lo va a consumir, menos.
    En Internet el uso de mayúsculas tiene un significado similar a gritar, así que no escribas una entrada en mayúsculas!
  5. Genera temas nuevos
    Aunque una de las cosas que más influye a la hora de posicionar un Blog es la frecuencia de actualización es tanto o más importante generar nuevo contenido y no únicamente copiar y copiar contenido ya generado. Aunque escribas de un mismo tema, hazlo por ti mismo. Consulta, investiga, averigua toda la información que necesites y luego transfórmala con tus palabras en un artículo.

La entrada SEO: Optimización de entradas la puede leer en Puppet Linux.
Leer más

MySQL, escalando en BlackHole

En anteriores entradas ya vimos cómo montar un clúster MySQL Master-Slave y también de cómo hacerlo para un Master-Master. En ambos casos la solución era siempre la misma y se comprobó que la segunda opción (máster-máster), no era más que la primera en ambos sentidos.
Hoy vamos a ver una solución más óptima al escalado de un sistema MySQL. Esta opción que veremos suele ser más desconocida, aunque viene perfectamente implementada en el motor de base de datos y permite realizar un escalado master-multi-slave de forma sencilla.
En la mayoría de los casos los sistemas necesitan escalar para dar soporte a múltiples lecturas y no tanto en los que a escrituras se refiere. Esto significa que por cada escritura, a lo mejor tenemos, 500 lecturas. Es decir, la gente consume más de lo que aporta. Obviamente estamos hablando en términos relativos y por supuesto, cada aplicación es un mundo. Sin embargo, si vuestro caso se ajusta al aquí descrito, lo más probable es que vayáis a necesitar varios nodos de lectura. Para ello, MySQL ya aporta el escalado Máster - Slave. y podemos poner, por ejemplo, los Slave en modo sólo lectura. Ahora bien, si pensamos lo que estamos diciendo, vamos a tener un equipo que hará de Máster y del que se replicarán los datos a N Slave's. Según la forma tradicional de trabajo de MySQL, el Máster escribirá en sus tablas los datos, luego en el binary log y luego estos datos serán replicados a los equipos Slave's. Pero si queremos tener un amplio escalado, ¿por qué necesitamos escribir los datos en el Máster? Este tiempo de acceso a disco es innecesario. Si no lo vamos a emplear, lo mejor sería suprimirlo.
Para intentar dar solución a este problema, vamos a hacer uso de la engine de MySQL, BlackHole. Sí, efectivamente, si lo traducimos, agujero negro. Antes de seguir  vamos a ver cómo trabaja en un pequeño ejemplo práctico.
mysql> CREATE TABLE `test` (
    -> `id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
    -> `nombre` text NOT NULL,
    -> PRIMARY KEY (`id`)
    -> ) ENGINE=BLACKHOLE;
Ya tenemos la tabla creada. Ahora metamos algunas tuplas...
mysql> INSERT INTO test (nombre) VALUES ('javier');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO test (nombre) VALUES ('puppet');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO test (nombre) VALUES ('linux');
Query OK, 1 row affected (0.00 sec)
Las inserciones se realizaron correctamente. Vamos a ver ahora al leer qué obtenemos...
mysql> SELECT * FROM test;
Empty set (0.00 sec)
Lo ocurrido es realmente lo esperado, la engine BlackHole no guarda datos.
Pero entonces, ¿en qué nos puede ayudar BlackHole a la hora de escalar una base de datos?
Pues muy simple, esta nueva engine no escribe los datos en las tablas de MySQL, pero sí lo hace en el binary log, que es justo el log que MySQL emplea para realizar la sincronización de los datos con los esclavos. Por lo tanto, empleando BlackHole podríamos terminar con una arquitectura como la que sigue.
mysql backhole escalate system
MySQL BackHole system escalate
En el equipo máster  que sólo se encargará de realizar las escrituras, todas las tablas serán de tipo BlackHole y tendrá como esclavos al resto de nodos, sobre los que sí existirán realmente los datos y sobre los que se realizarán todas las lecturas.
En el ejemplo anterior, las tres tuplas no se habían escrito en el máster y todo apuntaba a que se habían perdido. Ahora que la nuevo engine se ha explicado, vamos a ver como realmente las tuplas sí están escritas en los esclavos.
slave> select * from test;
+----+--------+
| id | nombre |
+----+--------+
|  1 | javier |
|  2 | puppet |
|  3 | linux  |
+----+--------+
3 rows in set (0.00 sec)
Así que ya sabéis, si realmente os interesa escalar una base de datos de un máster a varios esclavos y las escrituras las tenéis controladas, la opción de poner las tablas del maestro de tipo agujero negro es muy interesante ya que nos permitirá tener un máster más liviano y dejar el trabajo y el proceso de almacenar datos a los esclavos, que son los que realmente lo tienen que hacer.

La entrada, MySQL, BlackHole para escalar la puede leer en Puppet Linux.
Leer más

MSM760 Controller, automatic WiFi key

En post anteriores (hpenterasys) mostramos la forma de ejecutar comandos en sistemas que no admiten una ejecución continuada, sino que van pidiendo datos poco a poco, como puede ser la shell de router's o switch's. Hoy quiero dejar disponible un pequeño script que hice hace tiempo y que trata sobre cómo cambiar automáticamente la contraseña en un equipos HP MSM760. Este equipo es un controlador WiFi que tiene infinidad de configuraciones. Dispone de un interfaz web para administrarlo o como buen equipo con Linux que es, una pequeña shell de control. Aunque es muy limitada, por ejemplo el cambio de claves de la WiFi y la sincronización de los AP's es sencillo de automatizar. Os dejo a continuación el código.
#!/usr/bin/expect -f

set KEY [lindex $argv 0]

spawn ssh admin@192.168.1.2
match_max 100000
expect -exact "Password:"
send -- "mi_passwd\n"
expect -- "CLI>"
send "enable\n"
expect -- "CLI#"
send "config\n"
expect -- "#"
send "virtual ap \"WiFi\"\n"
expect -- "#"
send "encryption key 1 $KEY\n"
expect -- "#"
send "end\n"
expect -- "#"
send "end\n"
expect -- "#"
send "controlled network group \"Listado APs\"\n"
expect -- "#"
send "execute action synchronize\n"
expect -- "#"
send "end\n"
expect -- "#"
send "end\n"
expect -- ">"
send "quit\n"
Para aquellos a los que le interese, pueden consultar más datos del manual del equipo.
Una vez que tengamos el script, lo podemos colocar, por ejemplo en /usr/local/sbin/change_pass y luego, cada vez que necesitemos cambiar la contraseña de nuestra WiFi, únicamente habrá que llamarlo, pasándole como parámetro la nueva clave que deseemos.
shell> /usr/local/sbin/change_pass 12345
En caso de que nos interese cambiarla diariamente, podremos programarlo desde cron añadiendo la siguiente línea,
... PASS=`< /dev/urandom tr -dc A-Za-z| head -c4; echo n`; /usr/local/sbin/change_pass $PASS

La entrada, MSM760 Controller, automatic WiFi key la puede leer en Puppet Linux.
Leer más

Impidiendo la ejecución de varias instancias del mismo proceso

Fijo que muchos de vosotros alguna vez se vio con la necesidad de controlar que un programa que se ejecute automáticamente, por ejemplo desde cron, lo haga sólo si no hay otra instancia del mismo en ejecución. Dicho de otra forma, si ya se lanzó el script y todavía no ha terminado, que no se vuelva a lanzar. Aunque esto parece trivial, impedir que un script se ejecute dos veces puede llegar a ser complicado y nos obliga a tener partes del código similares a éstas,




#!/bin/bash

FILE_SYNC=/var/run/async.lock
if [ -f $FILE_SYNC ]; then
   exit
else
   touch $FILE_SYNC
   ...
   rm -f $FILE_SYNC
fi
Crear un fichero de control de ejecución, es una de las soluciones más habitualmente empleadas, pero este truco es un arma peligrosa ya que si en alguna parte del código termina la ejecución, o se aborta el programa, y el fichero no se borra el script no se volverá a lanzar, ya que para él seguirá un hermano en ejecución.
Para solucionar este tipo de inconvenientes y hacer el código más legible y con menos comprobaciones tenemos la utilidad flockflock es una herramienta que se encarga por nosotros de crear y manejar el fichero de bloqueo de ejecución. Y por ello, si la ejecución de un script está o no activa, bloqueará el fichero de control. Si dicho fichero existe no se permitirá otra ejecución. En caso contrario sí.
Como la mejor forma es verlo con un ejemplo,
5 * * * * root /usr/local/sbin/act.sh
Este es el típico script que se ejecuta desde cron cada 5 minutos, pero nada impide, a nivel del planificador, que haya varias instancias del mismo al mismo tiempo. Si queremos controlar eso, tendrá que ser empleando el truco de añadir código de control. Ahora vamos a lanzar el mismo script, pero controlado.
5 * * * * root /usr/bin/flock -w 0 /tmp/cron.lock /usr/local/sbin/act.sh
En este caso, la primera ejecución creará un fichero, /tmp/cron.lock, que siempre estará presente hasta que termine o alguien la aborte. Cuando finalice, la siguiente ejecución hará lo mismo y nunca habrá dos ejecuciones simultáneas. El código del script será únicamente para hacer el procesado de datos que tenga que hacer, pero no necesitará controlar si hay un hermano ejecutándose.
El contenido del fichero de bloqueo, por cierto, será similar al que sigue,
shell> fuser -v /tmp/cron.lock
             USER   PID  ACCESS COMMAND
cron.lock:   root   7836 f....  flock
             root   7837 f....  php

La entrada Impidiendo la ejecución de varias instancias del mismo proceso la puedes leer en Puppet Linux.
Leer más

Prevenir XSS en PHP

Realizar un ataque XSS (Cross Site Scripting) aprovechando alguna vulnerabilidad no suele ser excesivamente complicado. Lo más complejo del proceso es llegar a encontrar la variable de entrada no filtrada, que permite la ejecución del código javascript. Puesto que nuestro interés es evitar que nuestra web se vea comprometida por un ataque XSS tenemos siempre que controlar las variables de entrada que obtenemos.
Si empleamos frameworks como Joomla, Drupal, etc. generalmente ya tienen sus módulos de comprobación que intentan, en la medida de lo posible, filtrar los posibles valores de entrada. En caso de que optes por programar en PHP "a pelo", lo mejor es que conozcas, y bien, la clase PHP Input Filter. Esta clase es la que se encarga de filtrar, y por lo tanto limpiar, todo el código malintencionado que alguien pueda meter en un formulario de entrada.
Su uso es muy sencillo, y únicamente tendremos que incluirla en nuestro código PHP. Una vez la tengamos incluida, podremos crear un InputFilter, que será el encargado de limpiar la variable del formulario y dejar los valores correctos en la variable PHP empleada. Un ejemplo rápido,
require_once("class.inputfilter.php");

$filter = new InputFilter();
$var = $filter->process($_POST['variable']);
La idea de emplear esta clase PHP es simplemente que una entrada como esta,
<script>window.location = "http://www.google.com";</script>
Tenga un valor real así,
resultado: window.location = "http://www.google.com";
Por defecto el InputFilter filtra todo tipo de datos de entrada, pero podemos indicarle que determinadas etiquetas puedan pasar, como es el caso de a o href. Para ello, cuando creamos la nueva clase,
...
$filter = new InputFilter(array('a'), array('href'));
...

La entrada, Prevenir XSS en PHP la puedes leer en Puppet Linux.
Leer más

rats, auditando código fuente

rats es una de esas utilidades que no se suelen emplear y que puedan dar muy buenos resultados en poco tiempo a la hora de programar. La verdad es que yo no conocía este tipo de herramientas (debe ser por la falta de costumbre de programar), pero son muy útiles, ya que permiten detectar fallos triviales en el código, de forma automática. Los típicos con las variables no inicializadas, cast's entre tipos de datos diferentes sin límites, etc.
rats tiene soporte para 5 lenguajes de programación, c, perl, ruby, python y php, con una amplia base de datos de fallos comunes, especialmente c, con 334 entradas. La forma de funcionar típica, es indicarle el tipo de lenguaje de programación (sino lo autodetecta) y los ficheros de entrada. También se le puede decir que saque la salida en formato xml o html. Por defecto, los fallos si no se indica nada, los saca desde la consola.
Al termina de analizar, ofrece unos resultados y el tiempo que tardó en procesar todos los ficheros. Los resultados los agrupo por el tipo de vulnerabilidad que tiene (alta, medio o baja), indicando las líneas en las que se encuentra el fallo, así como información de mismo.
Un ejemplo de ejecución puede ser el que sigue, con sus correspondientes resultados.
shell> rats --language c --input *.c --html > salida.html
Y los resultados obtenidos (copiado del formato html),
------------
Entries in perl database: 33
Entries in ruby database: 46
Entries in python database: 62
Entries in c database: 334
Entries in php database: 55

Analyzing checks_agent.c
Analyzing checks_aggregate.c
Analyzing checks_calculated.c
Analyzing checks_db.c
Analyzing checks_external.c
Analyzing checks_internal.c
Analyzing checks_ipmi.c
Analyzing checks_simple.c
Analyzing checks_snmp.c
Analyzing checks_ssh.c
Analyzing checks_telnet.c
Analyzing poller.c

RATS results

Severity: High
Issue: fixed size global buffer
Extra care should be taken to ensure that character arrays that are allocated on the stack are used safely. They are prime targets for buffer overflow attacks.
    File: checks_agent.c
    Lines: 49
    File: checks_aggregate.c
    Lines: 297
    File: checks_calculated.c
    Lines: 311
    File: checks_internal.c
    Lines: 46 47
    File: checks_ipmi.c
    Lines: 772 862
    File: checks_simple.c
    Lines: 28 29 30 31
    File: checks_snmp.c
    Lines: 248 468 838 839 840 841 842 843
    File: checks_ssh.c
    Lines: 86 343
    File: checks_telnet.c
    Lines: 319 394 516
    File: poller.c
    Lines: 347 447
Severity: Medium
Issue: read
Check buffer boundaries if calling this function in a loop and make sure you are not in danger of writing past the allocated space.
    File: checks_telnet.c
    Lines: 72

Inputs detected at the following points

Total lines analyzed: 5449
Total time 0.007437 seconds
732687 lines per second
------------
La verdad es que es una herramienta interesante si el lenguaje de programación está soportado para controlar los tipos de fallos más comúnmente conocidos y poder corregirlos. Sin duda, ayudará a mejorar la seguridad del código final. Por supuesto, al ser código libre, las bases de datos de vulnerabilidades se pueden seguir mejorando, así como emplear otras conocidas y compatibles (opción --database).
Leer más

Zabbix, not browser check

En la versión 2.0 de Zabbix, una de las cosas que más llamó la atención es que comenzaron a eliminar el soporte a ciertos navegadores. Bueno, más que a navegadores, a versiones de navegadores y cuando se accede al frontend Zabbix, comprueba la versión del navegador que se está empleando. En caso de que no esté entre las soportadas, nos redirige a una página para actualizar la versión del navegador. Aunque puede darse el caso de que lo que detecte no sea lo correcto, por ejemplo, si estás empleando IE-10.
Zabbix warning navigation
Zabbix warning
Si no os interesa esta redirección, lo mejor es optar por sacársela y para ello, únicamente hay que editar el fichero js/browsers.js y comentar las últimas líneas, tal que así.
...
/*if (document.cookie.indexOf('browserwarning_ignore') < 0) {
   if (IE6 || IE7) {
      window.location.replace('browserwarning.php');
   }
}*/
Leer más

Cómo clonar discos en VirtualBox

Este post va dedicado a los amantes de VirtualBox, y en especial a aquellos que tienen que duplicar o exportar máquinas que ya tienen listas en sus equipos.
El problema viene originado cuando copias directamente el disco de una máquina y únicamente le cambias el nombre. Si haces esto, obtendrás un maravilloso error muy similar a éste cuando intentes arrancar la nueva máquina.




Cannot register the hard disk 'debian.vdi' with UUID {b02159ec-1596-b951-4ffc-49c99f25306e} because a hard disk 'debian.vdi' with UUID {b02159ec-1596-b951-4ffc-49c99f25306e} already exists in the media registry...
Básicamente, como podéis observar os está diciendo que el disco con el UUID XXX ya existe y por lo tanto no lo puede volver a usar. Desde hace tiempo, en GNU/Linux los discos se identifican por el UUID, un "número de serie" que garantiza que un disco va a ser único siempre (más o menos...).
Así que ya sabéis, si necesitáis duplicar el disco de una de vuestras máquinas, hacerlo directamente con VBoxManage y la opción de clonado que tiene,
shell> VBoxManage clonehd vuln.vdi debian.vdi
Oracle VM VirtualBox Command Line Management Interface Version 3.2.10_OSE
(C) 2005-2010 Oracle Corporation
All rights reserved.

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone hard disk created in format 'VDI'.
UUID: edc388a1-ba0c-4d7b-9d53-895aca643829
Esto creará una copia del disco, pero le cambiará el UUID para evitar tener los problemas anteriormente comentados.

La entrada Cómo clonar discos en VirtualBox la puedes leer en Puppet Linux.
Leer más

Control de volumen desde consola

Desde hace algún tiempo, aquellos usuarios de GNU/Linux que estábamos acostumbrados a emplear aumix como software para controlar el volumen desde línea de comandos hemos llevado un gran chasco, ya que ha dejado de estar incluido. Ahora, por lo menos en sistemas Debian/Ubuntu se emplea amixer, que básicamente es lo mismo, pero cambiado de nombre. Como se puede leer en la página man, amixer es un mezclador de sonido para ALSA y como tal también nos va a permitir controlar el volumen de nuestro sistema desde línea de comandos. Así que vamos a ver cómo configurar el teclado para que pueda subir o bajar volumen con las teclas correspondientes.
En mi caso empleo XFCE, por lo que la configuración del teclado se hará como sigue, pero lo importante del artículo son los comandos a ejecutar. Para subir volumen,
shell> amixer sset Master 5%+
Y para bajarlo,
shell> amixer sset Master 5%-
Como podéis ver, el funcionamiento es muy simple, únicamente ponemos el porcentaje que deseamos subir o bajar y un + o -, en función de si nos interesa aumentarlo o disminuirlo.
Si esto lo llevamos al escritorio, en XFCE, nos iríamos a Configuración/ Teclado y creamos ahí dos nuevos atajos de teclado. Cómo hacerlo ya lo explicamos aquí.
amixer xfce volume control
amixer - XFCE integration

Leer más

Skipping the data of table mysql.event

Recientemente realicé la actualización de los servidores de MySQL/Percona a la última versión estable en Debian. Concretamente ahora tengo la versión 5.5.30 de MySQL. Como es lógico, antes tenía un pequeño script que se encargaba de realizar periódicamente un dump de las bases de datos para poder almacenarlas en backup. Funcionaba perfectamente. Tras la actualización, descubro lo que parece un bug, y todo apunta a ello. Al tratar de hacer un dump de la base de datos mysql, obtengo un warning, no importante, pero sí molesto.


shell> mysqldump -u root -p'passwd' -B mysql > /tmp/mysql.sql
-- Warning: Skipping the data of table mysql.event.
Specify the --events option explicitly.
Y la versión actual de MySQL,
shell> mysql -V
mysql  Ver 14.14 Distrib 5.5.30, for Linux (x86_64) using readline 5.1
La solución adoptada fue indicarle al mysqldump que ignore la tabla event de la base de datos mysql y con eso ya sacamos el warning.
shell> mysqldump -u root -p'passwd' --ignore-table=mysql.event -B mysql > /tmp/mysql.sql
Otra posible solución si deseamos tener copia también de esa tabla es indicar en el proceso del dump que deseamos obtener la tabla events, tal como hacía antes, por defecto. Para ello,
shell> mysqldump -u root -p'passwd' --events -B mysql > /tmp/mysql.sql
Este fallo no sólo es cosa de Debian, sino que sucede en todas las distribuciones que actualizaron la versión de MySQL y está considerado un bug. Se puede leer más acerca de él en bugzilla.redhat.com y en bugs.mysql.com.

La entrada Skipping the data of table mysql.event la puedes leer en Puppet Linux.
Leer más

Zabbix, control de temperatura

La mayoría de los equipos traen sensores de temperatura que son perfectamente accesibles por el kernel. Estos sensores nos marcan la temperatura de determinadas partes del equipo, así como en algunos casos, la temperatura externa de los mismos. Los valores que estos sensores envían los vamos a monitorizar desde Zabbix, para tener controlada la temperatura y actuar en caso de que ésta aumente.
Para hacer uso de los sensores de temperatura, emplearemos el paquete sensord, el cual devuelve las temperaturas de los sensores (si están soportados), y que luego mandaremos directamente a Zabbix.
shell> apt-get install sensord
Tras la instalación del paquete, lo configuramos con sensors-detect, por si no los detectó automáticamente. Luego con el comando sensors ya podemos visualizar lo que nos devuelve.
shell> sensors
i5k_amb-isa-0000
Adapter: ISA adapter
Ch. 0 DIMM 0: +49.5°C  (low  = +105.0°C, high = +124.0°C)  
Ch. 1 DIMM 0: +50.5°C  (low  = +105.0°C, high = +124.0°C)  
Ch. 2 DIMM 0: +48.0°C  (low  = +105.0°C, high = +124.0°C)  
Ch. 3 DIMM 0: +46.0°C  (low  = +105.0°C, high = +124.0°C) 
En mi caso, tengo 4 sensores en el equipos. Lo que representa cada sensor ya depende del equipo. Para saberlo, lo mejor es mirar el manual de la placa. Lo que aquí nos interesa es simplemente sacar esos datos. Sólo para no dar lugar a equivocaciones, ejecutando este mismo comando en otro equipo, la salida es un poco diferente,
shell> sensors
coretemp-isa-0000
Adapter: ISA adapter
Core 0:       +37.0 C  (high = +87.0 C, crit = +97.0 C)
Core 1:       +34.0 C  (high = +87.0 C, crit = +97.0 C)
Core 2:       +35.0 C  (high = +87.0 C, crit = +97.0 C)
Core 3:       +33.0 C  (high = +87.0 C, crit = +97.0 C)
Como podéis observar, la salida depende mucho del fabricante de la placa, por lo que el comando a ejecutar para obtener la temperatura solamente lo tendréis que adaptar.
Para hacerlo editamos el fichero de configuración del agente Zabbix (/etc/zabbix/zabbix_agentd.conf) y creamos una nueva key personalizada, dejándola tal y como así.
UserParameter=system.temp[*], sensors | awk '/^Ch. $1/ {print substr($$5,2,4);}'
En el caso de la segunda salida, sería el mismo comando, pero un poco cambiado,
UserParameter=system.temp[*], sensors | awk '/^Core $1/ {print substr($$3,2,4);}'
Como no sabemos la cantidad de sensores que vamos a tener por equipo, lo mejor es optar por una única key parametrizada. En este caso, $1 será el sensor detectado (0, 1, etc). Por cierto, si ejecutamos el comando en una shell, el valor que nos devuelve es la temperatura actual de ese sensor. En caso de que el resultado no sea como el que sigue, tendréis que adaptar vuestra expresión awk.
shell> sensors  |  awk '/^Ch. 0/ {print substr($5,2,4);}'
49.5
Llegados aquí ya sólo queda configurar los nuevos item's en Zabbix. Tendríamos que configurar un item por cada sensor que nos interese controlar. La configuración es tal como sigue.
New key for temperature control
Lógicamente, también nos interesa tener alertas que nos avisen de que la temperatura ha subido en el equipo más de lo que debiera. Este tipo de alertas sirven para controlar el equipo y a la vez, para controlar la climatización del CPD, por ejemplo. Puesto que los item's son de tipo numérico, la expresión queda muy sencilla. En mi caso por ejemplo, me interesa que si la temperatura de un sensor pasa de 55 °C me alerte. El trigger,
Name: Temperature control fail
Expression: {Template_sensors:system.temp[0].last(0)}>55 |
            {Template_sensors:system.temp[1].last(0)}>55 |
            {Template_sensors:system.temp[2].last(0)}>55 |
            {Template_sensors:system.temp[3].last(0)}>55
Severity: Average
Enabled: True

La entrada Zabbix, control de temperatura la puedes leer en Puppet Linux.
Leer más

Ejecución de comandos remotos en Zabbix

Zabbix es una herramienta de monitorización excelente que permite saber el estado de nuestras máquinas y en función del mismo alertarnos e incluso ejecutar por sí mismo comandos remotos. En caso de que tengamos una máquina con tendencia a que, por ejemplo, Apache, se quede colgado y no responda, podemos hacer que Zabbix ejecute automáticamente cuando esto pasa un restart del servicio. Vamos a ver en este post cómo permitir que Zabbix ejecute comandos en equipos remotos.
Lo primero que necesitamos es editar el fichero de configuración del agente (/etc/zabbix/zabbix_agentd.conf) y habilitar que permita la ejecución de comandos.
EnableRemoteCommands=1
Por defecto, está deshabilitada dicha funcionalidad, así que habilitamos y simplemente hacemos un restart del servicio.
Una vez ya tenemos esto permitido, tenemos que tener en cuenta que en entornos habituales, el agente Zabbix se ejecuta con un usuario sin privilegios (zabbix), por lo tanto no puede hacer todo lo que probablemente queramos. Sí podrá crear un fichero en /tmp, pero no podrá iniciar un servicio, por ejemplo. En este caso, hay dos opciones, ejecutar zabbix-agent como usuario root, lo cual no es aconsejable, o sino incluir en sudo al usuario zabbix con los comandos que nos interese. La segunda opción, más restrictiva, es la mejor de cara a la seguridad.
Entonces, con el paquete sudo instalado, agregamos un nuevo permiso para el usuario zabbix de tal forma que podamos ejecutar lo que nos interese. Siguiendo el ejemplo, reiniciar el servidor Apache. Para ello agregamos la siguiente línea.
zabbix ALL=(ALL) NOPASSWD: service apache2 restart
O en caso de que queramos poder ejecutar todo tipo de comandos sin filtrar, también se podría poner esta línea,
zabbix ALL=NOPASSWD: ALL
Zabbix remote command
Zabbix remote command
Ahora ya tenemos habilitada la ejecución de comandos remotos y también tenemos permisos para hacerlo. Lo único que queda, es establecer la acción que tenga que suceder para ejecutar el comando. Para ello vamos a Configuración/ Acciones y creamos una nueva acción. La parte de Acción y de Condición es la de siempre, como si quisiéramos que nos alertase por e-mail de un error. La parte que cambia es la de operaciones. Concretamente el tipo de operación, que tenemos que ponerlo en "Comando remoto".
En la imagen de la derecha se muestran las partes más esenciales a la hora de configurar una nueva condición para la ejecución del comando. Aunque lo lógico es que un comando se ejecute únicamente cuando hay un fallo en el equipo y no cuando éste se recupera de dicho fallo. Es decir, reiniciaremos el servicio cuando aparezca el "PROBLEM", pero no con el "OK". Puede darse el caso de que tenga que pasar algo de cada vez. En ese caso, simplemente se ejecuta sin condición de estado.
Como podéis observar configurar una acción para que se ejecute un comando remoto no es algo demasiado complicado y lo único a tener en cuenta es la lógica, al igual que para el envío de notificaciones al correo o a jabber.

La entrada Ejecución de comandos remotos en Zabbix la puedes leer en Puppet Linux.
Leer más

Bloquear tráfico P2P desde IPTables

Puede que en nuestra red no nos interese tener tráfico P2P, por motivos de rendimiento de la misma o simplemente por que es una red de empresa, en la que la gente debería de estar trabajando y no descargando cosas. Si bien es cierto que el P2P hoy en día se emplea para muchas cosas, puede darse el caso de que nos interese filtrarlo. En ese caso, vamos a ver cómo bloquear el tráfico con IPTables, algo que no suele ser trivial en la mayoría de los casos.
Para poder llevar a cabo esta tarea, vamos a hacer uso de xtables-addons, una pequeña extensión para IPTables que nos ayudará de forma efectiva a realizar la tarea. Algunas de estas extensiones todavía no fueron aprobadas para entrar a forma parte del kernel, otras quizás nunca lo serán. A nosotros nos interesa concretamente el módulo ipp2p (xt_ipp2p), que el es que facilita el filtrado del tráfico P2P.
Puesto que partimos de un sistema Debian, existe un paquete disponible en los repositorios que facilita la instalación de las xtables. También tenemos disponible el paquete con el código fuente, para poder compilarlo, en caso de que nos interesase. Lo primero, por lo tanto, instalar el software necesario.
shell> apt-get install xtables-addons-common
Al finalizar la instalación, simplemente simplemente tendremos que ver que estén correctamente cargadas y sean funcionales. Para ello,
shell> iptables -m ipp2p --help
...
ipp2p v0.10 match options:
  --edk    [tcp,udp]  All known eDonkey/eMule/Overnet packets
  --dc     [tcp]      All known Direct Connect packets
  --kazaa  [tcp,udp]  All known KaZaA packets
  --gnu    [tcp,udp]  All known Gnutella packets
  --bit    [tcp,udp]  All known BitTorrent packets
  --apple  [tcp]      All known AppleJuice packets
  --winmx  [tcp]      All known WinMX
  --soul   [tcp]      All known SoulSeek
  --ares   [tcp]      All known Ares
...
Si en la ayuda os aparece eso, es que el módulo ipp2p está cargado y es funcional. Como podéis observar, el tráfico P2P que detecta y permite filtrar es el típico, por lo que ésto tiene buena pinta...
Ahora toca ver cómo emplear estas reglas para ver si funcionan o no. El método de funcionamiento es el mismo de siempre con IPTables, la única diferencia es que vamos a añadir un match contra el módulo P2P que hemos instalado. Así que para bloquear todo el tráfico P2P, nos quedarían unas reglas tal que así,
shell> iptables -A FORWARD -p tcp -m ipp2p --edk -j DROP
shell> iptables -A FORWARD -p udp -m ipp2p --edk -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --dc -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --kazaa -j DROP
shell> iptables -A FORWARD -p udp -m ipp2p --kazaa -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --gnu -j DROP
shell> iptables -A FORWARD -p udp -m ipp2p --gnu -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --bit -j DROP
shell> iptables -A FORWARD -p udp -m ipp2p --bit -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --apple -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --winmx -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --soul -j DROP
shell> iptables -A FORWARD -p tcp -m ipp2p --ares -j DROP

Más información: xtables-addons

La entrada Bloquear tráfico P2P desde IPTables la puedes leer en Puppet Linux.
Leer más

SEO: Optimización de Blogger

Técnicas SEO
Recientemente he comenzado a leer un poco de técnicas SEO y aunque Blogger no permite hacer demasiados ajustes en lo que a SEO se refiere, hoy quiero enseñaros un pequeño truco que mejora un poco el SEO en nuestro blog. Poco a poco iré introduciendo mejoras, algunas aplicables a Blogger, otras no.
De momento vamos a ver cómo crear la URL de cada post, cómo cambiar el título del blog en cada artículo y cómo añadir etiquetas META.
Cuando creamos un post, a éste le ponemos un título y luego al visualizarlo en el navegador y por lo tanto también al indexarlo Google, quedará de la siguiente forma, por defecto.
Titulo blog | Titulo post
Esto queda muy bien, pero el problema viene cuando Google recoge los títulos de vuestros post. Google por defecto tiene unos títulos de 60 caracteres, por lo que si vuestra combinación de "Título blog + Título post" sobrepasa esos caracteres, se pueden ignorar partes de título o key's importantes de dicho artículo.
Tecnicas SEO Blogger
Título Blogger con SEO
Para solucionar esto, existen dos formas de hacerlo, o bien eliminamos el título del blog o bien intercambiamos las ocurrencias. Primero el título del post y luego el del blog. A mi personalmente me parece más adecuada la segunda, así que vamos a ver qué cambios hay que realizar si estáis empleando una plantilla de Blogger. Tenemos que ir a editar la plantilla en HTML y buscar el siguiente código,
<title><data:blog.pageTitle/></title>
Que será reemplazado por este otro,
<b:if cond="’data:blog.pageType" item="" quot="">
   <title><data:blog.pageName/> | <data:blog.title/> </title>
<b:else>
   <title><data:blog.pageTitle/></title>
</b:else></b:if>
En caso de que sólo deseemos quedarnos con el título del post y obviar la parte del título del blog, el código final quedaría,
<b:if cond="’data:blog.pageType" index="" quot="">
   <title><data:blog.title/></title>
<b:else>
   <title><data:blog.pageName/></title>
</b:else></b:if>
Tecnicas SEO Blogger
SEO en URL
La segunda parte que tenemos que cuidar también bastante es la URL con la que publicamos cada uno de nuestros posts. Los motores de indexación también se fijan en ello y no sólo en el contenido. Esta parte es importante. Cuando estáis redactando un post, al lado derecho tenéis el botón Permalink, que por defecto coge un valor predetermiando, en función del título o de las primeras palabras del artículo. Esto lógicamente no es bueno para posicionarse, así que lo mejor es siempre editarlo y poner una URL estática con las 2 o 3 palabras que mejor definan de lo que estáis hablando. La separación de palabras, lo mejor es realizarla con -. Es importante también no pasar de 3 palabras en crear el título. Por ejemplo, para este post, no sería lo mismo http://.../tecnicasseoi.html, que http://.../tecnicas_seo_i.html que http://.../tecnicas-seo-i.html. De las 3 aproximaciones aquí puestas, la primera no significa nada, ya que para un indexador la palabra tecnicasseoi no tiene sentido y será muy raro que alguien la busque así. De las 2 que quedan, realmente la diferencia es muy poca y depende en gran medida del bot, algunos los _ no los toman como separadores de palabras mientras que -, sí.
Como píldora final, os dejo otro pequeño truco para mejorar también el posicionamiento. Los motores de búsqueda cada vez hacen más hincapié en los metadatos, es decir, la tendencia es ir hacia lo que se quiere decir y no a lo que se dice. Esto es muy complicado, así que como método de ayuda podemos incluir metadatos con información de nuestro blog en las cabeceras del mismo. En este caso, vamos a añadir metadatos de descripción y palabras clave. Para ello, nuevamente editamos la plantilla (edición HTML) y buscamos
<![CDATA[/*
Justo antes de esa línea, agregamos estas,
<b:if cond='data:blog.url == data:blog.homepageUrl'>
   <meta name="description" content="Tu descripción" />
   <meta name="keywords" content="key1, key2, key3" />
</b:if>
Con ello conseguiremos meter las meta-etiquetes a nivel general del blog.

Más información: search-engine-optimization-starter-guide.pdf

La entrada SEO: Optimización de Blogger la puedes leer en Puppet Linux.
Leer más

Montaje de recursos bajo demanda en GNU/Linux

Si alguna vez habéis trabajado con servidores NFS sabréis que el modelo habitual de trabajo es el de conectarse al recurso cuando un el equipo se arranca. Por ejemplo, si las /home de vuestros usuario están compartidas por NFS, éstas se suelen montar cuando el equipo cliente arranca, pero no se tiene en cuenta de si se están o no usando realmente. La conexión se establece y eso hace que el servidor NFS consuma más recursos de los que probablemente tendría que emplear, especialmente si el número de usuarios es grande.
Para evitar este tipo de complicaciones, GNU/Linux tiene un paquete, llamado autofs que permite montar automáticamente un partición cuando esta es requerida y desmontarla si no se está empleando, ahorrando así recursos. Vamos a ver cómo emplear automount para hacer justamente lo aquí descrito.
Primero vamos a instalar el paquete,
shell> apt-get install autofs
Tras su instalación tendremos varios archivos nuevos sobre el directorio /etc. En concreto auto.master, auto.misc, auto.net, auto.smb y default/autofs. Tras instalarlo, tendremos un nuevo daemon (autofs) que se encargará de controlar los puntos de montaje.
El fichero de configuración principal es /etc/auto.master y que contiene las principales líneas de los puntos de montaje. Cada línea es similar a ésta.
/misc /etc/auto.misc --timeout=60
Esto quiere decir que todo lo que hay en el fichero /etc/auto.misc hay que montarlo bajo /misc y desmontarlo si lleva sin usarse más de 60 segundos. La línea ahí descrita es la que tenemos de ejemplo comentada en el fichero principal, pero vamos a crear una que haga lo que queremos nosotros con NFS para nuestro /home.
Para ello, añadimos la siguiente línea a auto.master.
/home /etc/auto.home --timeout=60
Y a continuación, creamos el fichero /etc/auto.home con el siguiente contenido.
-fstype=nfs4,intr,rsize=0192,wsize=8192 192.168.1.33:/home
Y ya tenemos listo el proceso de automount para nuestro /home. Cada vez que un usuario quiera acceder a dicho directorio, en caso de no estar montado se montará automáticamente. El único requisito, tener el daemon autofs ejecutándose ;-)
Lógicamente y haciendo honor al post, este truco sirve para tanto para recursos NFS como para cualquier otro recurso que necesite ser montado (sshfs, samba, etc.).

La entrada Montaje de recursos bajo demanda en GNU/Linux la puedes leer en Puppet Linux.
Leer más

MySQL, unir filas duplicadas

Hoy os voy a enseñar un pequeño truco en MySQL que permite borrar datos duplicados de una tabla forma sencilla. Para hacerlo, simplemente vamos a recurrir a una "índice temporal" sobre una tabla, que hará justamente el trabajo que deseamos. Para que se entienda mucho mejor y más rápido, lo veremos con una prueba de concepto. Partimos de la siguiente tabla test.
mysql> CREATE TABLE `test` (
       `id` int(11) NOT NULL AUTO_INCREMENT,
       `a` int(11),
       `b` int(11),
       `c` int(11),
       `time` timestamp,
       PRIMARY KEY (`id`) );
El esquema es muy sencillo, pero para la demostración nos llegará. Ahora vamos a insertar unos cuentos valores, entre ellos, alguno repetido.
mysql> INSERT INTO test (a,b,c) VALUES (1,2,3),
       (1,2,3),
       (2,3,4),
       (3,4,5);
mysql> INSERT INTO test (a,b,c) VALUES (1,2,3);
mysql> SELECT * FROM test;
+----+------+------+------+---------------------+
| id | a    | b    | c    | time                |
+----+------+------+------+---------------------+
|  1 |    1 |    2 |    3 | 2013-03-04 19:41:20 |
|  2 |    1 |    2 |    3 | 2013-03-04 19:41:20 |
|  3 |    2 |    3 |    4 | 2013-03-04 19:41:20 |
|  4 |    3 |    4 |    5 | 2013-03-04 19:41:20 |
|  5 |    1 |    2 |    3 | 2013-03-04 19:41:42 |
+----+------+------+------+---------------------+
5 rows in set (0.00 sec)
Como podemos observar tenemos 5 filas con datos diferentes (el valor id, autoincremental, difiere). También para comprobar que funciona, hemos creado una nueva fila un poco más tarde que las demás, para así ver que el tiempo no influye en el resultado.
Nuestra intención es por lo tanto que aquellas filas que tengan los valores de a y b comunes se junten en una única fila. Aunque en este caso los valores son numéricos, sería aplicable a cualquier otro tipo soportado por MySQL. Para lograrlo, simplemente,
mysql> ALTER IGNORE TABLE test ADD UNIQUE INDEX(a,b);
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 2  Warnings: 0
Y vemos el resultado,
mysql> SELECT * FROM test;
+----+------+------+------+---------------------+
| id | a    | b    | c    | time                |
+----+------+------+------+---------------------+
|  1 |    1 |    2 |    3 | 2013-03-04 19:41:20 |
|  3 |    2 |    3 |    4 | 2013-03-04 19:41:20 |
|  4 |    3 |    4 |    5 | 2013-03-04 19:41:20 |
+----+------+------+------+---------------------+
3 rows in set (0.00 sec)
Observamos por lo tanto que algunos valores que había en la tabla han desaparecido, concretamente los que se vieron afectados por la creación de UNIQUE INDEX de las columnas a y b. En caso de que no queramos que este índice quede, tendremos que borrarlo. Muy sencillo y puede que en algunos casos necesario.

Nota: En caso de que al ejecutar la sentencia de creación de nuevo índice os de el siguiente fallo,
mysql> ALTER IGNORE TABLE  test ADD UNIQUE INDEX(a,b);
ERROR 1062 (23000): Duplicate entry '1-2' for key 'a'
es por que la tabla está en InnoDB y no en MyISAM. Así que antes de ejecutar dicha sentencia la cambiamos de engine, la modificamos y la volvemos a poner como nos interesa.
mysql> show create table test;
+-------+------------------------------+
| Table | Create Table                 |
+-------+------------------------------+
| test  | CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  `time` timestamp,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+------------------------------+
1 row in set (0.00 sec)

mysql> ALTER TABLE test ENGINE MyISAM;
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> ALTER IGNORE TABLE test ADD UNIQUE INDEX(a,b);
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 2  Warnings: 0

mysql> ALTER TABLE test ENGINE InnoDB;
Query OK, 3 rows affected (0.03 sec)
Records: 3  Duplicates: 0  Warnings: 0

La entrada MySQL, unir filas duplicadas la puedes leer en Puppet Linux.
Leer más

Metasploit, auditando joomla

joomla metasploit demo
Joomla es uno de los CMS más habituales para blog's o contenido dinámico. Quizás algo menos profesional que Drupal, pero sí más sencillo, por lo que su integración y despliegue en numerosos sitios fue alta. Hoy vamos a ver cómo empleando metasploit podemos comenzar a auditar la seguridad de un Joomla. Lo módulos de los que dispone metasploit para realizar el análisis que vamos a efectuar no son invasivos, por lo que sólo obtendremos información, que es lo esencial para comenzar a trabajar. Esto es lo que conocemos como Information Gathering (Recolección de Información).
Actualmente en Joomla hay 3 módulos para consultas acerca de Joomla, que nos comprobar la versión (joomla_version), ver las páginas colgadas (joomla_pages) y los plugins instalados en el CMS (joomla_plugins). Por lo tanto, para saber más acerca de una web en Joomla, lo único que necesitas saber será la dirección en la que contesta. Lo primero será saber a qué versión nos estamos enfrentando.
msf> use auxiliary/scanner/http/joomla_version
msf auxiliary(joomla_version)> set RHOSTS domain.com
RHOSTS => domain.com
msf auxiliary(joomla_version)> run

[+] 192.168.1.33:80 - Joomla Version: 2.5.0 from: language/en-GB/en-GB.xml 
[+] 192.168.1.33:80 - OS: *Nix
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
En este caso, como podéis comprobar estamos antes la versión 2.5.0. Esto ya nos da muchas ideas para buscar módulos vulnerables o posibles exploit's que funcionen. Acabamos de acotar mucho las búsquedas a realizar.
Ahora vamos a comprobar qué páginas tiene este Joomla disponibles,
msf> use auxiliary/scanner/http/joomla_pages
msf auxiliary(joomla_pages)> set RHOSTS domain.com
RHOSTS => domain.com
msf auxiliary(joomla_pages)> run

[+] 192.168.1.33:80 - Page Found: /robots.txt
[+] 192.168.1.33:80 - Page Found: /administrator/index.php
[+] 192.168.1.33:80 - Page Found: /htaccess.txt
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
En este caso no nos fue de gran ayuda. Tenemos el robots.txt, como todos los Joomla's y la página de administración. En este caso, el robots es también el por defecto del CMS, por lo que no tenemos ninguna información extra.
Así que vamos por la parte más divertida, buscar los plugins que tiene activos el sistema. Esto lo conseguimos tal que así,
msf> use auxiliary/scanner/http/joomla_plugins
msf auxiliary(joomla_plugins)> set RHOSTS domain.com
RHOSTS => domain.com
msf auxiliary(joomla_plugins)> run

[+] 192.168.1.33:80 - Plugin: /administrator/ 
[+] 192.168.1.33:80 - Plugin: /administrator/components/ 
[+] 192.168.1.33:80 - Plugin: /administrator/components/com_admin/ 
[+] 192.168.1.33:80 - Plugin: /administrator/index.php?option=com_djartgallery&task=editItem&cid[]=1'+and+1=1+--+ 
[+] 192.168.1.33:80 - Plugin: /administrator/index.php?option=com_searchlog&act=log 
[+] 192.168.1.33:80 - Plugin: /components/com_banners/ 
[+] 192.168.1.33:80 - Plugin: /components/com_content/ 
[+] 192.168.1.33:80 - Plugin: /components/com_mailto/ 
[+] 192.168.1.33:80 - Plugin: /components/com_search/ 
[+] 192.168.1.33:80 - Plugin: /components/com_users/ 
[+] 192.168.1.33:80 - Plugin: /components/com_weblinks/ 
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Y aunque va a tardar un poco, la verdad es que esta información sí es MUY importante. De aquí sacaremos qué exploit's podemos aplicar y cuales no tiene sentido intentar explotar, así como posibles SQLi.
Entradas relacionadas: Averiguando fallos en joomla

La entrada Metasploit, auditando joomla la puedes leer en Puppet Linux.
Leer más

Zabbix + MySQL + CONSTRAINT FOREIGN KEY

La mayoría de la gente que usa habitualmente Zabbix sabe el problema que éste tiene con la base de datos. Ya bien sea MySQL o cualquier otro motor. Una de las formas de evitar un acceso tan abusivo a los datos almacenados es dehabilitar el Housekeeping, o dicho de otra forma, deshabilitar el purgado de datos. Si hacemos esto, los datos almacenados en la base de datos nunca se borrarán y para evitar que crezcan sin control, la mejor solución es sin duda emplear un particionado de tablas.
Particionando las tablas conseguimos borrar de forma muy sencilla una gran cantidad de datos (partición == fichero en disco). Puesto que prácticamente todas las tablas dignas de ser particionadas en Zabbix tienen un campo llamado clock, de tipo unixtime, lo que facilita el particionado y el borrado.
En Zabbix 1.8, particionar las tablas y que todo funcionase no conllevaba problema alguno. Sin embargo con el upgrade a la 2.0 la cosa se complica. Si miramos un poco el schema de la base de datos podremos ver cosas como esta,
ALTER TABLE `screens` ADD CONSTRAINT `c_screens_1` FOREIGN KEY (`templateid`)...
ALTER TABLE `media` ADD CONSTRAINT `c_media_1` FOREIGN KEY (`userid`)...
ALTER TABLE `rights` ADD CONSTRAINT `c_rights_2` FOREIGN KEY (`id`)...
...
Estas reglas realizan una restricción de clave foránea, o dicho de forma más comprensible, un campo de una tabla influye directamente en la otra tabla. Por lo tanto, si borramos un valor de una de las tablas, este borrado se tiene que propagar al resto de tablas afectadas.
En la versión 2.0 de Zabbix este tipo de claves han aparecido y lo que en realidad es una facility muy interesante, en entornos de trabajo grandes puede ser un problema. Imaginemos el siguiente escenario en el que tenemos la tabla events está particionado por fecha (semana | mes) y que queremos comenzar a emplear las alertas para determinados eventos. Puesto que la tabla tiene creada la siguiente clave,
ALTER TABLE `alerts` ADD CONSTRAINT `c_alerts_2` FOREIGN KEY (`eventid`) REFERENCES `events` (`eventid`) ON DELETE CASCADE;
Cuando un nuevo evento intenta insertarse en la tabla alerts, tenemos el siguiente fallo,
[Z3005] query failed: [1452] Cannot add or update a child row: a foreign key constraint fails (`tiendas_produccion`.`alerts`, CONSTRAINT `c_alerts_2` FOREIGN KEY (`eventid`) REFERENCES `events` (`eventid`) ON DELETE CASCADE) [insert into alerts (alertid,actionid,eventid,userid,clock,mediatypeid,sendto,subject,message,status,alerttype,esc_step) values (9754,2,327497453,8,1362020524,1,'javier@domain.com','PROBLEM: Zabbix Agent fail','Trigger: Zabbix Agent fail
Trigger status: PROBLEM
Trigger severity: Information
Este fallo realmente es provocado por MySQL, que no soporta las claves "CONSTRAINT FOREIGN KEY" contra tablas particionadas. Si se piensa fríamente, tiene lógica ya que si se borra una partición, el motor de base de datos no puede controlar la clave. Esto pasará con cualquier tabla, pero en lo que nos afecta a nosotros es para Zabbix, en su versión 2.0.
Entonces, ¿cómo lo solucionamos?
Pues bien, como sabemos cual es el problema (la clave foránea) y como tenemos controlado el crecimiento de nuestras tablas con particiones y no nos interesa la funcionalidad que ofrecen estas claves (no las podemos usar), la mejor solución es sin duda, borrar las claves que no se usan. Así que vamos allá!
mysql> ALTER TABLE events DROP FOREIGN KEY c_alerts_2;
ERROR 1506 (HY000): Foreign key clause is not yet supported in conjunction with partitioning
Justamente queremos borrar la clave y nos da un error de que no se puede hacer, justamente por tener la tabla particionada. No pasa nada, no hay nada que root no sea capaz de hacer. Para ello vamos a optar por deshabilitar las claves foráneas,
mysql> SET FOREIGN_KEY_CHECKS = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
Y lo volvemos a intentar,
mysql> ALTER TABLE alerts DROP FOREIGN KEY c_alerts_2;
Esta vez ya sin problemas lo pudo ejecutar y las alertas ya comenzarán a funcionar sin problemas en Zabbix.
La entrada Zabbix + MySQL + CONSTRAINT FOREIGN KEY la puedes leer en Puppet Linux.
Leer más

Formulario de contacto

Nombre

Correo electrónico *

Mensaje *

Últimos comentarios