Limpiar sitios webs infectados por virus

Buscar archivos .php modificados recientemente, en este caso -7 en la última semana.

find . -type f -name ‘*.php’ -mtime -7

Buscar dentro de los archivos php código malicioso:

TIP: The blank space followed by a * means zero or more spaces.

find . -type f -name '*.php' | xargs grep -l "eval *(" --color
find . -type f -name '*.php' | xargs grep -l "base64_decode *(" --color
find . -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color
find . -type f -name '*.php' | xargs egrep -i "(mail|fsockopen|pfsockopen|stream_socket_client|exec|system|passthru|eval|base64_decode) *\("
find . -type f -name '*.php' | xargs egrep -i "preg_replace *\((['|\"])(.).*\2[a-z]*e[^\1]*\1 *," --color

Checkear que archivos pueden haber cambiado, este truco se hace con dos versiones idénticas de WordPress, la tuya y una descargada, vamos a buscar diferencias en los archivos para ver cuales pueden estar comprometidos:

diff -r wordpress-clean/ wordpress-compromised/ -x wp-content

Tip: asegurase de usar la misma version de WordPress que la que tienes instalada.

Buscar en los directorios con permisos de escritura archivos infectados o que puedan estarlo

search_for_php_in_writable

chmod +x search_for_php_in_writable
find . -type f -name '*.php' > phpfiles.txt
~/search_for_php_in_writable > php_in_writable.txt
find . -type d -perm 0777 > writable_dirs.txt

find_non_php_in_writable

chmod +x find_non_php_in_writable;
~/find_non_php_in_writable;
./find_non_php_in_writable | less
./find_non_php_in_writable > suspicious_files.txt

####Tip. Puedes usar grep -v para excluir de la busqueda resultados que contengan palabras de las búsquedas salvadas anteriormente.

grep -iv 'binary file' suspicious_files.txt | less

find_suspicious_php

chmod +x find_suspicious_php;
~/find_suspicious_php
find . -type d -perm 0770 > writable_dirs.txt

si encuentras archivos maliciosos busca en los logs los accesos a estos archivos para encontrar la ip del hacker que ha hecho la intrusion.

grep -i "ejfyebh\.php" /var/log/apache/access.log | less

TIP: El truco está en encontrar la IP, una vez encuentras la ip, haces búsquedas en tus logs de la ip del hacker que te ha atacado y con ellos puedes llegar a encontrar el truco que ha usado para hackear tu sitio web.

Esto es todo amigos, si necesitáis algún tipo de ayuda no dejéis de escribir unos comentarios.

Tunear PHP.ini para Centos7 y Nginx

Cada vez que creamos un nuevo Servidor Virtual nuestro sistema de creación replica el archivo que encuentra en /etc/php.ini, por eso lo que hacemos es editarla al crear el servidor y asi usaremos los mismos parámetros bases para todos los servidores virtuales que vamos añadiendo a cada Servidor Dedicado.

La seguridad es lo primero

Esconder la version de PHP en las cabeceras de las páginas servidas a nuestros usuarios maliciosos:

expose_php = Off

Output buffering – Error 502 Nginx

Deshabilitar output buffering, con esto deshabitamos el ob_flush(), esto evita errores tipo 502 en los servidores Nginx, sinceramente, es cuestión de gustos, si no hay buffer la experiencia del usuario se ve truncada a que termine de ejecutar un script hasta que muestra el resultado en pantalla, el caso más claro es cuando WordPress instala/actualiza los plugins y vamos viendo como se instala uno detrás de otro, con el buffering a Off solo veríamos el resultado final, el servidor retiene todo el contenido hasta que ha terminado todos los proceso que le require la carga de está página de WordPress, lo ideal es subir el limite por defecto que nos pone por defecto de 4096 bytes, pero si necesitamos recursos extras lo podemos subir a 16384 bytes.

output_buffering = Off
– or –
output_buffering = 16384

Tiempo de ejecución de los Script

En nuestro caso, corremos bases de datos bastante grandes, hacemos backups y sincronización de datos, a veces los 30 segundos que nos da PHP por defecto nos viene corta, por eso la subimos a 120 segundos el tiempo de espera a que se ejecute un script en una página php.

max_execution_time = 120

Otros valores

