顯示具有 資訊安全 標籤的文章。 顯示所有文章
顯示具有 資訊安全 標籤的文章。 顯示所有文章

2013年2月27日 星期三

假 Facebook email 攻擊使用者電腦的 java 的漏泂

今天早上我收到兩封信,其中一封假裝有人給了我照片的意見,如下

SNAGHTML18d44ebd

連結指向的網址,當然不是 Facebook 的官網。

我找了一台虛擬機(之後可再還原)試了一下該網址,看了一下 html code.

果然是攻擊時下最夯的 java 漏洞。美指JAVA有安全漏洞籲停用。這可是通過美國政府認證的哦!

即使後來 Oracle 出了 Java 7 Update 11, 但Java更新補漏洞 美國土安全部仍說勿用

clip_image004

反正現在很少網站使用 Java Applet 了,將它關掉或移除吧!

 

ps: 不知道現在最新的 update 15 解決了這個問題沒有?

2013/3/10 : 兩次更新徒勞無功,Java再爆嚴重漏洞 ,所以目前(2013/3/13) 還是不安全

2011年6月2日 星期四

危險的 HTTP method 測試

緣故

今天早上客戶寄來一封資安檢測結果,說我們維護的Web系統有漏洞。

弱點大意是:Web Server 提供了 PUT, TRACE, DELETE, CONNECT 的 Http Method. 應該關閉。

並且把這項缺失列為中等風險,寫的很厲害的樣子。「PUT method 允許用戶端上傳檔案至伺服器, DELETE method 允許用戶端將伺服器的檔案刪除. 將允許遠端攻擊者可任意上傳檔案至伺服器而置換網頁, 若攻擊者上傳惡意程式到具有執行權限的目錄, 將可達到更大的破壞.」

過程

記得我們沒有開 WebDAV 啊!為什麼寫的這麼離譜?使用 Fiddler 查一下吧!

使用 Fiddler 的 Request Builder 查開發機 IIS

image

再選到 Inspectors,看查詢的 Request 及 Response (結果)
OPTIONS 會列出該 Web Server 可使用的 Http Method.

image

結果列出來,只有一項 TRACE 是有爭議的。根據 RFC 2616 指出,這是用來 Debug 用的 Method,可能揭露出不必要的資訊。因此會被列為風險。在 Apache 上更可能被偷取 cookie

IIS

為什麼在IIS 上 TRACE 預設是可以使用的呢?再使用 Fiddler,這次使用 TRACE 查一下吧。

image

image

這次的結果是 HTTP/1.1 501 Not Implemented (未實作)。HttpStatus 500 以上代表伺服器錯誤。

雖然有開放 TRACE 這個 Method,但一律回未實作。這妙吧。
因此,沒有漏洞。

再使用 DELETE 查一下。結果是 405 Not allowed(不允許)。這證明 IIS 上的WebDAV 果然沒有開啟。

image

結論

一看到資安檢測結果時,雖然只有這一項目,還是心裡不舒服。

看來該資安廠商是使用工具掃出來的結果。雖然只有一個 TRACE 看來符合,但把整個 PUT, DELETE, TRACE, CONNECT 全部列上去,看來比較有「價值」。

另外, IIS 為什麼要列為可用的Method,然後再回應 501 未實作呢?這裡就不深究原因了。

2011年2月1日 星期二

本機Windows驗證不通過?

這個很怪。剛開始完全弄不懂。

發生的是這樣子。我有一台伺服器,例如 serverA, FQDA 是 serverA.domainA。

為了作業方便,對內對外我希望是 serverB.domainB 都可以存取。在其他的伺服器都可以存取,但在這個伺服器,使用 http://serverB.domainB 時,會拋出 Windows 的驗證。而無論怎麼打帳密都不會過。此時,只要使用 http://localhost, http://serverA, http://serverA.domainA, 都會過,唯獨本機時不過.

在事件檢視器中會出現下面的錯誤

 

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" /> 
  <EventID>4625</EventID> 
  <Version>0</Version> 
  <Level>0</Level> 
  <Task>12544</Task> 
  <Opcode>0</Opcode> 
  <Keywords>0x8010000000000000</Keywords> 
  <TimeCreated SystemTime="2011-02-01T02:13:08.330597300Z" /> 
  <EventRecordID>42135</EventRecordID> 
  <Correlation /> 
  <Execution ProcessID="528" ThreadID="580" /> 
  <Channel>Security</Channel> 
  <Computer>PTTFS.pt.bankpro</Computer> 
  <Security /> 
  </System>
