2011年12月20日星期二
[Security]SQL injection的簡介與預防
前言
『程式不是會動就好!』,在安全性上的設計,更是完全的貼切這句話。如果設計出在裸奔的網站(請參考黑大的文章),就算網站上的功能可以正常運作,但千瘡百孔的網站,可能淪為人家的玩物或是提款機。
SQL injection的問題,在前幾年掀起了不少次旋風,甚至包括現在可能還有一堆網站有著同樣的問題,要命的是,根本不需要到駭客等級,就可以把有SQL injection問題的網站搞掛。一個程式設計師寫出來的程式,最要不得的就是有SQL injection的問題,我個人認為那是程式設計師不夠專業,甚至不夠格的表現。這不需要多高深的技巧跟學問,要嘛就是程式設計師偷懶,要嘛就是還不夠專業。
這篇文章簡介一下,SQL injection的基本原理,以及基本的防範措施。
什麼是SQL injection
回到之前重構系列的第一篇文章:[ASP.NET]重構之路系列v1 – UI, Business logic, Data access概念分開
畫面:
需求:
當輸入的帳號密碼,在資料庫中有吻合的資料,代表帳號密碼是對的。(再強調一次,一般設計驗證密碼的部分,應該是透過畫面上輸入密碼的值進行hash,再與資料庫中該帳號所對應hash完的密碼比對,以保障密碼不是以明文存在於資料庫中,確保密碼無法被還原)
直覺設計且造成SQL injection問題的程式碼:
view source
print?
01 protected void Verify_Click(object sender, EventArgs e)
02 {
03 string connectionString = @"myConnectionString";
04 int count;
05 using (SqlConnection cn = new SqlConnection(connectionString))
06 {
07 cn.Open();
08 string sqlStatement = @"Select Count(1) From SomeTable Where ID= '" + this.Id.Text + "' AND Password= '" + this.Password.Text + "'";
09 SqlCommand sqlCommand = new SqlCommand(sqlStatement, cn);
10 count = (int)sqlCommand.ExecuteScalar();
11 }
12
13 this.Result.Text = (count > 0) ? "Pass" : "帳號或密碼錯誤";
14 }
這樣的程式碼會有什麼問題? 問題可大了! 假設我是壞人,知道或猜測這功能的SQL是這樣串的(大部分功能都很好猜的,猜錯了也不會被咬),那麼我只要在畫面上的Id,隨便輸入個值,接著在密碼的部分,輸入' OR 1=1; --
這時候,這一支聰明的功能就可以把完整的SQL statement組出來,變成:
view source
print?
1 Select Count(1) From SomeTable Where ID= '隨便輸入' AND Password ='' OR 1=1; --
輸入這樣的值代表什麼,代表所有畫面上的輸入值都無所謂,因為1=1恆等式一定會成立,且前面的condition為OR,所以可以把前面的where condition都忽略掉。後面再補上個分號,代表這一個SQL子句已經結束,最後再補上--,代表後面的sql為註解。
就這樣,最基本的SQL injection就成功了。是的,這個網站在裸奔了。
如果你以為,只有登入頁面會存在這樣的問題,或是這樣的問題影響不大,那就大錯特錯了。通常會寫出這樣程式的人,如果又都是自己設計,那洞就不只一個。首先,DB的存取帳號,可能就是預設的sa或admin,也就是權限開到最大。這時候的SQL injection要進DB做事,就跟進自己家廚房一樣,例如:
view source
print?
1 Select Count(1) From SomeTable Where ID= '隨便輸入' AND Password ='' OR 1=1; DROP DATABASE pubs --
恭喜你,你DB中的pubs這個DataBase就被Drop掉了。
駭客高興的話,也可以針對sysobjects跟syscolumns來瞭解你DB中有哪些table, 欄位,再比對一下網頁的資料,接著透過Update的語法,把相關的欄位資料加入一些html tag或惡意的程式碼,進而引發從SQL injection觸發的Cross-site Scripting(XSS攻擊),常見的結果就是連到那一頁時,可能被導到別頁,或是XX政府網站上被掛上特殊的國旗,再來就是莫名其妙的個資外洩。
這些情況充斥在我們的生活中,這一切的原罪,都是因為程式設計師的偷懶或不專業。
除了上述的例子,還可以怎麼瞭解SQL的組成?以ASP.NET來說,一樣,通常會寫出那樣有問題的程式,web.config可能也沒有設定custom error頁面,所以當程式出錯時,IIS就大剌剌的幫你把程式錯誤的資訊show在網頁上(就是黃頁的那個),要讓錯誤資訊是掛在SQL statement執行錯誤,是一件再簡單不過的事。所以,要瞭解該網頁的輸入和對應SQL的組成,根本不需要駭客等級就可以做。瞭解之後,要啟動SQL injection,也就只是易如反掌的事。
如何避免SQL injection
簡單的說,過濾輸入值。
但,攻擊手法相當多種,要過濾的字元組合可能一個都漏不得,所以自己設定黑名單來進行過濾,是一件非不得以才做的事。如果是用ASP.NET寫,那所有人的強烈建議,就是使用Parameters。
Parameter的用法相當簡單,這也是為什麼我前面會說,寫出SQL injection問題的程式碼,是一種偷懶的行為。
對應剛剛上面的範例,使用Parameter的方式來改寫:
view source
print?
01 protected void Verify_Click(object sender, EventArgs e)
02 {
03 string connectionString = @"myConnectionString";
04 var id = this.Id.Text;
05 var password = this.Password.Text;
06
07 int count;
08 using (SqlConnection cn = new SqlConnection(connectionString))
09 {
10 cn.Open();
11 string sqlStatement = @"Select Count(1) From SomeTable Where ID= @id AND Password= @password";
12 SqlCommand sqlCommand = new SqlCommand(sqlStatement, cn);
13
14 ////定義parameter型別
15 sqlCommand.Parameters.Add("@id", SqlDbType.VarBinary);
16 sqlCommand.Parameters["@id"].Value = id;
17
18 ////讓ADO.NET自行判斷型別轉換
19 sqlCommand.Parameters.AddWithValue("@password", password);
20
21 count = (int)sqlCommand.ExecuteScalar();
22 }
23
24 this.Result.Text = (count > 0) ? "Pass" : "帳號或密碼錯誤";
25 }
透過使用parameter,在SqlCommand執行時,會自動過濾掉可能造成問題的字元。
另外,SQL injection並不只會發生在where condition,也有可能發生在Order by等語法中。所以只要是畫面上可能被改變的值,要串到SQL語法中,就應該使用parameter。如果是Parameter無法使用的語法,例如Table的名字,那也應該自己建立一個mapping module,來避免畫面上user可任意輸入且可能為惡意攻擊碼的值,直接存進DB中或被非預期地執行。
結論
在patterns & practices Developer Center簡單歸納出三個步驟防止SQL injection:
1. Constrain input.
2. Use parameters with stored procedures.
3. Use parameters with dynamic SQL.
2011年12月13日星期二
極速理解設計模式系列:簡單工廠模式(Simple Factory Pattern)
四個角色:抽象產品(Product)、具體產品(Concrete Product)、工廠(Creator)、用戶端(Client)
抽象產品(Product):需要創建的各種產品的父類。這類產品有共同的介面。
體產品(Concrete Product):需要創建的具體物件。
工廠(Creator):內部邏輯可以控制生成目標物件。
用戶端(Client):實例化工廠,然後工廠根據傳入參數得到各種產品。調用產品實現不同功能。
實現思路:首先將工廠產生實體,然後使用工廠創建產品賦值給抽象產品的引用,然後通過抽象產品的公共介面調用具體產品的方法以實現功能。
類圖:
應用場景:蘋果公司的工廠生產iphone 4、ipad 2、ipod nano 6。
分析:這裡多種產品都可以運行,所以有一個公共方法,然後抽象為父類。
下面我們在控制台程式去演示一下如何使用Simple Factory Pattern:
一、抽象產品(Product):
//抽象產品(Product)
abstract class Apple
{
public abstract void Run();
}
二、具體產品(Concrete Product):
//具體產品(Concrete Product)
class Iphone : Apple
{
public override void Run()
{
Console.WriteLine("iphone 4 開始運行!");
}
}
//具體產品(Concrete Product)
class Ipad : Apple
{
public override void Run()
{
Console.WriteLine("ipad 2 開始運行!");
}
}
//具體產品(Concrete Product)
class IpodNano : Apple
{
public override void Run()
{
Console.WriteLine("ipod Nano 6 開始運行!");
}
}
三、工廠(Creator):
//工廠(Creator)
class AppleFactory
{
public Apple CreateApple(string productName)
{
switch (productName.ToUpper())
{
case "IPHONE":
return new Iphone();
case "IPAD":
return new Ipad();
case "IPODNANO":
return new IpodNano();
default:
return null;
}
}
}
四、用戶端(Client):
//用戶端(Client)
class Program
{
static void Main(string[] args)
{
AppleFactory factory = new AppleFactory();
Apple iphone= factory.CreateApple("iphone");
iphone.Run();
Apple ipad = factory.CreateApple("ipad");
ipad.Run();
Apple ipodnano = factory.CreateApple("ipodnano");
ipodnano.Run();
Console.ReadLine();
}
}
2011年12月5日星期一
網站常用技巧
1.不管是IE那個版本都規定為IE8使用
2. 關閉自動完成功能
3.Title和keywords寫法
到底我們的Title屬性應該怎麼寫呢?我相信大部分人的網站title都是這樣寫的 網站名稱 - 所在網頁
這樣寫其實也沒有什麼,但是如果你想讓你的網站在從Google和Baidu過來更大的流量,我不建議只這樣寫,還應該把keywords完善
網站名稱|功能名稱|功能名稱的各種寫法
為什麼說是各種寫法呢,因為我們並不知道用戶是怎麼找到你網站的,也不清楚是根據什麼來找到的,比如HttpRequest
我們就可以這樣寫request|http|httpRequest等等,這樣你的網站被找到的幾率就會大在提高。
這個建議大家使用免費的站長統計工具來測試一下,現在的站長工具一般分析的都挺到位,比如http://www.51.la 會統計出來路,根據什麼關鍵字 ,來源IP等等大家可以自己查看一下。
然後你就可以根據使用者常用的關鍵字進行分析,來配置自己的網站,也許這就是簡單的SEo吧,呵呵,不過真正好的網站不能光靠這些,這是不夠的, 內容才是王道
4.網站的 description 我相信大部分人會忘記寫它,它們主要是用來做什麼的呢?
博客園 - 程式師的網上家園
不難看出來標題就是Title 而下面的說明就是description的值。大家應該知道怎麼寫了吧。
5.什麼樣的網站Seo最難優化
我個人認為目前Ajax的網站是最難優化的,因為Ajax的網站全是非同步的調用的,我們可以自己找一個Ajax的網站測試一下,當你調出了整個介面的 資訊時,你表面上看著是非常的多。
但實際是你右鍵看一下原始程式碼只有短短的幾行Js,那這樣的話,網路蜘蛛所抓取到的資訊也就只是一點點JS代碼。它可能會感覺你的網站沒有任何有 意義的東西,
自然權重和檢索量就會有一定的影響。
其實SEo最好優化的還是最基本的,所有資訊都鋪設在網頁 上,當然Ajax的方法,確實從客戶體驗上有大大的提升,也把好多壓力放在了用戶端。 具體要怎麼用,還得看大家的網站是做什麼的
如果對Seo要求不是太高的話,那就不需要管這些東西了。以客戶體驗為主。但相反的話而不然。
----------------常用功能我使用方法----------------
1. 將徹底遮罩滑鼠右鍵
oncontextmenu="window.event.returnValue=false"
用於Table
2. 取消選取、防止複製
3. 不准粘貼
onpaste="return false"
4. 防止複製
oncopy="return false;" oncut="return false;"
5. IE位址欄前換成自己的圖示
6. 可以在我的最愛中顯示出你的圖示
7. 關閉輸入法
8. 永遠都會帶著框架
9. 防止被人frame
10. 網頁將不能被另存為
11. 查看網頁原始程式碼
12.刪除時確認
刪除 刪除
13. 取得控制項的絕對位置
//Javascript //VBScript
14. 游標是停在文字方塊文字的最後
15. 判斷上一頁的來源 View Code
javascript: document.referrer 16. 最小化、最大化、關閉視窗 本例適用於IE
17.遮罩功能鍵Shift,Alt,Ctrl
18. 網頁不會被緩存
View Code
或者
19.怎樣讓表單沒有凹凸感?
或
20.
no |
&的區別?
(division)用來定義大段的頁面元素,會產生轉行 用來定義同一行內的元素,跟
的唯一區別是 不產生轉行 是ns的標記,ie不支援,相當於
21.讓快顯視窗總是在最上面:
22.不要捲軸? 讓豎條沒有:
讓橫條沒有:
兩個都去掉?更簡單了
23.怎樣去掉圖片連結點擊後,圖片周圍的虛線?
24.電子郵件處理提交表單
25.在打開的子視窗刷新父視窗的代碼裡如何寫?
window.opener.location.reload()
26.如何設定打開頁面的大小
打開頁面的位置
27.在頁面中如何加入不是滿鋪的背景圖片,拉動頁面時背景圖不動
28. 檢查一段字串是否全由數位組成
29. 獲得一個視窗的大小
document.body.clientWidth; document.body.clientHeight
30. 怎麼判斷是否是字元
if (/[^/x00-/xff]/g.test(s)) alert("含有漢字"); else alert("全是字元");
31.TEXTAREA自我調整文字行數的多少
32. 日期減去天數等於第二個日期
33. 選擇了哪一個Radio
View Code
Style Barcode
34.腳本永不出錯
35.ENTER鍵可以讓游標移到下一個輸入框
36. 檢測某個網站的連結速度: 把如下代碼加入
View Code
區域中:
37. 各種樣式的游標 auto :標準游標 default :標準箭頭 hand :手形游標 wait :等待游標 text :I形游標 vertical-text :水準I形游標 no-drop :不可拖動游標 not-allowed :無效游標 help :?幫助游標 all-scroll :三角方向標 move :移動標 crosshair :十字標 e-resize n-resize nw-resize w-resize s-resize se-resize sw-resize
38.頁面進入和退出的特效 進入頁面 推出頁面 這個是頁面被載入和調出時的一些特效。duration表示特效的持續時間 ,以秒為單位。transition表示使用哪種特效,取值為1-23: 0 矩形縮小 1 矩形擴大 2 圓形縮小 3 圓形擴大 4 下到上刷新 5 上到下刷新 6 左到右刷新 7 右到左刷新 8 豎百葉窗 9 橫百葉窗 10 錯位橫百葉窗 11 錯位豎百葉窗 12 點
擴散 13 左右到中間刷新 14 中間到左右刷新 15 中間到上下 16 上下到中間 17 右下到左上 18 右上到左下 19 左 上到右下 20 左下到右上 21 橫條 22 豎條 23 以上22種隨機選擇一種
39.在規定時間內跳轉
40.網頁是否被檢索 其中屬性值有以下一些: 屬性值為"all": 檔將被檢索,且頁上連結可被查 詢; 屬性值為"none": 檔不被檢索,而且不查詢頁上的連結; 屬性值為"index": 檔將被檢索; 屬性值為"follow": 查詢頁上的 連結; 屬性值為"noindex": 檔不檢索,但可被查詢連結; 屬性值為"nofollow": 檔不被檢索,但可查詢頁上的連結。
最大化視窗?
解決問題:由於層與下拉清單之間的優先順序是:下拉清單 > 層,因此在顯示的時候,會因為優先順序的次序而會出現如上問題。(如果幾個元素都是層的話 ,我們可以通過層的 z-index 屬性來設置)解決辦法就是:給層中放一個優先順序比下拉清單更高的元素(iframe),從而解決此問題!具體解決代碼如 下:
menu
輸入框也可以做的很漂亮了 head
View Code
注意:這段代碼是在新建檔中的
這個可不是
item 1 |
item 2 |
item 3 |
item 4 |
item 5 |
外向數: 沒回答的題數:
總得分: 結 論:
注意:修 改為即為打開最大
化視窗,而如果改為就變為視窗一打開就最小化
頁面自動刷新(說明)
當你做網頁時,是不是有的時候想讓你的網頁自動不停刷新,或者過一段時間自動跳轉到另外一個你自己設定的頁面?其實實現這個效果非常地簡單
,而且這個效果甚至不能稱之為特效。你只要把如下代碼加入你的網頁中就可以了。
1,頁面自動刷新:把如下代碼加入區域中,其中20指每隔20秒刷新一次頁面.
2,頁面自動跳轉:把如下代碼加入區域中,其中20指隔20秒 後跳轉到http://www.williamlong.info/頁面。
頁面自動關閉
5000是指時間
快顯視窗自動關閉
10秒後快顯視窗自動關閉
注意:在新的tan.htm的body中要加 總得分: 結 論:
訂閱:
文章 (Atom)