
PHP es un lenguaje de programación muy potente, intuitivo y fácil de utilizar. Además tiene gran cantidad de librerías desarrolladas de las que nos podemos aprovechar. Si eres administrador de sistemas y además tienes que realizar labores de administración de sistemas, estoy seguro que te encontrarás en multitud de situaciones donde utilizar PHP será la opción más rápida y comoda para llevar a cabo tus propósitos.
Por ejemplo, imagina que tienes que ejecutar una tarea diaria que involucre acceso a base de datos de una aplicación que está desarrollada en PHP y que dispone de su propia API, como por ejemplo Joomla. Además está tarea tiene que estar integrada dentro de una serie de shell scripts realizados ya, que funcionan bien y no quieres tener que reprogramarlos en PHP. Tienes 3 opciones, implementar las tareas dentro de otros shell scripts o scripts en perl, desaprovechando tus conocimientos de PHP y el API de Joomla, pasar tus scripts de shel Linux a PHP, lo que puede resultar una pérdida de tiempo si ya funcionan correctamente.. o la tercera y por la que me decanto, utilizar PHP desde la línea de comandos y crear un script de PHP que acepte los parámetros necesarios e invocarlo desde otros shell scripts o scripts en perl que ya tengamos implementados. Así que por todo esto vamos a ver como utilizar PHP en el CLI.
En Linux para saber que programa va a interpretar el código del script, se utiliza el shebang, que es una lína que se coloca al principio, que incorpora los caracteres #! seguidos del path al intérprete. Para saber cual es la ruta del interprete de PHP podemos utilizar los comandos
wich php
#o también
whereis php
Por ejemplo, nuestro script, en un SO CentOS, empezaría así:
#!/usr/bin/php
<?php
#código del script PHP
?>
Después la metodología de codificación es muy similar a la de cualquier script PHP desarrollado para ser ejecutado en Apache, con la diferencia de que ahora los parámetros los recibimos del Array $argv[] en lugar de utilizar los Arrays $_POST, $_GET o $_REQUEST. Deberemos de utilizar las marcas de PHP del mismo modo que en un script de CGI (>?php ?<) para que el intérprete de PHP ejecute el código. Por ejemplo, creamos un primer script de ejemplo con el nombre prueba.php y el siguiente código:
#!/usr/bin/php
<?php
print_r($argv);
?>
Si lo invocamos de la siguiente forma, obtendremos la siguiente salida:
./prueba.php argumento1 argumento2
#Salida del comando:
Array
(
[0] => ./prueba.php
[1] => argumento1
[2] => argumento2
)
Como veis, es muy fácil acceder a los parámetros del script utilizando el array $argv, es una buena idea asignar las variables del array a variables con nombres más intuitivos para no liarnos después en la programación. La posición 0 del array $argv siempre contiene el nombre del script desde elq ue se llama, esto es algo habitual, el que haya programado shell script en Bash lo sabrá muy bien. Podemos utilizar la función array_shift($argv) para eliminar el primer parámetro o recorrer el array $argv con un while.
Realizar comprobaciones básicas
En la variable $argc se almacena un entero con el número de parámetros introducidos. Empleando este valor podemos hacer algunas comprobaciones básicas:
#!/usr/bin/php
if ($argc != 3) {
die("Modo de empleo: prueba.php <num_usuarios> <bloquear> \n");
}
$num_usuarios = $argv[1];
$bloquear = $argv[2];
Comprobar que el valor de entrada es un valor numérico:
if (!is_numeric($param)){
die("$param no es un número");
}
Acceso a las variables de entorno
Puedes acceder a las variables de entorno del sistema
putenv("EDITOR=/path/al/editor");
echo "Actualmente estás usando el editor por defecto: " . getenv('EDITOR') ;
El resto es cuestión de saber programar en PHP. Por ejemplo, podemos utilizar el API de Joomla si nos lo proponemos si lo incluimos como se indica en la documentación de Joomla.
En próximos artículos veremos algunas funciones muy útiles para emplear en nuestros scripts de CLI en PHP..
Pues por que si no te hackean, así de simple :) Ayer estuve grabando un vídeo para Webempresa que cuelgo aquí también.. Se puede ver que es bastante simple hackear un Joomla desactualizado, en el vídeo no se muestra un hackeo 100% completo, pero entiendo que la técnica de robo de sesión queda bastante clara.. Si en lugar de introducir un simple alert en la URL que se aprovecha de la debilidad XSS lográramos introducir un script de BeEf, por ejemplo, pues entonces no solo podrían robarte la sesión, sino que hasta podrían obtener una shell de tu sistema.. Inquietante, eh?? Ya sabeis, toda protección es poca :)
NOTA: Advertir, que esto no sólo pasa en Joomla, te pueden hacer exactamente lo mismo en cualquier CMS que no esté actualizado, se llame Drupal, WordPress, Moodle, DotNetNuke… o como quieras llamarle..
Linux Malware Detect, escáner Open Source para aplicaciones web
Recursos, SysAdmin

