2009-03-12 27 views
8

私のASP.NET Webサイトには、Webアプリケーションに何らかのエラーが発生したときに私と他の開発者に電子メールを送信するグローバルエラーハンドラがあります。私たちは最近、聞いたことがない電子メールアドレスにCCを含むエラーを受け取りました。怖いのは、エラー電子メールが送信される開発者の一覧が、コンパイルされたASP.NETコードでハードコードされていることです。 CCがどのように追加されたかはわかりません。ASP.NETのSMTPヘッダインジェクション?

また、エラーの原因となったリクエストが私たちのフォームの1つを使用してスパムを送信しようとしたため、不正行為を起こしている可能性があります。要求を送信したIPアドレスもhttp://www.projecthoneypot.org/にリストされています。

私たちの最高の推測は、リクエストが何らかの形で不正であり、電子メールにCCヘッダーが挿入されたということです。問題は、これがどうやってできるのか理解できないことです。私たちはSystem.Net.Mailを使用して電子メールを送信しています。このようなことから保護するようです。 MailMessageオブジェクトの件名は1行しか受け付けないので、CC行の複数行の件名を作成することはありません。 MailMessageのtoとccアドレスを設定するのは非常に堅牢です。そして、私はあなたがメッセージの本文にCCヘッダーを追加する方法を見ることができません。私はこれに関する情報を見つけることができず、これが本当の問題かどうかを知りたいです。

EDIT:誰かがコードを要求しました。これでは...

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

コードを表示してください。さもなければ人々は野生の推測をちょうど取るでしょう... – Eppz

+0

私はコードを追加しました。私が言ったように、それは複雑ですが、私は問題がどこにあるのかわからないので、それをあまりにも愚かにしたくありませんでした。 –

+0

あなたが聞いたことがない電子メールアドレスにCCが含まれているエラーを含む電子メール(すべてのヘッダーを含む生の形式で、可能な限り難読化してください)を投稿してください。電子メール全体が偽造されている可能性が高いと思われます。 – bzlm

答えて

4

私は....あなたのメッセージの本文に、ユーザー制御データを詰めているにこれはVERY創造的な攻撃の対象である見ることができる:それは少し長いですが、ここにありますポイント、バイナリデータの狡猾な使用COULDは、フォーマットを取得するために、SMTPセッション中に適切なデータを送信するBODYになりますちょうど良い ...私は、すべてのASCIIテキスト、または文字列の作成中に、RFCの文字のみを許可する文字列サニタイザを作成します(URL、REFERRER、リモートアドレス、およびUserAgentをフィルタリングします)。これらは攻撃の可能性が高い点です。

コードで基本的な電子メールを作成し、作成した本文をテキスト、HTML、またはPDFファイルとしてATTACHすることも考えられます。

誰かがそれを希望、CRLFCRLF.CRLFCRLFは、身体の部分中に送信させ、正しい身体を送信するのに十分な狡猾だった場合.... SMTPエンベロープデータがメッセージデータと同じではありません、覚えておいてください送信を終了してからデータを送信し続けると、MAIL FROM:RCPT TO :, DATAなどを送信することができます(これは考えられないシナリオです...)

Iあなたが持っている電子メールのソースをRAWに見てください。(実際のSMTPトランザクションの16進ダンプと同じように、Outlookはあなたに何かを見たいと思っていません)。

また、これは興味深いものである、と私は楽しみにしています

...それはあなたの問題を解決する可能性があります....メッセージを送信する前にQP、またはB64を使用して、あなたの体をコードしてみてくださいそれの結果。

+0

私はこの問題を決して解決しなかったし、問題は1回しかなかった。この答えを最も可能性の高いシナリオとして受け入れるつもりです。私はユーザーが入力したデータは非常に巧妙な方法で作られているに違いないと思います。私はまた、ユーザーが入力したデータをテキストファイルの添付ファイルとして追加するというアイディアが本当に好きです。 –

1

あなたのコードは非常に安全に見えるので、問題はあなたの側にあるとは思わない。

IMOは、誰かがメールサーバに送信されている間にSMTPメッセージを傍受し、余分なCC:行を注入しました。メールサーバーが侵害されている可能性があります。

回答が見つからない場合は、マイクロソフトに直接お問い合わせください。.NET Frameworkで悪用された可能性があります。

0

回避策として、非公式の暗号化(たとえば公開鍵暗号化)を使用して電子メールメッセージを暗号化してみませんか?そうすれば、意図した受取人だけがそれを読むことができます。

この方法では、悪意のある人があなたのメッセージのコピーを(たとえどんな手段によって)得たとしても、それは今それらに使用されます。

あなたがFBIやGoogleのような高プロファイルのウェブサイトを持っている場合、非常に創造的な人の多くは、それを妥協するために多くの時間を費やし、偉大な長さに行くでしょう。詳細なエラーメッセージを保護することは非常に重要です。