August 2008 - Posts

Trixie Script: jQuery Plugin評分整合

Plugin眾多也是讓jQuery威力無窮的重要因素,不過每回遇到需求,尋找現成的Plugin卻很花功夫。

jQuery官網有個Plugin大總匯: http://plugins.jquery.com/,蒐集了很多的Plugin,分門別類,並逐一列出網站、文件、Demo等連結,資訊非常豐富。它甚至也提供了使用者評價(Rating)的機制,對我來說很受用。尤其當同一需求有很多選擇時,往往讓人無所適從,此時看看別人怎麼說,拿香跟著拜準沒錯!

不過Plugin網站在設計時,並沒有把Rating直接放在分類清單上,所以得一一點選開啟詳細檢視才能得知評價。如果直接在清單上顯示評價,就可以優先考慮票數多評價高者,勢必可大量節省翻找查看的時間;但網站是別人寫的,寫信請開發者發發佛心修改一下嗎? 當然也是辦法,但天助自助者,謝謝老天爺,我們有Trixie!!

以下的Trixie Script借用了jQuery的神奇力量(因為是jQuery網站的網頁,當然有Include jquery.js),簡單幾行就把Rating提取到清單頁上了,有需要的朋友就挾去配吧!

// ==UserScript==
// @name          Show jQuery Plugin Rating
// @namespace     http://www.darkthread.net
// @description      Show jQuery Plugin Rating
// @include       http://plugins.jquery.com/project/Plugins/category/*
// ==/UserScript==
(function()
{
    $("#project-overview H2").each(function() {
        var h2 = $(this);
        var a = h2.find("A");
        $.get(a.attr("href"), null, function(data) {
            var newData = data.replace(/star avg on/g, "");
            var stars = ((data.length - newData.length) / 11);
            var p1 = data.indexOf("rating-num-votes-");
            var votes = 0;
            if (p1 > 0)
            {
                var p1 = data.indexOf("\"", p1 + 16); //"
                var p2 = data.indexOf("<", p1 + 1);
                var votes = data.substring(p1 + 2, p2);
            }
            
            h2.append("<span style='color:red;font-size:9pt;'>&nbsp;&nbsp;Rating:"
+ stars + "&nbsp;("+votes+" Votes)</span>");
            
        });
    });
})();

VM平台的新選擇: Hyper-V

前些時候,我有篇Post提到我為了兼顧記憶體使用效率、應用程式相容性在Windows 2003 x64與Vista x64間左右為難,而不管何者,Virtual Machine的需求都是少不了的,網友Blair Chen提了個好建議,Why not Hyper-V?

Hyper-V是Windows 2008 x64 Standard、Enterprise、DataCenter Edition裡附加的新功能,RTM版本已於2008/06/26釋出。簡單來說,它將會取代原本Virtual Server 2005扮演的角色,但在架構及表現上,Hyper-V顯然更能實踐單一伺服器承載多台VM的理想。

雖然Hyper-V有許多新的強化,例如: 支援多CPU/x64的Guest OS、對Cluster架構的額外支援等等,不過以我單純的應用需求來說,所有的注意力都只集中在一點上: 速度。

Hyper-V在架構上做了很大的改良,VM與實體機器間的溝通簡化許多,因此VM的執行效率大大提升。擺脫模擬虛擬機器過程的層層損耗,應該可以終結在勇猛Core 2 Duo上的VM活像台486的惡夢,但這都是理論,實務上真的可以產生這麼明顯的差異嗎?

Michael O'Donovan在MSDN Blog上發表了一篇Virtual Server 2005R2 vs Hyper-V大車拼的數據。在一模一樣的硬體上分別安裝Vista x86+Virtual Server 2005及Windows 2008+Hyper-V,都用一個2G RAM+43G HD的VM執行Windows 2003+MOSS2007+SQL2005,並用Visual Studio 2005 Team Edition for Software Testers進行壓力測試。從數字上來看,Hyper-V的表現,足足比Virtual Sever 2005快了一倍以上,這是一個選擇Windows 2008的有力因素。