Queremos errores, nada más.

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_WARNING & ~E_NOTICE

Mejor un error que una página en blanco que no dice nada.

display_errors = On

Estos valores dependen de vuestros usuarios, que tipo de aplicaciones utilizan.


post_max_size = 20M
upload_max_filesize = 19M

Substituir Apache por nginx en Centos7 + Virtualmin

Somos fanáticos de NGINX, no podemos ocultarlo, es más complicado tunearlo pero los rendimientos son sorprendentes, entre los beneficios que nos da nginx es que no estamos limitados a correr servicios para PHP sino que tambien podemos usar Ruby o cualquier tipo de SOCKET.

Los pasos a seguir son los siguientes:

[bash]
service httpd stop ; chkconfig httpd off
yum install nginx
systemctl start nginx
yum install wbm-virtualmin-nginx wbm-virtualmin-nginx-ssl
[/bash]

 
Login to Virtualmin as root, and go to Webmin -> Servers -> Nginx Webserver and make sure that Nginx and its configuration files are found.
If not, click on the Module Config link and set the config and command paths correctly.

Return to Virtualmin, and go to System Settings -> Features and Plugins.

Un-check the “Apache website” , “SSL website” and “DAV Login”, “Mailman”, “Protected web directories”, “AWstats reporting” and “Subversion repositories” features.

Check the “Nginx website” and “Nginx SSL website” features, then click “Save”.

If Virtualmin reports that any other features cannot be used without Apache, go back and de-select them too.

Go to the System Information page and click Refresh system information in the top right.

Verify that Nginx is shown as running in the “Status” section.

Esto es todo amigos,..

FUENTE: https://www.virtualmin.com/documentation/web/nginx

Instalar un servidor web para alojar páginas webs desde cero

Hola amigos,

Hoy vamos a instalar un servidor web para dar servicio de páginas web y correo electrónico a nuestros clientes.
Lo primero que tenemos que hacer es conseguir un servidor, el mercado tiene un amplio abanico de posibilidades, si quereis algo para hacer unas pruebas, que no sea caro y podáis probar diferentes distribuciones os recomiendo echarle un vistazo a Digital Ocean, son una empresa con años de experiencia, pioneros en la tecnología que implementan y con una infraestructura verdaderamente robusta. Muy pronto van a contar con un Data Center en Gibraltar y la latencia para España va a ser extraordinaria.

La instalación es muy sencilla, los comando son muy pocos los que se necesitan para echar a andar el servidor web, al final de este POST teneis unas notas sobre que hacer después y por donde seguir.
Este post está dedicado a como hacerlo funcionar en un Centos, al día de hoy estamos usando la version 7 a 64bits, pero se puede hacer con Ubuntu el sistema recomendado por este panel de control es la de RedHat o en nuestro caso Centos7.
NOTA: Podeis seguir el ejemplo usando una máquina virtual con programas tales VirtualBox podeis bajaros la distro desde aqui: Centos Mirrors arrancar desde el CD e instalar la version mínima, son solo 600Mb.
Yo en mi caso dispongo de una distribución virtualizada para los desarrollos, luego solo tengo que exportar e importar el servidor virtual en el servidor de producción.

El único requerimiento previo antes de poder instalar el sistema es aseguraros de tener un nombre de HOST válido. Para ello debemos correr el siguiente comando hostname -f y os debe mostrar un nombre de internet válido tipo servidor.dominio.com. Este ha de tener una reversa o de lo contrario los clientes no podrán acceder a tu servidor. Este paso es el más importante. Piensa antes de decir que YES.

Una vez tengamos nuestro Centos7 64bits recien instalado, y hemos comprobado que el Hostname es válido, vamos a poceder a instalar todo nuestros paquetes para convertir este equipo en un autentico servidor web, para ello nos vamos a entrar por ssh al servidor, entra como root en nuestra nueva máquina y vamos a correr los siguientes comandos:

[code]
yum update
# si no teneis wget instalado porque no viene con la instalación mínima de Centos:::
yum install wget
# nos descargamos el instalador de nuestro servidor web
wget http://software.virtualmin.com/gpl/scripts/install.sh
/bin/sh install.sh
[/code]

