2009-03-12 17 views
8

Moja witryna ASP.NET ma globalny moduł obsługi błędów, który wysyła do mnie e-mail (i innego programistę), gdy wystąpi jakikolwiek błąd w aplikacji internetowej. Niedawno otrzymaliśmy błąd, który zawierał kod CC na adres e-mail, o którym nigdy nie słyszeliśmy. Przerażające jest to, że lista programistów, do których wysyłany jest e-mail z błędem jest zakodowana w skompilowanym kodzie ASP.NET. Nie wiemy, w jaki sposób można było dodać CC.Wstrzyknięcie nagłówka SMTP w ASP.NET?

Jesteśmy również bardzo podejrzliwi wobec nieczystej gry, ponieważ prośba, która spowodowała błąd, była próbą użycia jednego z naszych formularzy do wysyłania spamu. Adres IP, który wysłał żądanie, jest również wymieniony na http://www.projecthoneypot.org/.

Nasze najlepsze przypuszczenie brzmi teraz, że żądanie zostało źle sformułowane w taki sposób, że wstawiło nagłówek CC do wiadomości e-mail. Problem polega na tym, że nie możemy zrozumieć, jak można to zrobić. Używamy System.Net.Mail do wysyłania e-maili i wydaje się, że chroni przed tego typu rzeczami. Obiekt obiektu MailMessage akceptuje tylko jedną linię, aby nie tworzyć obiektu wielowierszowego z linią CC. Ustawianie adresów do i cc w programie MailMessage wydaje się dość solidne. I nie widzę, jak można dodać nagłówek CC w treści wiadomości. Nie mogę znaleźć żadnych informacji na ten temat i chciałbym wiedzieć, czy to prawdziwy problem.

EDYCJA: Ktoś zażądał kodu. To trochę długo, ale tutaj jest:

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

Pokaż nam swój kod, a my pomożemy. W przeciwnym razie ludzie będą po prostu zgadywać ... – Eppz

+0

Dodałem kod. Jak już powiedziałem, jest to skomplikowane, ale nie chciałem go za bardzo zgadywać, ponieważ nie wiem, gdzie może być problem. –

+0

Proszę napisać e-mail (w jego surowej formie, w tym wszystkie nagłówki, możliwie jak najmniej zaciemnić) zawierający błąd, który zawierał CC na adres e-mail, o którym nigdy nie słyszałeś. Wydaje się bardziej prawdopodobne, że cała wiadomość e-mail jest sfałszowana. – bzlm

Odpowiedz

4

mogłem zobaczyć co jest celem a SAMYM twórczego ataku .... Jesteś farsz kontrolowane przez użytkownika dane do treści wiadomości ... Na którym point, sprytne użycie danych binarnych COULD wynikiem jest BODY, który wysyła odpowiednie dane podczas sesji SMTP, aby uzyskać sformatowany format PO PROSTU PRAWIDŁOWO ... Jeśli mogę, proponuję albo przekonwertować treść do całego tekstu ASCII , lub podczas budowania ciągów, napisać odświeżacz ciągu, który zezwala na wprowadzanie znaków RFC. (Filtruje adresy URL, REFERRERA, Adres zdalny i UserAgent). To są bardziej prawdopodobne punkty ataku.

Druga myśl może być skonstruowanie podstawowe wiadomości w kodzie, i dołączyć ciało, które zostały skonstruowane w postaci tekstu lub HTML lub PDF.

Pamiętaj, dane KOPERTA SMTP NIE takie same jak dane wiadomości .... Jeśli ktoś był na tyle przebiegły, aby wysłać właściwą jednostkę, która spowodowała CRLFCRLF.CRLFCRLF być wysłany w ciągu części ciała, które zakończyć wysyłanie, a następnie, jeśli wysyłają dane, mogą wysłać całą wiadomość od: RCPT DO :, DANE, itp. (Przyznano, że jest to mało prawdopodobny scenariusz ...) ...

I "KOCHAM, aby zobaczyć źródło wiadomości e-mail, którą otrzymałeś ... (Tak jak w przypadku zrzutu heksadecymalnego transakcji SMTP, a nie tego, co program Outlook chce zobaczyć).

Możesz także spróbować kodowania swoje ciało przy użyciu QP lub B64 przed wysłaniem wiadomości .... To może rozwiązać problem ...

ten jest interesujący, a ja się doczekać jego wynik.

+0

Ostatecznie nigdy nie rozwiązałem tego problemu i mieliśmy tylko jeden problem. Przyjmuję tę odpowiedź jako najbardziej prawdopodobny scenariusz. Myślę, że dane wprowadzone przez użytkownika musiały zostać wykonane w bardzo przebiegły sposób. Bardzo podoba mi się także pomysł dodania wprowadzonych przez użytkownika danych jako załącznik do pliku tekstowego. –

1

Twój kod wygląda bardzo bezpiecznie, więc nie sądzę, że problem jest po twojej stronie.

IMO, albo ktoś przechwycone wiadomości SMTP, podczas gdy była ona wysyłana do serwera pocztowego i wstrzykuje dodatkowy CC: linia; lub serwer pocztowy został naruszony.

Jeśli nie możesz znaleźć odpowiedzi, sugeruję bezpośredni kontakt z Microsoftem - być może odkryłeś exploit w .NET Framework.

0

Aby obejść ten problem, może chcesz zapisać wiadomość e-mail przy użyciu asymetrycznej enkrypcji (na przykład z użyciem klucza publicznego)? W ten sposób tylko zamierzony odbiorca będzie mógł go odczytać.

W ten sposób, nawet jeśli źli ludzie otrzymają kopię twojej wiadomości (w dowolny sposób), będą teraz dla nich użyteczne.

Spójrzmy prawdzie w oczy, jeśli masz wysokiej jakości strony internetowe, takie jak FBI lub Google, wielu bardzo kreatywnych ludzi poświęci dużo czasu i dołoży wszelkich starań, aby go skompromitować. Bardzo ważne jest, aby chronić szczegółowe komunikaty o błędach.

Powiązane problemy