- <EventData>
  <Data Name="SubjectUserSid">S-1-0-0</Data> 
  <Data Name="SubjectUserName">-</Data> 
  <Data Name="SubjectDomainName">-</Data> 
  <Data Name="SubjectLogonId">0x0</Data> 
  <Data Name="TargetUserSid">S-1-0-0</Data> 
  <Data Name="TargetUserName">administrator</Data> 
  <Data Name="TargetDomainName">PT</Data> 
  <Data Name="Status">0xc000006d</Data> 
  <Data Name="FailureReason">%%2304</Data> 
  <Data Name="SubStatus">0x0</Data> 
  <Data Name="LogonType">3</Data> 
  <Data Name="LogonProcessName" /> 
  <Data Name="AuthenticationPackageName">NTLM</Data> 
  <Data Name="WorkstationName">PTTFS</Data> 
  <Data Name="TransmittedServices">-</Data> 
  <Data Name="LmPackageName">-</Data> 
  <Data Name="KeyLength">0</Data> 
  <Data Name="ProcessId">0x0</Data> 
  <Data Name="ProcessName">-</Data> 
  <Data Name="IpAddress">172.18.1.31</Data> 
  <Data Name="IpPort">56489</Data> 
  </EventData>
  </Event>

原因

使用 0xc000006d 當關鍵用,到Bing 搜尋一下找到一篇

Account failed to log on (0xc000006d) – Unable to load website from local server

這裡寫出了解法,並且原是:防止 DoS 攻擊。很怪吧!

解法是,在 registry 中,在 增加

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 下新增一個名為 BackConnectionHostNames 的 MultiString,值就輸入 serverB.domainB。

這樣就解除了這個問題.

2011年1月19日 星期三

ASP.NET 發生錯誤: 要解密的資料長度無效

緣由

最近更新客戶的網頁伺服器時,在事件檢件器中發現了下面的錯誤

Type : System.ApplicationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : 發生錯誤: 要解密的資料長度無效。

由於該網站有建置Web Farm以符合 NLB(Network Load Balance),另外一個網頁伺服器雖然沒有看到這個錯誤,但有另一個看來詭異的錯誤

Type : System.ApplicationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : 發生錯誤: 這是無效的 webresource 要求。
Query String: d=xA7L75UVc2mKUixrFtavoQ2&t=633722850937794608
Cookie: __utma=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
__utmz=xxxxxxxxxxxxxxxxxxxxxxxx.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
ASP.NET_SessionId=4lflv055rekkuqierw02csa1

毀了,完全看不懂!

原因

找了老半天,這是因為 MS10-070 的因素,我要求客戶上 windows update。而客戶的環境通常只開放一些 IP才可以連入,通常是維護性質的IP。並且,微軟的Windows Update 網站竟然也沒有開放!

windows update幫我們檢視哪些update 需要上,我們只需要按照指示安裝即可。沒有windows update 工具的輔助,該上的更新自然容易沒上了。

MS10-070 如果在Web Farm 的環境下,需要每個加入 Web Farm 的伺服器都要上這些 update,並且每一個都要試著上上看。如下圖,在Windows Server 2003 Service Pack 2 中,如果有安裝 .NET Framework 2.0 SP2,就需要安裝 KB2418241。如果有安裝 NET Framework 3.50 SP1,就要安裝 KB2416473。如果上述兩個.NET 版本都有安裝,則對應的兩個update都要安裝。

image

我的Case,是Web Farm 中這些伺服器安裝這些更新未上齊,而且每個伺服器上的更新還不一致,導致asp.net 的 viewstate需要 check ViewStateMAC (見EnableViewStateMAC)時,發生解密的錯誤。

解決方法

  • 使用Windows Update,將需要上的更新一次上完。這是最佳建議。
  • MS10-070 所顯示的符合Windows 版本,可能需要更的新Update 一次下載回來。每一個都裝裝看。需要的更新自然就會安裝進去,不需要的更新也不會讓我們更新(如下圖)。

image

2010年12月20日 星期一

換SSL 憑證後,客戶得到未信任的憑證

原由

這次,由於網站的 SSL 憑證到期了,更新了SSL 憑證。更換後,有一家公司抱怨瀏覽網站時,會出現「未信任的憑證」問題。

原因