Esto es todo, pasado unos minutos podemos acceder a nuestro recien creado webserver a través de la dirección https://servidor.dominio.com:10000, solo tendrás que substituir servidor.dominio.com por el hostname que hayas elegido.

Siguientes recomendaciones a seguir:

Cambiar la version de PHP5 a PHP7, podeis seguir este tutorial.
Cambiar la version de MariaDb5 a MariaDb10, tambien tenemos un tutorial a medida.
Cambiar Apache por Nginx, aqui teneis el tutorial (Este paso es para usuario avanzados).
Activar / Instalar FirewallD, la seguridad es muy importante, no menosprecies una buena configuración del firewall.
Instalar Fail2Ban, nos protege de ataques por fuerza bruta.

Limpiar la memoria cache en un servidor linux

Un buena manera de limpiar la cache de memoria sin usar es la siguiente, puede usarse en casi cualquier servidor linux, en mi caso yo uso Centos.

Añade la siguiente linea al cron de la cuenta de Root ejecuntado el comando “crontab -e” hay que entrar por ssh o por medio de la consola de comando si estamos trabajando con un servidor en local.

[bash]
0 * * * * /root/limpiacache.sh
[/bash]

Crea un archivo en la carpeta /root/ con el nombre ‘limpiacache.sh’ y añade las dos siguientes líneas

[bash]
#!/bin/sh
sync; echo 3 > /proc/sys/vm/drop_caches
[/bash]

Dale persmisos de escritura al archivo:

[bash]
chmod +x limpiacache.sh
[/bash]

Tuneando Apache Prefork MPM

Tuning the Apache Prefork MPM

Apache uses a set of values called the Prefork MPM to determine how many servers it will utilize and how many threads each server can process. Out of the box all Apache installations use the same values regardless of whether your server has 512Mb of RAM or 8Gb of RAM. It is important that as the server administrator you configure these values to work with your server load.

The Apache Prefork MPM can be found in the Apache configuration file; usually /etc/httpd/conf/httpd.conf. The default values are…


StartServers 2
MinSpareServers 3
MaxSpareServers 3
ServerLimit 75
MaxClients 75
MaxRequestsPerChild 1000

Each Directive taken from “http://httpd.apache.org/docs/trunk/mod/mpm_common.html” is detailed below.

– – – – – – – – – – – –

The StartServers directive sets the number of child server processes created on startup. As the number of processes is dynamically controlled depending on the load there is usually little reason to adjust this parameter.

– – – – – – – – – – – –

The MinSpareServers directive sets the desired minimum number of idle child server processes. An idle process is one which is not handling a request. If there are fewer than MinSpareServers idle then the parent process creates new children until satisfies the MinSpareServers setting.

– – – – – – – – – – – –

The MaxSpareServers directive sets the desired maximum number of idle child server processes. An idle process is one which is not handling a request. If there are more than MaxSpareServers idle, then the parent process will kill off the excess processes.

– – – – – – – – – – – –

The ServerLimit directive is only used if you need to set MaxClients higher than 256 (default). Do not set the value of this directive any higher than what you might want to set MaxClients to.

– – – – – – – – – – – –

The MaxClients directive sets the limit on the number of simultaneous requests that will be served. Any connection attempts over the MaxClients limit will normally be queued, up to a number based on the ListenBacklog directive. Once a child process is freed at the end of a different request, the connection will then be serviced.

For non-threaded servers (i.e., prefork), MaxClients translates into the maximum number of child processes that will be launched to serve requests. The default value is 256; to increase it, you must also raise ServerLimit.

– – – – – – – – – – – –

The MaxConnectionsPerChild directive sets the limit on the number of connections that an individual child server process will handle. After MaxConnectionsPerChild connections, the child process will die. If MaxConnectionsPerChild is 0, then the process will never expire.

Setting MaxConnectionsPerChild to a non-zero value limits the amount of memory that process can consume by (accidental) memory leakage.

– – – – – – – – – – – –

The single most important directive is MaxClients as this determines the amount of Apache child processes that will be launched to server requests. A simple calculation for MaxClients would be:

(Total Memory – Critical Services Memory) / Size Per Apache process

I define Critical Services as services such as mySQL, Plesk, Cpanel; any service that is required for proper operation of your server.