我自己實測的結果,Hyper-V與Windows 2008的結合相當緊密,預設VM會隨著Host OS關機時暫存狀態,一開機又立即還原啟動,而且暫存與還原的速度比Virtual Server快上許多,非常適合在一台機器上掛上多個Server VM提供服務以節省硬體的應用情境。另外,Virutal PC有但Virtual Server不支援的NAT功能(VM不需正式IP,可透過Host OS連上網路),在Hyper-V上又重現了。

不過,要執行Hyper-V有些硬體限制,CPU與BIOS要支援硬體虛擬化,這點可以用CPU檢測軟體(推薦Securable)確認。另外,Windows 2008在啟用Hyper-V後就不再提供Sleep及Hibernation的功能,不過應無大礙。

經過這番評量,我想這回的平台抉擇,應該會是家機用Vista x64,工作機用Windows 2008 x64 + Hyper-V的組合。

jQuery Bug: Defective Clone

I tried to append several dynamic tables to a DIV container and found something interesting.

<div id="divContainer">
    <table></table>
</div>
<script type="text/javascript">
$(function() {
    var div = $("#divContainer");
    var table = div.find("table");
    var c = 0;
    for (var i = 0; i < 3; i++) 
    {
        table = table.clone();
        div.append(table);
    }
    alert(div.children().length);
    alert(div.html());
});
</script>

What will 'div.children().length' be? It should be 4 in this case, but you will get 3 in IE7 and 4 in Firefox 3. The 'alert(div.html())' provide more detail.  In IE7, the div.html() looks like this:

<TABLE jQuery1218765772477="227"><TBODY></TBODY></TABLE>
<TABLE jQuery1218765772477="228"><TBODY jQuery1218765772477="null"></TBODY></TABLE>
<TABLE jQuery1218765772477="null"><TBODY jQuery1218765772477="null"></TBODY></TABLE>
<TABLE jQuery1218765772477="null"> <TBODY jQuery1218765772477="null"></TBODY></TABLE>

And div.html() will return blow result in Firefox3:

<table></table><table></table><table></table><table></table>

It seemed that jQuery added additional identification information (jQuery1218765772477 attribute) in IE and some of them are 'null'.  After more experiments, I found if I modified the code to:

table2 = table.clone();
div.append(table2);

I got div.children().length==4 and

<TABLE jQuery1218765990513="231"><TBODY></TBODY></TABLE>
<TABLE jQuery1218765990513="232"><TBODY jQuery1218765990513="null"></TBODY></TABLE>
<TABLE jQuery1218765990513="233"><TBODY jQuery1218765990513="null"></TBODY></TABLE>
<TABLE jQuery1218765990513="234"><TBODY jQuery1218765990513="null"></TBODY></TABLE>

Every table got a unique jQuery1218765990513 attribute, so the jQuery.unique() didn't filter out the extra 'null' attribute table object .  I don't think "table = table.clone()" is illegal syntax and this should be a bug of jQuery.clone().

I just submitted this bug to http://dev.jquery.com/newticket.  If there is any update, I will post it on my blog.

【中文摘要】

明明在趕程式,被這個Bug絆住,又跟它耗了大半天。利用clone()的寫法在DIV中動態新增Table object,卻發現明明放了4個,children().length卻只傳回3,但這問題只發生在IE上,Firefox上是正常的。研究了一下,發現clone()在IE下會產生額外的Attribute識別,而使用table=table.clone()的寫法,會讓這些識別Attribute變成null,在算個數時就會被過濾掉,看來是jQuery.clone()的Bug,暫無氣力追進去修改,但我先把它Submit反應出去,如果有消息再跟大家說吧。

Stopwatch.ElapsedTicks的祕密

這次的程式魔人賽,在先前的範例中,用的是Stopwatch.ElapsedTicks做為計數單位。