只有這一位客戶哦!請客戶幫我們看一下憑證的問題,會出現「信任憑證授權單位無法確認這個憑證」的錯誤訊息。如下圖

image

檢視憑證路徑時,也少了一層根憑證。

客戶的電腦
image

正常的狀況
SNAGHTMLc8c1dc

因此,我判斷 Baltimore CyberTrust Root 這個憑證並未在「 信任的根憑證」中。

Debug 步驟

為什麼別的客戶ok,單獨這位客戶有這樣的議題呢?我找到一某一台相同問題的電腦,特別先看了在「 信任的根憑證」中,也相同地沒有這張憑證。

接著,我瀏覽了該網頁,並以 Fiddler 錄下的 Request ,如下圖。

image

答案揭曉。原來當我們瀏覽一個https網頁時,windows 會幫我們檢查SSL 憑證。而SSL 憑證的 CA 尚未匯入時,且是公開常見的CA時,windows update 會自動匯入 CA 任證。

該客戶由於控管嚴格,連 windows update 的 IP 都使用防火牆封鎖了,造成憑證路徑不正確的問題。

結論

雖然只能檢視 https 網站這樣常見的動作,其後隱含了多少工作原理啊。這一次又學到新東西。

2010年9月29日 星期三

讓 Visual Studio 跑 3GB

緣由

在許多狀況,Visual Studio 都會跑的很辛苦,其中一個原因是 Visual Studio 只有 32位元的版本,而沒有 64 位元的版本。至於為什麼微軟不出 64 位元版本,原因很多,詳情見Visual Studio: Why is there no 64 bit version? (yet)

然而,Windows 只能讓32位元的應用程式存取到 2GB的記憶體。對於剛推出32位元電腦的時代(15年前了吧),有4MB記憶體的電腦就已經很高檔了。 對於現在的我來說,我的電腦已有8GB,作業系統也是Windows 7 64位元版,Visual Studio 只能跑2GB 的限制簡直是孫悟空的緊箍咒,真是天大的限制。尤其是跑  CAT.NET 時,需要大量的記憶體,2GB 一下子會出現 out of memory,真是不知道該怎麼辦。

[解法一]

找到了這一篇 Hacking Visual Studio to Use More Than 2Gigabytes of Memory。讚!

由於我是 64位元的系統,對於系統的 3GB修改就免了。直接使用 Visual Studio Command Prompt,執行下面的指令

cd "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE"editbin /LARGEADDRESSAWARE devenv.exe

執行

以下執行 CAT.NET 時,需要2.05 GB 的記憶體。在未操作前,跑到 1.64 GB 就不行了。

image

[解法二]

OutOfMemoryException Fix 這裡則給了另一個解法。由於這是 ReSharper 的公司 jetbrains 給的 solution,但在 windows server 2008R2 + Visual studio 2005 上跑似乎並非預期可以解決該問題。

[20101001] 在 Windows Server 2003 + Visual studio 2005,該方法卻似乎有用,但在最後,還是讓 Visual Studio 2005 掛掉。

image

2010年9月21日 星期二

Spam Email

最近垃圾信愈來愈多,當然一看就刪除。其中有一封假裝是我寄出去的信被退件,內容如下。

SNAGHTML19b2b47

還蠻像的。一看zip 的內容,果然內含 .exe 檔,想騙我執行它,門都沒有。

image

不過說實話,不熟電腦的人,會不會去執行它呢?100個人中有1個去執行它的話,這種技倆就相當有效了。

2010年6月4日 星期五

圖形驗證(4): 使用 Generic Handler 產生圖形

這個系列,請見
(1) 簡介
(2): ASP.NET 簡易實作圖形驗證
(3): ASP.NET 圖形加強版

上一篇加強了圖形後,發現了一個美中不足的部份。圖形是先產了圖檔後,再以 asp:image 元件指到該圖檔,讓使用者可以看圖猜字。但這樣長久下來,會讓圖檔愈來愈多,總有一天會讓硬碟爆掉。雖然可以定下MIS規則讓管理人員定期手動清理,但人是健忘的動物,還是有一天會忘的。

這一次,我們就來加強一下這個部份。

Generic Handler

我們將使用 Generic Handler來解決暫存圖檔的問題。首先新增一個  Captcha.ashx 到網站中。

image

由於在 ashx 中,我們要使用 Session,故必須實作 IRequiresSessionState,如下