I’ve used the following commands via shell to determine values for Total Memory, OS Memory, MySQL Memory, and Apache Process Size

TOTAL MEMORY
[root@vps httpd]# free -m
total used free shared buffers cached
Mem: 1002 599 402 0 28 337
-/+ buffers/cache: 233 769
Swap: 2047 124 1922

MYSQL MEMORY
[root@vps httpd]# ps aux | grep ‘mysql’ | awk ‘{print $6}’
408
21440
704

APACHE PROCESS SIZE
[root@vps httpd]# ps aux | grep ‘httpd’ | awk ‘{print $6}’
22468
11552
41492
40868
41120
41696
39488
41704
15552
16076
16084
728

In this case the server has 1002Mb of memory allocated, xx used by the OS itself, 21Mb used by mySQL, and each Apache thread averages about 30Mb.

MaxClients = (1002 – 21) / 30 therefore MaxClients = 32.7

The next important aspect is MaxConnectionsPerChild as this is the amount of threads that will be processed before the child is recycled.

A good calculation for MaxConnectionsPerChild would be:

(total amount of daily requests / total number of daily processes)

Determining these values is a bit more complex as it requires some type of statistics package or thorough knowledge of interpreting Apache access logs.

As this does not adversely effect memory usage, only cpu time to cycle the process if you are unable to determine this information the standard 1000 should be used.

Thus a good configuration for this server would be


StartServers 2
MinSpareServers 3
MaxSpareServers 3
ServerLimit 30
MaxClients 30
MaxRequestsPerChild 1000

Be sure once you’ve saved the file to perform a configuration test before restarting Apache.

[root@vps httpd]# service httpd configtest
Syntax OK

[root@vps httpd]# service httpd restart
Stopping httpd: [ OK ]
Starting httpd: [ OK ]

Soluciones peculiares para MySQL

Con este truco podemos hacer una consulta que nos devuelve el comando que nos eliminaria todas las tablas que tengan alguna similitud en el nombre de la tablas de dicha base de datos.

Antes de nada hay que ejecutar SET FOREIGN_KEY_CHECKS=0 al terminar haremos SET FOREIGN_KEY_CHECKS=1

luego podemos hacer una consulta que nos devuelve la consulta que elimina todas las tablas de la base de datos clienteX_DB_Nombre cuyo nombre se ajuste con la consulta LIKE “wp_%”;

[bash]
SELECT CONCAT("DROP TABLE ", GROUP_CONCAT(table_name), ";")
FROM information_schema.tables
WHERE table_schema = "clienteX_DB_Nombre"
AND table_name LIKE "wp_%";
[/bash]

El resultado que obtengamos de esta consulta tenemos que ejecutarlo, no olvideis volver a habilitar las foreing_key_checks=1.

Resolver problemas de WordPress por medio de Mysql

Uno muy útil que uso a menudo es substituir contenido dentro de la base de datos directamente por medio de un comando sql

[bash]
update wp_posts set post_content = replace
(post_content,’texto a reemplazar’,’texto para reemplazar’);
[/bash]
[bash]
update wp_options set option_value = replace
(option_value,’texto a reemplazar’,’texto para reemplazar’);
[/bash]

[/bash]
update wp_postmeta set meta_value = replace
( meta_value,’texto a reemplazar’,’texto para reemplazar’);
[/bash]

Algunos trucos para trabajar con el Firewall en Centos

Ver las entradas del firewall

Eliminar entradas del firewall si queremos hacer pruebas es muy sencillo. Para mostrar todas las reglas del firewall con el fin de ver quien tenemos baneados usamos:

[bash]iptables -L[/bash]

nos arrojaría un resultado parecido al siguiente

[bash]
Chain fail2ban-postfix (1 references)
target prot opt source destination
RETURN all — anywhere anywhere

Chain fail2ban-sasl (1 references)
target prot opt source destination
DROP all — xxx.xxx.xxx.xxx anywhere
RETURN all — anywhere anywhere
[/bash]

Eliminar entradas del firewall

Para eliminar la entrada que veamos oportuna podemos hacerlo con este comando substituyendo el nombre del filtro y la dirección ip:

[bash]iptables -D fail2ban-sasl -s xxx.xxx.xxx.xxx -j DROP[/bash]

Trucos para Fail2Ban en Centos