發現一件好玩的事,我在自己的機器上用DummyPlayer來跑,每一次就算胡亂猜也要近1,000 Ticks。但我接到一組參考數字,DummyPlayer在Q9300上跑,每次大約10-20 Ticks!!

不會吧?? Q6600輸Q9300這麼多?? 接著,更扯的事出現了,另一組DummyPlayer在PentiumD 920上的測試數據,Ticks數也不到100,我的Q6600是中了詛咒嗎?

這讓我想起之前研究過Thread.Sleep精確度的問題,大概有個結論是,計時的精確度與主機板、BIOS、OS有關係。再一查證,Q9300與PentiumD 930用的都是Asus的主機板,加上用Stopwatch計算int i=1做一次跟做10次的ElapsedTicks差不多,大概就有了初步推論(後來證實是錯的),這是不同硬體下造成的精準度的差異,而Asus的主機測量的Tick精確度較高。

會做出以上的推論,是基於一個錯誤的假設: 一個Tick代表的時間長度放諸四海皆同(誤)。

Google到Stopwatch.Frequency的MSDN文件,終於真相大白: 一個Ticks代表的時間長度會隨著硬體不同而有差異。例如我們可以用以下的Code在不同機器上做比較。

using System;
using System.IO;
using System.Threading;
using System.Diagnostics;
 
public class CSharpLab
{
    public static void Test()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        int k = 0;
        sw.Stop();
        Console.WriteLine("Ticks={0:N0}", sw.ElapsedTicks);
        Console.WriteLine("Freq={0:N0}", Stopwatch.Frequency);
        decimal ns = 1000000000M / Stopwatch.Frequency;
        Console.WriteLine("1 Tick = {0:N4}ns", ns);
    }
}
 

測試結果,我的Q6600工作機Freq=2,400,730,000(太約就是2.4Ghz,等於Q6600的CPU內頻),而Asus主板上測得Freq=3,579,545,相差了670倍,也就是說,在我的旗艦上,1 Tick = 0.4165 ns,Asus主板則為 1 Tick = 279.3651ns。如果換算回ms,則1200 Ticks與20 Ticks的時間長度就不會相去太遠。

經過了這番探索,得到了新結論:

  1. 不同硬體上,每個Tick代表的時間長度可能不同
  2. 每秒Tick數的極限應該就是CPU的內頻大小 (不過可測出的最小時間間隔也要好幾百Ticks)
  3. 測試結果比對時,Asus主板的Tick數少,反而是因為其Tick精確度較低所致(跟原來猜想的剛好相反)
Posted 15 August 2008 06:49 AM by Jeffrey | no comments
Filed under: ,
SQL2008 RTM來了

雖然Lag了好幾天,但還是要寫一下。SQL 2008 RTM於8/6正式釋出了,MSDN的訂戶已經可以去下載嚐鮮。

依我自己的安裝經驗,要先安裝以下兩個更新: (安裝程式會提示)

執行身份的地方多了不少選擇,不再像以前預設用Local System不知不覺就混過去,文件上建議使用不具管理者身份的Domain/Local User Account來跑服務,可以提升安全性,逼使用者要認真思考一下採用的身份,不能閉著眼睛按下一步晃過去。

裝好後開啟SQL Server Management Studio,不像上回SQL 2000->SQL 2005的大改版,管理介面上跟SQL 2005的差異不大。

我稍稍試了一個查詢,最明顯的改善是編輯視窗比照Visual Studio,多了欄位、資料表名稱自動提示的Intellisense功能,讓人小小感動了一下。

預估工作上要實際用到SQL 2008還要點時間,再找時間慢慢熟悉。

【茶包射手專欄】ODP.NET Internal Error -3000

討厭的ORACLE又來找麻煩了。(好吧! 我承認我對ORACLE有成見)

同事將在其他台機器運作正常的ASP.NET程式移到自己的PC上執行,卻一直遇到以下錯誤:

