2009-03-12 12 views
8

Mi sitio web ASP.NET tiene un controlador de error global que me envía un correo electrónico (y otro desarrollador) cuando hay algún tipo de error en la aplicación web. Recientemente recibimos un error que contenía un CC a una dirección de correo electrónico de la que nunca habíamos oído hablar. Lo aterrador es que la lista de desarrolladores a los que se envía el correo electrónico de error está codificada en código ASP.NET compilado. No vemos cómo se podría haber agregado el CC.Inyección de encabezado SMTP en ASP.NET?

También sospechamos de juego sucio porque la solicitud que provocó el error fue un intento de utilizar uno de nuestros formularios para enviar correo no deseado. La dirección IP que envió la solicitud también se encuentra en el http://www.projecthoneypot.org/.

Nuestra mejor suposición ahora es que la solicitud fue malformada de alguna manera que inyectó un encabezado CC en el correo electrónico. El problema es que no podemos entender cómo se podría hacer esto. Estamos usando System.Net.Mail para enviar los correos electrónicos y parece protegernos contra este tipo de cosas. El sujeto del objeto MailMessage solo acepta una sola línea para que no cree un asunto multilínea con una línea CC. Configurar las direcciones a y cc en MailMessage parece bastante robusto. Y no veo cómo podría agregar un encabezado CC en el cuerpo del mensaje. No puedo encontrar ninguna información sobre esto y me gustaría saber si esto es un problema real.

EDITAR: Alguien ha solicitado el código. Es un poco largo, pero aquí está:

public class Global : System.Web.HttpApplication 
{ 
    protected void Application_Error(Object sender, EventArgs e) 
    { 
     // Get the last exception. 
     Exception objException = Server.GetLastError(); 

     // Work out the error details based on the exception. 
     string ErrorType = ""; 
     string ErrorDescription = ""; 
     string ErrorHtml = ""; 

     if (objException == null) 
     { 
      // This should never occur. 
      ErrorType = "Unknown Error"; 
      ErrorDescription = "Unknown Error"; 
     } 
     else if (objException.GetType() == typeof(HttpException)) 
     { 
      // This will occur when the ASP.NET engine throws a HttpException. 
      HttpException objHttpException = objException as HttpException; 
      if (objHttpException.GetHttpCode() == 404) 
      { 
       string Resource = Globals.GetFullUrl(this.Context); 
       Server.ClearError(); 
       Response.Redirect("/ResourceNotFound.aspx?BadUrl=" + Server.UrlEncode(Resource)); 
       return; 
      } 
      else 
      { 
       ErrorType = objHttpException.GetHttpCode().ToString(); 
       ErrorDescription = objHttpException.Message; 
      } 
     } 
     else if (objException.GetType() == typeof(HttpUnhandledException) && objException.InnerException != null && objException.InnerException.GetType() == typeof(HttpException)) 
     { 
      // This will occur when the code throws a HttpException (e.g. a fake 404). 
      HttpException objHttpException = objException.InnerException as HttpException; 
      if (objHttpException.GetHttpCode() == 404) 
      { 
       string Resource = Globals.GetFullUrl(this.Context); 
       Server.ClearError(); 
       Response.Redirect("/ResourceNotFound.aspx?BadUrl=" + Server.UrlEncode(Resource)); 
       return; 
      } 
      else 
      { 
       ErrorType = objHttpException.GetHttpCode().ToString(); 
       ErrorDescription = objHttpException.Message; 
      } 
     } 
     else if (objException.GetType() == typeof(HttpUnhandledException)) 
     { 
      // This will occur when a page throws an error. 
      HttpUnhandledException objHttpUnhandledException = (HttpUnhandledException) objException; 
      ErrorType = objHttpUnhandledException.GetHttpCode().ToString(); 
      if (objHttpUnhandledException.InnerException != null) 
       ErrorDescription = objHttpUnhandledException.InnerException.Message; 
      else 
       ErrorDescription = objHttpUnhandledException.Message; 
      if (objHttpUnhandledException.GetHtmlErrorMessage() != null) 
      { 
       ErrorHtml = objHttpUnhandledException.GetHtmlErrorMessage(); 
      } 
     } 
     else if (objException.GetType() == typeof(HttpRequestValidationException) && !Globals.IsTtiUser(this.Context)) 
     { 
      // Do nothing. This is mostly just spider junk and we don't want to know about it. 
     } 
     else 
     { 
      // This will occur when the ASP.NET engine throws any error other than a HttpException. 
      ErrorType = objException.GetType().Name; 
      ErrorDescription = objException.Message; 
     } 

     // Send an email if there's an error to report. 
     if (ErrorType != "" || ErrorDescription != "") 
     { 
      Globals.SendErrorEmail(this.Context, ErrorType, ErrorDescription, ErrorHtml); 
     } 
    } 