Linux Malware Detect (LMD), o como yo lo llamo; Maldet, es un proyecto Open Source creado por Ryan M. y básicamente es un detector de malware de aplicaciones web creado a partir de unos shell scripts y scripts en perl para Linux. Está pensado para CentOS, aunque debería de funcionar en cualquier distribución. El motivo por el que está pensado para CentOS es que el autor usa CentOS y cPanel en los servidores que administra.. esta es una configuración muy común ya que cPanel funciona muy bien en CentOS.
Maldet es bastante completo, permite realizar escaneos manuales de nuestro sistema o dejarlo funcionando en modo monitor. Para que funcione el modo monitor el SO deberá de tener instalada la librería inotify. Por defecto, cuando se instala, se agregan unas entradas en el cron diario que ejecuta un escaneo de los ficheros que se han creado o modificado las últimas 24 horas y envía un reporte al root, por lo que nos permitirá tener un cierto control del malware que va llegando al servidor.
Pero la característica que realmente me gustó de Maldet es el modo monitor, cuando se está ejecutando en este modo, en el momento en que Maldet detecte que aparece malware en el disco duro, nos avisará y realizará la acción que hayamos definido, es decir, un aviso por mail, o aviso + cuarentena del fichero. Esto puede ser muy útil sobre todo con determinadas cuentas de usuario peligrosas.
Instalación de Linux Malware Detect
cd /usr/local/src/
rm -vrf maldetect-*
wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
tar -xzf maldetect-current.tar.gz
cd maldetect-*
sh ./install.sh
maldet --update-ver
maldet --update
Configuración de Maldet
$EDITOR /usr/local/maldetect/conf.maldet
En este archivo de configuración encontraremos varias líneas interesantes:
# Se define si se avisa por email al root
# [0 = disabled, 1 = enabled]
email_alert=1
# El asunto del mail de aviso
email_subj="maldet alert from $(hostname)"
# Emails de destino separados por coma
# [ values are comma (,) spaced ]
email_addr="david@malware.servidores.com"
# La acción que se realizará cuando se detecte malware, cuidado aquí con los falsos positivos!!
# [0 = alert only, 1 = move to quarantine & alert]
quar_hits=0
# Intentará limpiar el script PHP de funciones tipo base64_decode o eval, no se asegura que después de esto funcione bien el script
# [0 = disabled, 1 = clean]
quar_clean=1
# Se define si se suspenderá la cuenta de cPanel del usuario al que se le haya detectado malware. Esto es un modo ultra paranoico y no es recomendable por que suelen encontrarse falsos positivos que provocarían que se suspendiera la cuenta a la mínima.. En caso de no usar cPanel, colocaría la shell del usuario en /bin/false
# [0 = disabled, 1 = suspend account]
quar_susp=0
#Minimo user id, para asegurarse de no suspender usuarios de sistema
quar_susp_minuid=500
# This is the html/web root for users relative to homedir, when
# this option is set, users will only have the webdir monitored
# [ clear option to default monitor entire user homedir ]
inotify_webdir=public_html
# Prioridad que se le dará al proceso que irá escanenado los ficheros creados o modificados en tiempo real
# [ -19 = high prio , 19 = low prio, default = 10 ]
inotify_nice=10
Una vez editado el fichero de configuración podemos empezar a usar Maldet.
Escaneo manual
# Escaneo de todos los public_html del servidor, usamos ? como wildcard
maldet -a /home/?/public_html
También podemos ejecutar un escaneo solo de los ficheros recientes con:
# Escaneo de los ficheros con menos de 3 días de antiguedad
maldet -r /home/?/public_html 3
Puedes enviar a la cuarentena todos los ficheros encontrados en un SCANID una vez realizado el escaner, suponiendo que en la configuración no tuvieras puesto que se envíe a cuarentena automaticamente..
maldet --quarantine SCANID
Si queremos dejar Maldet monitorizando en tiempo real, podemos lanzar el siguiente comando:
maldet –monitor users
maldet --monitor /home,/tmp,/path/que/quieras
Maldet quedaría monitorizando la lista de paths separada por comas. Si en cambio ejecutamos el Maldet en modo monitor con el parámetro users, se escaneará el directorio definido en la variable inotify_webdir de la configuración, en cada home del usuario. Puedes ver un log del monitor de la siguiente forma:
tail -f /usr/local/maldetect/inotify/inotify_log
Si queremos matar todos los procesos de monitorización, podemos ejecutar:
maldet -k
Podemos ir viendo los reportes en Maldet en /usr/local/maldetect/sess/ y si vemos que algún Malware se ha colado, podemos enviarlo al autor para que lo incluya en la base de datos de Maldet de la siguiente forma:
maldet -c malware_no_detectado.php
Como ya he comentado al principio, cuando se instala se introducen unas entradas en el cron.daily para realizar escaneos diarios, si tienes curiosidad puedes mirar en el fichero /etc/cron.daily/maldet para ver que se está ejecutando exactamente.
Más información:
En mi trabajo estoy continuamente utilizando el cliente SSH de mi Mac y de mi Ubuntu para conectarme a los servidores. Muchas veces tengo que dejar la sesión abierta para volver a mirar después, o simplemente para dejar ejecutando un comando que tarda x tiempo en finalizar. Pues resulta que cuando me conecto desde mi conexión de Ono, si dejo la conexión inactiva más de 4 o 5 minutos, se corta y tengo que volver a conectarme. Esto es un incordio (por no utilizar otra palabra), sobre todo si dejas un comando largo que tiene que estar un buen tiempo ejecutándose. Sin embargo, esto no me pasa cuando empleo el router de mi conexión de Jazztel.
Para solucionar el problema de la ejecución de comandos largos desde SSH se puede emplear el comando screen, muy útil para esto, pero sigue siendo un tostón tener que conectarse de nuevo por SSH, hacer un detach del screen y volver a visualizar el screen, para que luego se te vuelva a cortar a los 5 minutos de inactividad.
Leyendo un poco, descubro que esto es un mecanismo del propio router NAT, que corta las conexiones establecidas si están más de X tiempo en espera para dejar la tabla NAT lo más limpia posible. Algunos routers son benévolos y te dan un día entero de tiempo de conexión (Jazztel), otros, como el router de Ono, te corta la conexión cada 5 minutos.
Pues todo este rollo, es para contaros que existe un parámetro que puedes añadir en el fichero ssh_config y que permite enviar paquetes KeepAlive cada X segundos para mantener la conexión abierta:
Host *
ServerAliveInterval 20
Esto haría que en todos los hosts a los que nos conectamos se envíen paquetes KeepAlive cada 20 segundos para mantener la sesión abierta. El fichero al que añadir estas dos líneas es /etc/ssh_config en Mac y /etc/ssh/ssh_config en Linux. Con esto se ha solucionado mi problema con el SSH y Ono que me hacía perder tanto tiempo inutilmente. Por lo que he visto por ahí también se puede configurar el parámetro en el router, pero me parecía más comodo configurar mi cliente SSH.
Leyendo el fichero access.log de Apache desde línea de comandos en Linux
SysAdmin
Esta tarde ando aburrido y he entrado por el acceso SSH que me ofrece mi empresa de hosting a curiosear un poco. He accedido al directorio donde se encuentran los logs y he empezado a leerlos. Al final he escrito unos cuantos comandos sencillos pero que permiten encontrar información interesante en los logs y demuestran el potencial de la línea de comandos de Linux.
Listado de IPs únicas que ha accedido hoy a tu web
cat access.log.2011-02-24 | cut -d " " -f 1 | sort | uniq
109.230.216.XXX
110.75.164.XXX
114.80.93.XXX
.
.
.
95.60.25.XXX
95.61.0.XXX
95.63.178.XXX
Cuantas IPs han accedido hoy a tu web
cat access.log.2011-02-24 | cut -d " " -f 1 | sort | uniq | wc -l
1830
#El día 24 de febrero hubieron 1830 IPs diferentes conectadas al blog. Contrastando con los datos de Google Analytics puedo ver que es bastante verídico el dato..
Contar cuantas veces accede cada IP a tu web
cut -d " " -f 1 access.log.2011-02-24 | sort | uniq -c | sort
323 67.205.46.XXX
587 78.136.66.XXX
794 190.233.141.XX
962 189.155.9.XXX
1081 95.17.167.XXX
El modificador -c del comando uniq hace que además de agrupar por IPs, muestre a la izquierda el número de veces que se repetía esta IP.. muy útil.
Como veis, usando los comandos de manipulación de texto de Linux se puede obtener mucha información de los logs. Esto es sólo un ejemplo, se podría obtener mucha información del error.log o de los logs de ModSecurity que podríamos utilizar para tareas de mantenimiento del servidor como por ejemplo añadir IPs a una lista negra de bloqueos para IPs que generan demasiadas entradas de determinado error… en fín, lo que nuestra imaginación de de sí..
Después de una temporadita sin escribir nada, me he decidido a ponerme delante del teclado y escribir un corto tutorial sobre como instalar un servidor SVN en Linux, usaremos una distribución de paquetes RPM, pero en distribuciones de paquetes DEB el proceso es muy similar, sólo hay que usar el sentido común..
Todo programador sabe de la importancia de un servidor de versiones a la hora de programar en grupo o de mantener un software que va creciendo con el tiempo, nada mejor que disponer de nuestro propio servidor SVN para esto.
Instalando y configurando el servidor SVN
Para instalar el servidor es muy sencillo, simplemente nos accedemos al terminal de línea de comandos como root y ejecutamos lo siguiente:
yum install subversion
Deberemos asegurarnos previamente de que no tenemos la palabra “perl” en la línea de excludes del fichero yum.conf, si fuera así deberíamos de comentar la línea de exludes, guardar cambios y volver a ejecutar el comando.
Una vez se haya completado la instalación, dispondremos del servidor y el cliente de subversion instalados en nuestro sistema. Ahora deberemos de crear el directorio donde guardaremos nuestros repositorios de software, en mi caso voy a guardarlos en el directorio /root/repos, después crearemos nuestro primer repositorio.
mkdir /root/repos
svnadmin create /root/repos/nombre_repositorio
Siguiendo estos sencillos pasos ya disponemos de un repositorio creado, ahora vamos a ver como lanzar el servicio. Por defecto no se crea el script de inicialización que debería de almacenarse en /etc/init.d/subversion, por lo que tendremos que lanzar el servicio manualmente, para ello ejecutamos el siguiente comando:
mkdir /root/repos
svnserve -d -r /root/repos
Este comando lanzará el proceso que dejará el servidor subversion a la escucha en el puerto 3690. Para saber si está el proceso a la escucha podemos emplear el siguiente comando:
netstat -anp | grep svn
#La salida del comando debería ser algo así:
#
# tcp 0 0 :::3690 :::* LISTEN 17911/svnserve
#
#Vemos que hay un proceso con PID 17911 escuchando en el puerto 3690 del protocolo TCP.
Para parar el servicio, podemos proceder a matar el proceso con un “kill -9 PID”, en este caso, “kill -9 17911″ .
Para realizar una importación inicial podemos ejecutar el siguiente comando:
mkdir /root/repos
svn import /home/david/software/miproyecto file:///root/repos/nombre_repositorio/ -m "Importacion inicial"
Este comando efectuará una importación inicial del directorio miproyecto al repositorio que acabamos de crear. Deberemos de tener el puerto 3690 abierto tanto en entrada como salida para poder usar el servidor y clientes de SVN respectivamente, podemos usar estos comandos:
iptables -A INPUT -p TCP --dport 3690 -j ACCEPT
iptables -A OUTPUT -p TCP --dport 3690 -j ACCEPT
Ya tenemos nuestro servidor corriendo, vamos a ver como configurar los accesos al servidor. Si accedemos al directorio /root/repos/nombre_repositorio veremos que hay creados 3 ficheros: authz , passwd y svnserve.conf. Hacemos una copia de seguridad antes de editarlos por si acaso :)
Vamos al fichero svnserve.conf y dejamos los siguientes valores:
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
realm = Mi software
Como veis, hemos limitado el acceso a gente anonima, por lo que todo el mundo deberá de acceder con usuario y contraseña que ahora veremos como definir. Ahora vamos al fichero passwd y dejamos los siguientes valores para crear el usuario david, puede cambiar el nombre de usuario y pass por el que quieras, logicamente:
[users]
david = MiPasComplicado4758965
Por último editamos el fichero authz y lo dejamos como se muestra:
[groups]
# harry_and_sally = harry,sally
[nombre_repositorio:/]
david = rw
Como puedes ver, se pueden definir grupos. En este caso le damos acceso de lectura y escritura al usuario david. Guardamos los cambios y ya tenemos nuestro servidor SVN configurado. Ahora vamos a ver como usar el cliente de línea de comandos de una forma básica.
Usando el cliente de SVN
Nos vamos a un ordenador cualquiera y hacemos el checkout inicial, para ello navegamos en línea de comandos hasta el directorio donde queremos hacer el checkout y usamos el siguiente comando:
svn checkout --username david svn://miserver.com:3690/nombre_repositorio/
Nos pedira el password y descargará todo el código al directorio actual. Ahora vamos a ver un par de comandos básicos para añadir ficheros y actualizar nuestro código. Imaginar que queremos crear un nuevo directorio y dentro de este directorio queremos crear un fichero, pues accedemos al código y ejecutamos lo siguiente.
mkdir midir
cd midir
nano mificheronuevo.php
#Escribimos el contenido que necesitemos
#Añadimos un nuevo fichero
svn add midir mificheronuevo.php
svn commit -m "Comentarios del commit" midir mificheronuevo.php
Con este código creamos un nuevo directorio, dentro creamos un fichero, los añadimos al repositorio central de Subversion y ejecutamos el commit para subirlos al servidor.
Copias de seguridad de Subversion
Podemos hacer copias de seguridad de nuestro repositorio empleando el siguiente comando:
svnadmin dump /root/repos/nombre_repositorio > nombre_repositorio.svn_dump
Después podemos recuperarla fácilmente en otro servidor creando un nuevo respositorio y volcando el dump:
svnadmin create /root/repos/nombre_repositorio
svnadmin load /root/repos/nombre_repositorio < nombre_repositorio.svn_dump
Si investigas un poco más, verás como puedes hacer dumps solo de los cambios efectuados a partir de un número de revisión concreto y muchas cosas más. De momento, hasta aquí hemos llegado.. Recomiendo la lectura de este artículo de Ariel Camus para los no iniciados. Saludos!!
Borrar directorios y ficheros viejos en Linux usando el comando find y rm
SysAdmin
Este comando me sirvió de utilidad el otro día para eliminar todos los backups con más de 2 días de antiguedad. Los backups se realizaban a cada hora con una tarea cron que llamaba a un shell script, por lo que este comando sirve para ir borrando todos los ficheros en cada llamada al script y que no se llene el disco de backups..
for i in `find /ruta/al/directorio/que/quieras -maxdepth 1 -type d -mtime +2 -print`
do
echo -e "Borrando el directorio $i";
rm -rf $i;
done
También puede ser ejecutado en una sola línea así:
for i in `find /ruta/al/directorio/que/quieras -maxdepth 1 -type d -mtime +2 -print`; do echo -e "Borrando el directorio $i"; rm -rf $i; done
Si ponemos un mtime de 0, se borrarán todos los ficheros que no se hayan creado hoy, ya que el parámetro mtime de find redondea la fecha. Con un valor de dos, se borrarán todos los ficheros con más de dos días de antiguedad. Ejecutar man find para saber más.. Modificar el script para hacer que bsuque ficheros sería muy sencillo, recomendable mirar más opciones de find, es increíble lo que puede buscar este comando :).
Cuidado con la ruta que se indica en el find, no se vayan a borrar ficheros no deseados.
Con este artículo se estrena la categoría SysAdmin. Ahora que me estoy dedicando a algunas labores de mantenimiento y seguridad de sevidores Linux, iré colgando de vez en cuando algunas recetas que me vayan siendo de utilidad. Hoy cuelgo esta receta que me fue de gran ayuda en un script donde quería enviar 3 ficheros adjuntos con el resultado de unos logs que se habían generado. Usando el método habitual solamente podría enviar un fichero adjunto, después ví esta receta y pensé..¿Cómo no se me había ocurrido antes?
#!/bin/sh
uuencode /home/david/log.txt /home/david/log.txt > /tmp/out.mail
uuencode /home/david/log2.txt /home/david/log2.txt >> /tmp/out.mail
cat email-body.txt >> /tmp/out.mail
mail -s "Logs enviados ( `date` )" david@dominio.com < /tmp/out.mail
rm -f /tmp/out.mail
Al comando uuencode hay que pasarle dos veces el nombre del fichero.. por si alguién pensaba que es un error.
Vía Cyberciti
Me llamo David Noguera, tengo 23 años y soy Desarrollador/Administrador web.
Puedes encontrar algo más de información en la página