Oracle.DataAccess.Client.OracleException: 資料提供者內部錯誤(-3000)
英文: Data provider internal error(-3000)
[System.PlatformNotSupportedException: 目前的平台不支援 ResourcePool。
英文: 'ResourcePool' is not supported on the current platform.
於 System.EnterpriseServices.Platform.Assert(Boolean fSuccess, String function)
於 System.EnterpriseServices.Platform.Assert(Version platform, String function)
於 System.EnterpriseServices.ResourcePool..ctor(TransactionEndDelegate cb)
於 Oracle.DataAccess.Client.ConnectionPool..ctor(OpoConCtx opoConCtx)
於 Oracle.DataAccess.Client.ConnectionDispenser.CreateConnectionPool(OpoConCtx& opoConCtx)]

錯誤發生在ODP.NET要開啟連線時。

一開始我懷疑是ODP.NET 9207連線Oracle 10g的版本相容問題,不過確認過有許多成功案例後排除這個可能。既然這次的錯誤訊息很明確(雖然有少量中翻英的工作,但幸好不難翻),就用力Google吧!

最後找到了這篇文章,照著regsvr32 system32\com\comadmin.dll,再IISRESET(不可省略)後問題排除,收工回家。

【茶包射手專欄】選擇性貼上的黑白人生

我不是Excel重度依賴者,對於Excel的一些花式應用只懂皮毛。

負責帳務的同事教了我一招"選擇性貼上"的妙用。就是可以將Excel中的一部分用剪貼簿(Clipboard)複製下來,再使用選擇性貼上(Paste Special)成中繼檔(Metafile)的方式貼到PowerPoint裡。這種做法比把Excel試算表內嵌(Embedded)到投影片來得輕巧,既可以完整保存在Excel中看到的樣子,比起擷取螢幕畫面存成GIF/PNG再貼到投影片,多了任意縮放不走味的向量特性,實在是很不錯的做法。

不過,現在遇到的困擾是:

  • 不知曾幾何時,貼上彩色內容的功能忽然消失,貼上的樣式不變,但全是黑白的
  • 貼貼樂變成黑白後,同事找了同部門的幾台機器測試,發現大家都是黑白的
  • 另一部門同事的機器,就還可以貼上帶顏色的中繼檔,後來都將Excel寄給該同事請她代貼後再寄回
    (該同事還得意地說: 她的肝比較好,所以人生是彩色的... XD)
  • 幾天前,原本可以貼彩色中繼檔的同事機器也淪陷了,變成只能貼黑白
    (那麼,該去檢查肝功能了嗎?)

綜合以上,大家的結論是: "明明沒有修改什麼設定或安裝程式/更新,原本可用的功能忽然壞掉,莫非真的大家肝都出了狀況?"

接下了這個問題,回到自己機器上試了一下。慘了! 我的肝也不好耶~~~ 剪下五顏六色的試算表,選擇性貼上成中繼檔只得到黑白的結果...

這問題不難,用對關鍵字: Paste Special, Metafile, Black and White去Google一下,馬上就得到答案,先前的一堆靈異現象也都有了解釋:

  1. 貼上中繼檔是否為彩色由預設印表機是黑白或是彩色決定
  2. 同事們可能原本預設了彩色印表機,後來改設另一台黑白的,但沒有意識到這會與選擇性貼上的結果有關,所以認知上是"什麼都沒做,它自己就壞掉了"。
    ** 這是茶包學中很經典的情境,使用者非常確信"自己什麼都沒做",但事實上使用者自己(或者所有人)都認為沒關係的操作是關鍵 **
  3. 而同一部門預設印表機多指向同一台黑白印表機,所以大家一起變黑白。

要解決以上的問題,可將預設印表機先改設成彩色印表機上,處理完再改回來。如果嫌麻煩,還有一招,Excel剪貼簿中有個"複製成圖片"(Copy Picture)的功能,用它來取代單純的複製,也可以克服彩色變黑白的問題。

參考資料:  Excel content turns black and white (B&W), loses color when copy/pasted into PowerPoint

RFC-黑暗盃程式魔人賽考題