    public static void SendErrorEmail (HttpContext context, string errorType, string errorDescription, string errorHtml) 
    { 
     // Build the email subject. 
     string Subject = "EM: " + errorType + ": " + context.Request.ServerVariables["SCRIPT_NAME"]; 

     // Build the email body. 
     string Body; 

     StringBuilder sb = new StringBuilder(""); 
     sb.Append("Server:\r\n"); 
     sb.Append(Globals.Server.ToString() + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("URL:\r\n"); 
     sb.Append(Globals.GetFullUrl(context) + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Error Type" + ":\r\n"); 
     sb.Append(errorType + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Error Description" + ":\r\n"); 
     sb.Append(errorDescription + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Referring Page:\r\n"); 
     sb.Append(context.Request.ServerVariables["HTTP_REFERER"] + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Date/Time:\r\n"); 
     sb.Append(DateTime.Now.ToString() + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Remote IP:\r\n"); 
     sb.Append(context.Request.ServerVariables["REMOTE_ADDR"] + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("User Agent:\r\n"); 
     sb.Append(context.Request.ServerVariables["HTTP_USER_AGENT"] + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Crawler:\r\n"); 
     sb.Append(context.Request.Browser.Crawler.ToString() + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("Admin User:\r\n"); 
     sb.Append(context.User.Identity.Name + "\r\n"); 
     sb.Append("\r\n"); 
     sb.Append("\r\n"); 
     Body = sb.ToString(); 

     // If there's HTML to represent the error (usually from HttpUnhandledException), 
     // then stuff the body text into the HTML (if possible). 
     bool HtmlMessage = false; 

     if (errorHtml != "") 
     { 
      Regex r = new Regex("(?<thebodytext><body.*?>)", RegexOptions.IgnoreCase); 
      if (r.IsMatch(errorHtml)) 
      { 
       Body = Body.Replace("\r\n", "<br>"); 
       Body = r.Replace(errorHtml, "${thebodytext}" + Body, 1); 
       HtmlMessage = true; 
      } 
     } 

     // Send an email to the TTI developers. 
     MailMessage objMail; 
     objMail = new MailMessage(); 
     objMail.From = new MailAddress("from-address"); 
     objMail.To.Add(new MailAddress("to-address")); 
     objMail.CC.Add(new MailAddress("cc-address")); 
     objMail.CC.Add(new MailAddress("another-cc-address")); 
     if (HtmlMessage) 
      objMail.IsBodyHtml = true; 
     else 
      objMail.IsBodyHtml = false; 
     if (errorType == "404") 
      objMail.Priority = MailPriority.Low; 
     else 
      objMail.Priority = MailPriority.High; 
     objMail.Subject = Subject; 
     objMail.Body = Body; 

     try 
     { 
      SmtpClient objSmtpClient = new SmtpClient(); 
      objSmtpClient.Send(objMail); 
     } 
     finally 
     { 
      // Do nothing. 
     } 
    } 
} 
+0

Muéstranos tu código y te podemos ayudar. De lo contrario, la gente simplemente tomará locas suposiciones ... – Eppz

+0

Agregué el código. Como dije, es complejo, pero no quería dejarlo mudo porque no sé dónde podría estar el problema. –

+0

Publique el correo electrónico (en su formato original, incluidos todos los encabezados; ofusque lo menos posible) que contenga el error que contenía un CC en una dirección de correo electrónico de la que nunca había oído hablar. Parece más probable que todo el correo electrónico se falsifique. – bzlm

Respuesta

4

pude ver que era el blanco de un ataque muy creativa .... Se están rellenando los datos controlados por el usuario en su cuerpo del mensaje ... En ese punto, el uso astuto de datos binarios PODRÍA dar como resultado un CUERPO que envía los datos adecuados durante la sesión SMTP para formatearlo JUSTO DERECHO ... Si me permiten, sugiero convertir el cuerpo a todo el texto ASCII o durante la creación de cadenas de caracteres, escriba un sanitizador de cadenas que solo permita el uso de caracteres RFC. (Filtra las URL, REFERRER, dirección remota y UserAgent). Esos son sus puntos de ataque más probables.

Un segundo pensamiento podría ser construir un correo electrónico básico en el código, y UNIR el cuerpo que ha construido como un texto, HTML o archivo PDF.

Tenga en cuenta, los datos sobre SMTP es NO los mismos que los datos del mensaje .... Si alguien fue lo suficientemente astuto para enviar el cuerpo correcto que causó una CRLFCRLF.CRLFCRLF que se enviará durante la parte del cuerpo, que sería terminar el envío, y luego si siguieron enviando datos, podrían enviar el CORREO completo DE: RCPT A :, DATOS, etc. ... (Otorgado, este es un escenario improbable ...) ...

I QUERÍA ver el RAW fuente del correo electrónico que recibió ... (Como en el volcado hexadecimal de la transacción SMTP real, no es lo que Outlook quiere que vea, ni lo que sea).

También puede intentar codificar su cuerpo usando QP, o B64 antes de enviar el mensaje .... Eso podría resolver su problema ...

Esto es muy interesante, y estoy deseando que llegue el resultado de eso.

+0

Finalmente, nunca resolví este problema y solo tuvimos el problema 1 vez. Voy a aceptar esta respuesta como el escenario más probable. Creo que los datos ingresados ​​por el usuario deben haber sido elaborados de una manera muy astuta. También me gusta la idea de agregar los datos ingresados ​​por el usuario como un archivo adjunto de texto. –

1

Su código se ve muy seguro, por lo que no creo que el problema esté de su parte.

IMO, o bien alguien ha interceptado el mensaje SMTP mientras estaba siendo enviado al servidor de correo e inyectó la línea CC: adicional; o el servidor de correo ha sido comprometido.

Si no puede encontrar una respuesta, le sugiero contactar directamente a Microsoft: es posible que haya descubierto un exploit en .NET Framework.

0

Como solución alternativa, ¿por qué no encriptas el mensaje de correo electrónico usando la inscripción asimetría (por ejemplo, inscripción de clave pública)? De esa forma solo el destinatario previsto podrá leerlo.

De esta forma, incluso si los tipos malos obtienen una copia de su mensaje (por cualquier medio) les será de utilidad.

Seamos realistas, si usted tiene un sitio web de alto perfil como el FBI o Google, mucha gente muy creativa pasará mucho tiempo y hará todo lo posible para comprise. Es extremadamente importante proteger los mensajes de error detallados.

Cuestiones relacionadas