黃偉榮的學習筆記

軟體的世界變化萬千,小小的我只能在這洪流奮發向上以求立足。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[個人作品]安全性:URL查尋字串加密

Posted on 2007-08-30 23:34  黃偉榮  阅读(1356)  评论(2编辑  收藏  举报
也是我一年前的作品,那時好像自己架了一個站,有一個月的時間,很熱忱的豐富自己的站,可點像現在的自己,在豐富自己的Blog,不知一年後我的熱忱可持續多久,希望可以一直下去。 

PDF下載


安全性:
URL查尋字串加密

作者:黃偉榮

開發工具:Visual Studio 2005


議題

  URL查尋字串是很容易作為被功擊的地方,而是很容易被程式設計師忽略而使資訊洩漏,本文將介紹常見的功擊和防範。

什麼是URL查尋字串

  在 URL 中,查詢資訊與路徑資訊是以問號 (?) 分隔,而名稱/值組則是以等號 (=) 分隔。
Http://localhost/index.aspx?ID=S01,其中Http://localhost/index.aspx代表的是路徑,有一個ID的資訊,在ASP.NET中讀取URL查尋字串的方法是Request.QuestString方法。

下列程式碼將範例Request.QuestString方法如何讀取URL的字串

public partial class Default : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        string ID;

        int Count;

        string[] Keys;

        //使用索引鍵來取得或設定項目

        ID = Request.QueryString["ID"];

        //使用索引來取得或設定項目

        ID = Request.QueryString[0];

        //取得所有的索引鍵

        Keys = Request.QueryString.AllKeys;

        //取得數目

        Count = Request.QueryString.Count;

    }

}

資訊被非法取得

           上圖是我模擬如何被非法取得資訊,請注意網址列的部分,URL有加上EmployeeID的查尋字串,EmployeeID=0代表了顯示EmployeeID0的個人資料,只要將0修改成別的數字如1,就可以取得EmployeeID1的個人資料,很多人都是這樣設計網站,包括很多書都是這樣寫,因為參數的傳遞非常的容易,很容易撰寫程式碼,請不要抱者僥倖的心態以為使用者不會注意這個小細節,而且這樣作法除了很容易被非法取得資訊外,也是常被SQL Injection[1]功擊的地方。

為查尋字串加一道鎖

           原來使用URL來傳遞參數,這麼不安全,那是不是就不要使用了呢?以上一個例子EmployeeID=0從字面上就很容易猜出他的作用,那如果我把EmployeeID=0加以編碼變成EmployeeID=MAA1或 A=AHAAbABvAHkAZQBlAEkARAA9AD[2]是不是比較讓人無從猜起,而且因為還需經過解碼手序,就算被人亂輸入也不怕,唯一的缺點經過編碼查尋字串會增加好幾倍,URL的查尋總字數為4096Byte(約二千個字左右),如果字串多很容易就爆掉了,這點要多加注意。

編碼範例

<%@ Page Language="C#" %>

<script runat="server">

    protected void Page_Load(object sender, EventArgs e)

    {

        //假設我的EmployeeID為0

        int EmployyeeID = 0;

        //先將字串轉成位元組

        byte[] StringByte = System.Text.UnicodeEncoding.Unicode.GetBytes(EmployyeeID);

        //將位元組編碼

        String Encode = HttpServerUtility.UrlTokenEncode(StringByte);

        //設定連結控制項的連結Url

        MyInforHyperLink.NavigateUrl = "MyInfo.aspx?EmployeeID=" + Encode;

    }

</script>

<html>

<head runat="server">

    <title>EnCode</title>

</head>

<body>

    <form id="form1" runat="server">

        <div>

            <asp:HyperLink ID="MyInforHyperLink" runat="server">My Information</asp:HyperLink>&nbsp;

        </div>

    </form>

</body>

</html>

這個範例主要就這二行

byte[] StringByte = System.Text.UnicodeEncoding.Unicode.GetBytes(EmployyeeID);

String Encode = HttpServerUtility.UrlTokenEncode(StringByte);

首先先看第一行,這一行的做用是將字串轉成位元組,轉成位元組是因為在.Net中大部分的編碼都只支援編碼位元組,這裡是使用Unicode[3]轉成位元組(不要使用ASCII免得中文字無法還原)

第二行的做用是將位元組編碼成字串如0就變成MAA1

.NET Framework中有很多的編碼的類別,這裡使用的是比較簡單且適合URL的編碼,也有更安全,更複雜的編碼方法,請自行研究。

解碼範例

<%@ Page Language="C#" %>

<script runat="server">

    protected void Page_Load(object sender, EventArgs e)

    {

        //有沒有查尋字串

        if (Request.QueryString["EmployeeID"] != null)

        {

            string EmployeeID = Request.QueryString["EmployeeID"];

            //先將字串解碼成位元組

            byte[] StringByte = HttpServerUtility.UrlTokenDecode(EmployeeID);

            //將位元組轉成字串

            String Decode = System.Text.UnicodeEncoding.Unicode.GetString(StringByte);

            //下面是連資料庫

            System.Data.DataTable MyInfo;

            System.Data.SqlClient.SqlDataAdapter SDA = new System.Data.SqlClient.SqlDataAdapter("Data Source=(local);

                     Initial Catalog=DataBase;Integrated Security=True",

                    "Select * From Employee Where EmployeeID=" & EmployeeID);

            SDA.Fill(MyInfo);

            DetailsView.DataSource = MyInfo;

            DetailsView.DataBind();

        }

    }

</script>

<html>

<head runat="server">

    <title>Decode</title>

</head>

<body>

    <form id="form1" runat="server">

        <h3>

            My Information</h3>

        <p>

            <asp:DetailsView ID="DetailsView" runat="server">

            </asp:DetailsView>

        </p>

    </form>

</body>

</html>

這個範例主要就這二行

byte[] StringByte = HttpServerUtility.UrlTokenDecode(EmployeeID);

String Decode = System.Text.UnicodeEncoding.Unicode.GetString(StringByte);

第一行的做用是將字串解碼成位元組就是沒碼解前的位元組,第一行的做用是將位元組還原成字串。


安全性是現在程式設計很注重的問題,就算程式寫的再好,卻沒有考慮到安全性,那就算失敗的程式了,小弟會慢慢的一些常見的問題與決解方法寫出來,供大家參考,請近請期待。

2006/7/12偉榮



[1] SQL Injection 是指利用應用程式開發人員不期待或沒有預料到的方法,將SQL程式碼傳入應用程式的程式。如何防止SQL Injection不在本文的範圍內。

[2]將查尋字串全部編碼如查尋字串type=25&NO=40編碼變成http://localhost/default.aspx?QueryString = AHAAbABvAHkAZQBlAEkARAA9AD,這個方法更安全,只是在取值的時會較複雜些。

[3] Unicode(統一碼、萬國碼、單一碼)是一種在電腦上使用的字元編碼。它為每種語言中的每個字元設定了統一併且唯一的二進位編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。隨著電腦工作能力的增強,Unicode也在面世以來的十多年裡得到普及。