前陣子在Blog上宣告要辦程式魔人賽的事,還祭出了VSTS2008+MSDN當大獎,說好八月上旬要公佈辦法,結果這陣子也不知在忙什麼,搞得焦頭爛額,連Blog文章都寫沒幾篇,更不用說構思比賽考題的事了。

出來混,遟早要還的。拼了老命,還是把題目給擠出來。先前有提過,遊戲規則會參酌大家的意見,以RFC方式提出,做些微調再定案。所以我先說明草擬的規則並釋出題目程式碼,大家可以開始先玩玩,即日起到2008/08/17 00:00前接受大家留言Call-In給建議,正式規則在8/17後公布。

我寫了一個GameHost的程式,可以指定數字範圍(maxNum)、數字位數(digits),決定題目的困難度,例如: maxNum = 10, digits = 4,可用的數字是0-9,就是我們人腦在玩的1234 2A1B標準猜數字遊戲。要挑戰的人要寫一個Class繼承Player這個Abstract Class:

public abstract class Player
{
    protected int _maxNum, _digits;
    public virtual int[] StartGuess(int maxNum, int digits)
    {
        _maxNum = maxNum;
        _digits = digits;
        return null;
    }
    public abstract int[] GuessNext(Hint lastHint);
 
    public static Hint Compare(int[] answer, int[] guess)
    {
        int a = 0, b = 0;
        for (int i = 0; i < answer.Length; i++)
            for (int j = 0; j < guess.Length; j++)
            {
                if (answer[i] == guess[j])
                    if (i == j) a++; else b++;
            }
        return new Hint(a, b);
    }
 
    public string GetPalyerName()
    {
        return this.GetType().ToString();
    }
}

為了示範Player的寫法,我實作了一個只會用亂數胡猜、好傻好天真的DummyPlayer(四位數應該平均要猜5000次才會中吧!)

public class DummyPlayer : Player
{
    private int[] _currAnswer = null;
    private Random _rnd = new Random();
 
    private void randomGuess()
    {
        List<int> lst = new List<int>();
        for (int i = 0; i < _digits; i++)
        {
            int r = _rnd.Next(_maxNum);
            while (lst.Contains(r))
                r = _rnd.Next(_maxNum);
            lst.Add(r);
            _currAnswer[i] = r;
        }
    }
 
    public override int[] StartGuess(int maxNum, int digits)
    {
        base.StartGuess(maxNum, digits);
        _currAnswer = new int[digits];
        randomGuess();
        return _currAnswer;
    }
    public override int[] GuessNext(Hint lastHint)
    {
        randomGuess();
        return _currAnswer;
    }
}

遊戲主持人跟好傻好天真挑戰者的Code可以按這裡下載,放進Mini C# Lab中就可以跑了。

重點來了,比賽規則如下:

  1. 參賽者請撰寫一個繼承Player的C# Class,以提供Source Code的方式寄到指定Email信箱參賽。
  2. 參賽者提供的Source Code會整合到前述的遊戲主持人程式碼中,以Mini C# Lab於大會指定的機器上執行,比賽場地有個: Q6600+8G RAM實體機(我的旗艦工作機,簡稱香格里拉)、於該實體機上執行的WinXP 1G RAM VM(簡稱惡魔島)
  3. 參賽者程式將於香格里拉與惡魔島進行(maxNum/digits): 10/4, 16/6, 20/8, 32/10, 64/12, 256/16, 1024/32七種難易程度不同的猜數字挑戰,每種題目各跑五次,計算次數及耗用時間取平均值。
  4. 每次猜數字挑戰最長耗用時間不得超過30分鐘,超過即算挑戰失敗。(我不要陷入河內之塔地獄呀)
  5. 由於是x86 OS,Process有2G的記憶體限制,請節約使用記憶體,想出"暴力攻擊"以外的手法。(這才是有挑戰性的趣味所在吧?)
  6. 可使用Multithreading解題加快速度。(香格里拉有4核,惡魔島只有單CPU)
  7. 禁止使用資料庫或檔案作為輔助儲存空間。(禁用的理由是,這麼做很容易又變成另一種暴力攻擊法,但我也擔心會不會禁用後高階的題目就沒解? 我也在猶豫,歡迎大家提供意見)
  8. 名次計算方式: 共會有7(10/4, 16/6...) * 2 (香格里拉+惡魔島) * 2(比次數少、比時間短) 28場比賽,每場比賽取前三名,第一名得10分,第二名得5分,第三名得3分,解出答案得2分,逾時、記憶體用盡、發生錯誤則得0分。以28場比賽的積分總和決定最後名次,第一名就可以將VSTS2008+MSDN抱回家。
  9. 主辦單位也會派出一位DarkPlayer攪局參賽,其積分會列入排名,但無領獎資格。(大家放心,它只算得出10/4, 16/6, 20/8三種,其餘一律Out of memory)