Fail2Ban es una excelente herramienta que se programa para revisar los logs de los distintos programas a intervalos periódicos, si encuentra a través de sus filtros registros que pueden ser sospechosos podemos tomar medidas de seguridad para bloquear el servicio a la ip en cuestión, incluso bloquear por X tiempo cualquier petición de dicha ip sospechosa, etc.

Instalar Fail2ban

Unos sencillos comandos para descargar, descomprimir, installar y configurar… merece la pena.

[bash]
wget https://github.com/downloads/fail2ban/fail2ban/fail2ban_0.8.7.1.orig.tar.gz
tar xzvf fail2ban_0.8.7.1.orig.tar.gz
cd fail2ban-0.8.7.1/
service fail2ban stop
python setup.py install
vi /etc/fail2ban/jail.conf
[/bash]

Configurar Fail2ban

Estos son algunos de los filtros que podemos activar en función de los servicios que corriendo en el servidor:
Para ello editamos el archivo jail.conf, segun la instalacion por defecto de cada distribucion el fichero se encuentra en /etc/fail2ban/jail.conf

[bash]

[ssh-iptables]

enabled = true
filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp]
sendmail-whois[name=Fail2banSSH, dest=admin@email.com, sender=root@server.com]
logpath = /var/log/secure
maxretry = 2

[proftpd-iptables]

enabled = true
filter = proftpd
action = iptables[name=ProFTPD, port=ftp, protocol=tcp]
sendmail-whois[name=Fail2banProftp, dest=admin@email.com, sender=root@server.com]
logpath = /var/log/proftpd/ftp.log
maxretry = 3

[sasl-iptables]

enabled = true
filter = sasl
backend = polling
action = iptables[name=sasl, port=smtp, protocol=tcp]
sendmail-whois[name=Fail2banSASL, dest=kikopc@gmail.com, sender=root@s1.ksirve.com]
logpath = /var/log/maillog

[dovecot]

enabled = true
filter = dovecot
action = iptables-multiport[name=Dovecot, port="110,995,143,993,25", protocol=tcp]
sendmail-whois[name=Fail2Dovecot, dest=admin@email.com, sender=root@server.com]
logpath = /var/log/maillog
/var/log/secure
maxretry = 3

[postfix-tcpwrapper]

enabled = true
filter = postfix
action = iptables-multiport[name=postfix, port="110,995,143,993,25", protocol=tcp]
sendmail[name=Fail2banPostfix, dest=admin@email.com, sender=root@server.com]
logpath = /var/log/postfix.log
/var/log/maillog
bantime = 30000

[/bash]

Configurar filtros en fail2ban

Cada uno deberá configurar los servicios que vea oportunos, también debemos asegurarnos de que los filtros funcionan, los filtros se encuentran en /etc/fail2ban/filter.d/ los podemos encontrar en formato Nombre_Filtro.conf. Un ejemplo que me he encontrado en un Centos usando Virtualmin es el filtro SASL por defecto viene erróneo, hay que ajustar el failregex dentro del archivo que podemos encontrar en /etc/fail2ban/filter.d/sasl.conf

[bash]
failregex = : warning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed$
#cambiamos por
failregex = (?i): warning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed

[/bash]

Si queremos probar si funciona correctamente podemos aplicar el filtro con el siguiente comando

Comprobar un filtro

[bash]

fail2ban-regex /var/log/maillog /etc/fail2ban/filter.d/sasl.conf

[/bash]

Para hacer reportes

[bash]

#resumen de ips y reglas
grep "Ban " /var/log/fail2ban.log | awk -F[\ \:] ‘{print $10,$8}’ | sort | uniq -c | sort -n
#Reporte del dia en curso
grep "Ban " /var/log/fail2ban.log | grep `date +%Y-%m-%d` | awk ‘{print $NF}’ | sort | awk ‘{print $1,"("$1")"}’ | logresolve | uniq -c | sort -n
#Resumen de vida de fail2ban
zcat /var/log/auth.log* | grep ‘Failed password’ | grep sshd | awk ‘{print $1,$2}’ | sort -k 1,1M -k 2n | uniq -c

[/bash]

Si quereis ver como configurar el firewall con algunos sencillos comandos, aqui los teneis.