public class Captcha : IHttpHandler, IRequiresSessionState 
{

public void ProcessRequest(HttpContext context)
{
  context.Response.ContentType = "image/gif";
  VerifyNow(context);
}

public bool IsReusable
{
  get
  {
    return false;
  }
}

接下來,經過重構之後,之前大部份關於Captcha 圖形驗證的程式都可以搬到 Captcha.ashx.cs 下了。程式如下

Captcha.ashx.cs

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Web;
using System.Web.SessionState;

namespace Captcha.Utility
{
  /// <summary>
  /// Summary description for Captcha
  /// </summary>
  public class Captcha : IHttpHandler, IRequiresSessionState 
  {

    public void ProcessRequest(HttpContext context)
    {
      context.Response.ContentType = "image/gif";
      VerifyNow(context);
    }

    public bool IsReusable
    {
      get
      {
        return false;
      }
    }

    private void VerifyNow(HttpContext context)
    {
      string randomString = context.Session["ImgText"] as string;
      CreateImage(context, randomString);
    }

    

    private void CreateImage(HttpContext context, string imageText)
    {
      //建立一個 Bitmap。寬高未定,故先給定1, 1
      Bitmap bmpImage = new Bitmap(1, 1);

      //指定字型
      Font font = new Font("Verdana", 24, FontStyle.Bold, GraphicsUnit.Point);

      //進行繪圖。繪圖需透過 Grahpics 物件。
      Graphics graphics = Graphics.FromImage(bmpImage);
      //測量文字的寬高
      int width = (int)graphics.MeasureString(imageText, font).Width;
      int height = (int)graphics.MeasureString(imageText, font).Height;

      //重新指定 Bitmap
      bmpImage = new Bitmap(bmpImage, new Size(width, height));

      //重新繪圖
      Random r = new Random();
      graphics = Graphics.FromImage(bmpImage);
      graphics.Clear(r.NextColor()); //使用亂數底色
      graphics.TextRenderingHint = TextRenderingHint.AntiAlias;  //不要鋸齒

      int avgWidth = width / imageText.Length;
      for (int i = 0; i < imageText.Length; i++)
      {
        font = new Font("Verdana", r.Next(12, 24), FontStyle.Bold, GraphicsUnit.Point);
        graphics.DrawString(imageText.Substring(i, 1), font, new SolidBrush(r.NextColor()), avgWidth * i, 0); //把文字畫上去
      }

      graphics.Flush();

      for (int i = 0; i < 10; i++)
        DrawRandomLine(graphics, height, width, r);

      bmpImage.Save(context.Response.OutputStream, ImageFormat.Gif);

      //記得 release 記憶體
      graphics.Dispose();
      font.Dispose();
      bmpImage.Dispose();
    }

    private static Color NextColor(Random r)
    {
      return Color.FromArgb(r.Next(255), r.Next(255), r.Next(255));
    }

    private static void DrawRandomLine(Graphics graphics, int height, int width, Random random)
    {
      Pen pen = new Pen(random.NextColor());
      pen.Width = random.Next(3);
      Point p1 = new Point(random.Next(width), random.Next(height));
      Point p2 = new Point(random.Next(width), random.Next(height));
      graphics.DrawLine(pen, p1, p2);
    }
  }
}
網頁的部份,就只剩下取得密碼及驗證的部份
Sample1.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Sample1.aspx.cs" Inherits="Captcha.Sample1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
      <asp:Image runat="server" ID="image" ImageUrl="~/Utility/Captcha.ashx" />
      <asp:TextBox runat="server" ID="txtAnswer" />
      <asp:Button Text="輸入" runat="server" ID="btnSubmit" onclick="btnSubmit_Click" />
    </div>
    </form>
</body>
</html>

Sample1.aspx.cs

using System;
using System.Text;
using System.Web.UI;

namespace Captcha
{
  public partial class Sample1 : System.Web.UI.Page
  {
    protected void Page_Init(object sender, EventArgs e) 
    {
      if (!Page.IsPostBack)
      {
        CreateImageText();
      }
    }

    protected void btnSubmit_Click(object sender, EventArgs e)
    {
      string randomString = Session["ImgText"] as string;
      if (randomString != txtAnswer.Text.Trim())
      {
        Response.Write("驗證錯誤");
        CreateImageText();
      }
      else
        Response.Write("驗證成功");
    }

    private void CreateImageText()
    {
      string randomString = GetRandomString(4);
      Session["ImgText"] = randomString;
    }