以上就是題目跟比賽規則,給大家七天鑑賞期,有任何意見或想法,請留言提出。(大會保留接受與否的權利,若未被採納請見諒)

另外,想參加的人請在8/17前寄信到"iwantvsts2008  @  darkthread.net"預先報名(為防Spam, 請將其中的空白移除才是電子郵件信箱),讓我掌握參賽人數,或許會調整比賽規則以切合實際狀況。

 

VSTS2008+MSDN在等著各位呢! 加油~~

TIPS-在Windows 2003/2008上安裝Windows Live Messenger 2008

如果你跟我一樣工作用的OS是Windows 2003,看到Live Messenger出了8.5版(2008版),興沖沖地連上網站、下載、安裝,應該馬上會被這個訊息澆了一頭冷水...

抱歉,Windows Live 程式無法在 Windows Server、Windows XP Professional x64 Edition,或 Windows XP Service Pack 2 之前的 Windows 作業系統上安裝。

Sorry, Windows Live programs cannot be installed on Windows Server, Windows XP Professional x64 Edition, or Windows operating systems earlier than Windows XP Service Pack 2.

原本我都乖乖地繼續用舊版Messenger,最近在測試Windows 2008又遇上裝Messenger的需求,順手Google了一下,沒想到找到了在這些安裝程式"宣稱"不支援的OS版本上安裝Live Messenger的方法。

原來,Windows Live安裝程式只是個總管,Live Messenger、Liver Writer等都另有各自MSI安裝檔。說來好笑,安裝程式雖然不給裝,若直接執行這些個別MSI安裝檔,卻又可以順利安裝並執行無誤。

因此,只要有辦法取得這些MSI安裝檔就可以在Windows Server OS上享用Live Messenger最新版了。網路上可以找到一些下載點下載這些MSI檔案,但我對非官方提供的程式下載有很深的戒心(擔心裡面藏著一匹木馬或300個斯巴達戰士),還是習慣使用官方網站取得的檔案。Google一下,有不少文章都介紹了這個小技巧: 找一台安裝過新版Live Messenger的XP或Vista,開啟\Program Files\Common Files\WindowLiveInstaller\MsiSources目錄(它被設定了作業系統檔案屬性,對檔案總管來說是隱形的,可以調整檔案總管的檢視選項讓它現形,或是直接在網址手動輸入完整路徑即可找到它)。

MsiSources下有多個檔名包含GUID的MSI檔(視該Client裝了幾項Live家族軟體而定),我們可以由檔案摘要查出何者是Live Messenger的安裝檔。

把找到的MSI Copy到Windows 2003/2008上,點兩下,從此就可以過著幸福快樂的日子囉!

小測微軟SQL Injection漏洞掃瞄工具

微軟日前推出了可以掃瞄ASP原始碼是否有SQL Injection漏洞的工具,我的第一個念頭是,They really did it?

在我的認知裡,原始碼分析工具最有挑戰性的部分在於要能順著程式的邏輯跑,而不單只從字面上查,例如: Request("id")被指定成變數id,傳給函數GetInfo(id),函數中再呼叫RunGetInfoSel(id),使用者輸入的參數經過三手才被拿來組SQL指令字串(危險,勿學),除非分析工具一路追進函數中,才能解析出這裡隱含了SQL Injection的漏洞。換著角度想,分析工具幾乎要有假裝自己在執行程式碼的能力,才不容易發生疏漏。

高深的工程被做成免費的工具,當然是好事。但我對它的犀利度存疑,於是下載了工具,並寫了以下的程式來考驗它一下。以下的ASP程式裡,我故意搞了三處SQL Injection漏洞(再次警告,錯誤示範,勿學),用msscasi_asp.exe掃瞄:

   1:  <%
   2:  Dim id, sql, cnStr
   3:  cnStr = "Provider=MSDAORA;Data Source=TTT;User Id=xxx;Password=xxx;"
   4:  id = Request("id")
   5:  '以下寫法隱含SQL Injection漏洞,千萬不可學
   6:  sql = "SELECT * FROM X WHERE ID='" & id & "'"
   7:  RunSql sql
   8:  RunSql2 id
   9:   
  10:  Dim cnY,rsY
  11:  Set cnY=Server.CreateObject("ADODB.Connection")
  12:  cnY.Open cnStr
  13:  Set rsY=Server.CreateObject("ADODB.Recordset")
  14:  rsY.Open sql, cnY
  15:  Response.Write rsY("D")
  16:  rsY.Close
  17:  cnY.Close
  18:  Set cnY=Nothing
  19:   
  20:  Sub RunSql(sql)
  21:      Dim cnY,rsY
  22:      Set cnY=Server.CreateObject("ADODB.Connection")
  23:      cnY.Open 
  24:      Set rsY=Server.CreateObject("ADODB.Recordset")
  25:      rsY.Open sql, cnY
  26:      
  27:      Response.Write rsY("D")
  28:      rsY.Close
  29:      cnY.Close
  30:      Set cnY=Nothing
  31:  End Sub
  32:   
  33:  Sub RunSql2(id) 
  34:      Dim cnY,rsY
  35:      Set cnY=Server.CreateObject("ADODB.Connection")
  36:      cnY.Open 
  37:      Set rsY=Server.CreateObject("ADODB.Recordset")
  38:      '以下寫法隱含SQL Injection漏洞,千萬不可學
  39:      sql = "SELECT * FROM X WHERE ID='" & id & "'"
  40:      rsY.Open sql, cnY
  41:      Response.Write rsY("D")
  42:      rsY.Close
  43:      cnY.Close
  44:      Set cnY=Nothing
  45:  End Sub
  46:  %>

執行結果不太理想,工具只抓到第14列一處,將有問題的SQL傳入函數執行,或是將Request("id")傳入函數中再直接組SQL,都成了漏網之魚。因此,若把第14列Remark起來,工具就找不出任何漏洞!!

結果讓人有些失望,但不意外! 要寫出可以"跑"VBScript程式的工具本來就不是簡單的事,更何況它是免費工具。大家在使用這類工具時,要把握一個原則: 有抓到表示有問題,沒抓到不代表沒問題。

自動化工具可以偷懶省工,但總難免疏漏,腳踏實地逐一人工Review,對我來說還是最可靠的方法。如果你不幸有幸在帶領團隊開發網站,記得要在動手前再三強調SQL Injection知識的宣導,可以省去事後補破網要花的龐大人力物力。

PS: 之前保哥寫過文章介紹HP提供的另一套免費偵測工具--scrawlr。做法與MS的這個工具上不太相同,並不分析程式碼本身,而是模擬這陣子很流行的游擊式SQL Injection攻擊的手法,以QueryString方式測試網站有沒有漏洞,比較屬於黑箱測試性質,涵蓋度有限,但如果只是想拿來證明網站沒穿衣服,倒是夠用。

【延伸閱讀】

Search

Go

<August 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456
 
RSS
【工商服務】


BlogLook Score and Rank

Syndication