    private string GetRandomString(int length)
    {
      char[] chars = @"23456789ABCDEFGHIJKLMNPQRSTUVWXYZ".ToCharArray();
      Random r = new Random((int)DateTime.Now.Ticks);
      StringBuilder sb = new StringBuilder(length);
      for (int i = 0; i < length; i++)
        sb.Append(chars[r.Next(chars.Length)]);
      return sb.ToString();
    }
  }
}

結論

經過這樣一重構,ashx 的可重用性變高了,也不再需要圖片的暫存檔。

範例下載

圖形驗證(3): ASP.NET 圖形加強版

(1) 簡介(2): ASP.NET 簡易實作圖形驗證後,這次針對圖形太簡單的問題再做加強。

加強1

底色換成亂數取色。為了亂數取色,我寫了一個 extension method,延伸了 Random

using System;
using System.Drawing;

namespace Captcha.Utility
{
  public static class RandomExtension
  {
    /// <summary>
    /// 取得下一個顏色
    /// </summary>
    /// <param name="random"></param>
    /// <returns></returns>
    public static Color NextColor(this Random random)
    {
      return Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
    }
  }
}

因此,可以在換底色時,改成亂數取色。

//重新繪圖
Random r = new Random();
graphics = Graphics.FromImage(bmpImage);
graphics.Clear(r.NextColor()); //使用亂數底色
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;  //不要鋸齒

加強2

讓字型大小也能亂數忽大忽小,並且就亂數取色,我將部份程式修改如下

int avgWidth = width / imageText.Length;
for (int i = 0; i < imageText.Length; i++)
{
font = new Font("Verdana", r.Next(12, 24), FontStyle.Bold, GraphicsUnit.Point);
graphics.DrawString(imageText.Substring(i, 1), font, new SolidBrush(r.NextColor()), avgWidth * i, 0); //把文字畫上去
}

加強3

最後,我再加強甘擾,讓機器人更難以進行 AntiCaptcha,我畫了10條粗細長度顏色不一的線。程式如下

private static void DrawRandomLine(Graphics graphics, int height, int width, Random random)
{
  Pen pen = new Pen(random.NextColor());
  pen.Width = random.Next(3);
  Point p1 = new Point(random.Next(width), random.Next(height));
  Point p2 = new Point(random.Next(width), random.Next(height));
  graphics.DrawLine(pen, p1, p2);
}
...
for (int i = 0; i < 10; i++)
        DrawRandomLine(graphics, height, width, r);

結果

以下是這三個步驟加強後的結果.還不錯呢!

image

結論

看起來不錯,但仍有些美中不足的部份。例如字的顏色如果很接進底色的話,使用者就看不出來了。此時必須讓使用者自行換圖,或者想辦法讓兩者的顏色差異變大。這些小加強就請讀者自行發揮了。

範例程式下載

2010年6月3日 星期四

圖形驗證(2): ASP.NET 簡易實作圖形驗證

接續上一篇的簡介,我們這一次實作一個簡易的 ASP.NET 的圖現驗證。

步驟1: 顯示圖形

一般來說,圖形只能給人工來閱讀,SpamRobot 碰到圖形當然較吃力。這個步驟,我們就先把文字變成最簡單的圖形吧。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Web.UI;

namespace Captcha
{
  public partial class Sample1 : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      if (!Page.IsPostBack)
      {
        CreateImage("I wanna go home");
      }
      image.ImageUrl = ImageUrl;
    }

    //圖檔放置的位置
    private string ImagePath
    {
      get
      {
        return Server.MapPath(ImageUrl);
      }
    }
    //圖檔的 Url。使用 SessionID 避免重複
    private string ImageUrl
    {
      get
      {
        return "~/imgs/" + Session.SessionID + ".gif";
      }
    }

    private void CreateImage(string imageText)
    {
      //建立一個 Bitmap。寬高未定,故先給定1, 1
      Bitmap bmpImage = new Bitmap(1, 1);

      //指定字型
      Font font = new Font("Verdana", 24, FontStyle.Bold, GraphicsUnit.Point);

      //進行繪圖。繪圖需透過 Grahpics 物件。
      Graphics graphics = Graphics.FromImage(bmpImage);
      //測量文字的寬高
      int width = (int)graphics.MeasureString(imageText, font).Width;
      int height = (int)graphics.MeasureString(imageText, font).Height;

      //重新指定 Bitmap
      bmpImage = new Bitmap(bmpImage, new Size(width, height));

      //重新繪圖
      graphics = Graphics.FromImage(bmpImage);
      graphics.Clear(Color.White); //使用白底
      graphics.TextRenderingHint = TextRenderingHint.AntiAlias;  //不要鋸齒
      graphics.DrawString(imageText, font, new SolidBrush(Color.Red), 0, 0); //把文字畫上去
      graphics.Flush();

      bmpImage.Save(ImagePath, ImageFormat.Gif);

      //記得 release 記憶體
      graphics.Dispose();
      font.Dispose();
      bmpImage.Dispose();
    }
  }
}

而網頁使用了簡單的 asp:image

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Sample1.aspx.cs" Inherits="Captcha.Sample1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
      <asp:Image runat="server" ID="image" />
    </div>
    </form>
</body>
</html>

在步驟1中,我使用了 Session 作為圖檔的名稱,儲存在網站的目錄下,並以 asp:image 來顯示圖形。

 

步驟2: 亂數

上一個步驟中,驗證的文字是寫固定地。這個步驟我們就來亂一下吧!

 

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
    string randomString = GetRandomString(4);
    CreateImage(randomString);
  }
  image.ImageUrl = ImageUrl;
}

private string GetRandomString(int length)
{
  char[] chars = @"2346789ABCDEFGHIJKLMNPQRTUVWXYZ".ToCharArray();
  Random r = new Random((int)DateTime.Now.Ticks);
  StringBuilder sb = new StringBuilder(length);
  for (int i = 0; i < length; i++)
    sb.Append(chars[r.Next(chars.Length)]);
  return sb.ToString();
}

顯示的文字,不能讓使用者不小心看錯,例如O 與 0,l, i, 與 1,S與5。為了易於使用,必須將這些容易誤解的字元全部移掉。圖形如下

image

步驟3: 驗證

這是最簡單的步驟了。將驗證用的文字儲存起來,放到 Session中,等待使用者的回應並檢查之。

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
    VerifyNow();
  }
}

private void VerifyNow()
{
  string randomString = GetRandomString(4);
  Session["ImgText"] = randomString;
  CreateImage(randomString);
  image.ImageUrl = ImageUrl;
}

protected void btnSubmit_Click(object sender, EventArgs e)
{
  string randomString = Session["ImgText"] as string;
  if (randomString != txtAnswer.Text.Trim())
  {
    Response.Write("驗證錯誤");
    VerifyNow(); //重新產生驗證文字
  }
  else
    Response.Write("驗證成功");
}

結論

這是一個極簡單的CAPTCHA圖形驗證的範例。雖然已經可以運作了,但仍然有不少的缺點,例如可重用性,使用了Session,以及最重要的是「圖形太簡單」的問題。

由於道高一尺魔高一丈的布袋戲真理,一定有 AntiCaptcha 工具的產生,圖形太過於簡單,等同於不設防。另外驗證文字的長度也太短了些,10000次總有一次會猜中,也是個問題。

範例可在這裡下載

圖形驗證(1): 簡介

在網路上無奇不有,什麼都賣,什麼都不奇怪。

為了許多的商業目的,如商品廣告、網站知名度、色情、甚至詐諞、釣魚等網路詐諞等,有時會在各大留言版、部落格、msn 等地方發一些廣告連結。這些文章、訊息通常不能被接受,通稱為惡意文章或訊息。

這些惡意文意如果以人工的方式發文,那當然費日秏時。因此接著發展出機器人,自動發文,甚至自動註冊帳號。免費的 Spam Robots甚至可自行下載。

使用人工來發這些帶有其他目的之訊息,通常不為原網站及網站使用者所喜。為了防止這些不正常目的惡意文章、帳號註冊,常用的防堵方式就是圖形驗證,(英文縮寫為 CAPTCHA),確保的確是由使用者正常的發文,而非機器人。這些圖形(如下圖例),通常希望讓人以目視的方式讀出驗證的通關密碼,防止機器人的攻擊。

然而有攻有防,有圖形驗證,就有破解圖形驗證。PWNtcha 就是一套這樣的工具,並且解釋了各式各樣的 CAPTCHA 及對應的破解率。

個資法通過的今天,圖形驗證已經是必要的加強網站安裝的設計。下一篇會為大家寫一篇 ASP.NET 上CAPTCHA的實作。

Share with Facebook