最近工作上因為資安問題,修補程式修到頭破血流了

但也學到了不少防堵方法,有些入侵的手法還真的是有些讓人傻眼

一般的新手程式設計師,或是專門寫內部系統的工程師大概也很容易犯類似的錯誤

所以以下就列出一些在開發中必須要注意的事項或建議寫法,還有可能入侵的手法

有些是程式開發的常識,但有些是用本人的血淚堆積成的.......orz

如果以下有寫到程式碼的話,就用 C# 來舉例

 

1.使用 SQL Parameters 

這個非常重要,要防止 SQL Injection 的方法只有這個了

千萬不要自己去做一個關鍵字集合去 Replace SQL命令

因為你沒法確定是不是會有新的攻擊命令或關鍵字敘述

所以操作資料庫的SQL命令一定要使用SQL Parameter 

如下 : 

string sql = "select * from City where Zip = @Zip";

SqlCommand cmd = new SqlCommand();

cmd.Parameters.Add("@Zip", SqlDbType.VarChar,10).Value = Zip;

cmd.CommandText = sql;

 

2.Cookies 內容加密

網站登入資料(ex:帳號) 不要寫在Cookies中,尤其是Client 端Cookies

因為瀏覽器只要按F12就可以看到值了,用Fiddler也可以很容易就錄到

沒加密的話知道Cookies 是幹嘛的之後就很好try了

如果要在Cookies中儲存登入資訊 (因為可能有"記住我"之類的功能)

比較好的做法

使用ASP.Net內建的 FormsAuthentication

ex : 

//登入

FormsAuthentication.SetAuthCookie("使用者帳號", true);

//判斷是否登入

if (User.Identity.IsAuthenticated) {

   Response.Write("已登入");

//取得使用者帳號方式

User.Identity.Name;

//登出

FormsAuthentication.SignOut();

之後打開瀏覽器F12,Cookies 就被加密了

Clipboard02  

但在使用這功能前要先改web.config 

<authentication mode="Forms">

<forms name=".ASPXAUTH" loginUrl="~/default.aspx" defaultUrl="default.aspx" protection="All" timeout="600" path="/" requireSSL="false" slidingExpiration="true" cookieless="UseDeviceProfile" domain=".suncolor.com.tw" enableCrossAppRedirects="false">

<credentials passwordFormat="SHA1" />

</forms>

</authentication>

更詳細的使用方式請參考保哥這篇

http://blog.miniasp.com/post/2008/02/21/Explain-Forms-Authentication-in-ASPNET-20.aspx

裡面的這篇很詳細

http://msdn.microsoft.com/en-us/library/aa480476.aspx

 

3.千萬不要相信Client傳來的內容

這個內容包含的實在很廣.....

因為Client傳到Server的任何資訊都是可以被竄改的,尤其位置不是存在於SSL之下

舉例來說一般在會員註冊時,會要求使用者填寫住家地址,選擇縣市地區

相信大部份70%都是用AJAX處理 (因為對使用者體驗比較好)

選擇縣市後觸發change去更改地區值填回select option or DropDownList

而 Server 端就直接接收下拉的數值了

ex : 

//如果是 Server Control

string City = this.City.SelectedValue;

//如果是一般HTML

string City = Request.Form("City");

...............

然後你可能就直接存取資料庫了

string sql = "Insert into Order (.....) values (......,@City)";

SqlCommand cmd = new SqlCommand();

cmd.Parameters.Add("@City", SqlDbType.VarChar,10).Value = City;

cmd.CommandText = sql;

如果此時你寫入的City值沒有再去驗證的話,你可能很容易就中了XSS

因為你接收到的數值可能已經被竄改

比較好的做法 : 

下拉選單的數值盡量為數字,傳到Server端之後就可以驗證參數值是否為數字型態

以上面的例子而言 City 有城市編號,再利用城市編號 AJAX 去找回 ZipCode

如果要取回使用者所在城市就用ZipCode去資料庫去反查

ex : 

//記得Zip 要先判斷是否為數值型態,或是在getCityInfo中處理

//傳入getCityInfo後取得 CityInfo 物件

CityInfo city = getCityInfo(Zip);

//用此方式取得城市與地區

city.Area;

city.City;

如果是一般無法用數字表示的下拉值,就要檢查長度

例如 : 台灣城市地區可能最長也就"海南諸島"四個字

超過四個字當然就很有問題

 

4.有牽扯到敏感資訊的內容頁面,要放在SSL之下

這是Fiddler 在 Http 下錄到的結果

 Clipboard02  

這是Fiddler 在 Https 下錄到的結果

 Clipboard03

看到圖應該就不用解釋了吧!   

 

 5. Server 端接收的所有參數使用AntiXSS過濾

這元件就是用來防止XSS攻擊,可以到下方下載 dll

http://www.microsoft.com/en-us/download/details.aspx?id=43126

或是在Nuget上搜尋 AntiXSS

 Clipboard03  

用法 : 

先引用 dll or Nuget 下載安裝

using Microsoft.Security.Application;

string Str = AntiXss.GetSafeHtmlFragment("要過濾的文字");

ps : framework 4.5有內建AntiXss了,但用法跟使用 dll 不同使用時要注意一下

System.Web.Security.AntiXss 命名空間

所有傳遞到 Server 端的參數都最好加上XSS的過濾,尤其是會寫入到資料庫的值

如部落格類型的網站,就必須要檢查 or 過濾編輯器 ex:ckeditor 內的輸入是否有惡意符號,過濾後才能進資料庫

如SQL Parameters一般,防止XSS最好的辦法就這個了

 

6. 圖片上傳後要檢查副檔名,與內容是否真的為圖片

檢查副檔名這個雖然是常識,但是我有因為邏輯沒寫好而沒檢查到 @@

所以這個很重要,一定要再三確認邏輯是否正確,而且也建議要檢查內容是否真的是圖檔

因為如果只判斷附檔名,把 .txt、.js、.aspx....之類的改成.jpg 也是可以上傳

萬一不小心有其他洞可以rename就好玩了,更不用講有些真的是圖片裡面也有程式碼

網路上看到這個解決方式可以參考一下

請教判斷是否為真的圖檔的方法 <------ 這篇判斷前幾個byte 的方式

但我最後的做法是利用縮圖元件,再把上傳上來的圖再縮一次圖

測試過就算把.txt 改為 .jpg 拿去縮圖,也會被轉成真正的圖片

 

7.禁止使用者發表文章時寫入 iframe or frame 標籤

這其實也算XSS,如果沒有禁止iframe,就等於開了個洞讓人植入惡意程式

可以在iframe 的src 把瀏覽到此頁user的 document.cookie 送回指定網址

對方取得cookies 後再模擬登入你網站就好了,如果你連加密都沒有的話就更慘

請看此篇 : XSS Attack Using Frames

或是直接就在 iframe的onload 事件run 惡意js 了

 

8. Web.config 加上 Http Header 的相關安全設定 

除了寫程式要注意,相關的設定檔也可以幫很大的忙

貼一下主管給我的這一篇給大家參考 :

https://www.imququ.com/post/web-security-and-response-header.html

web.config 加上以下標籤

<httpProtocol>

<customHeaders>

<add name="X-Frame-Options" value="SAMEORIGIN"/>

<add name="X-XSS-Protection" value="1; mode=block"/>

</customHeaders>

</httpProtocol>

 

X-Frame-Options 設定後可以啟動瀏覽器避免非網站的Frame夾在頁面取得資料。

X-XSS-Protection 設定後可以啟動瀏覽器的XSS攻擊。 

還有其他詳細設定請看上面那個連結

 

9.重新檢查網站金流服務的串接方式

網站金流都要在SSL下進行才對,但有可能會連出去的就是信用卡刷卡的服務 or 711

因為要連到銀行端頁面進行授權,雖然還是在SSL之下,但轉頁就可能會有可趁之機

在此講一下遇到的狀況......

我們使用的技術文件上寫了要以iframe方式箝入對方的信用卡輸入頁面

但因為iframe 的 src 網址上參數有什麼都一目了然,包含訂單編號、要授權的金額...等

而我們之前的外包寫得更糟是直接以網址連到銀行端,參數就直接在網址列改了

雖然改了參數之後還是有被銀行端拒絕交易,但不知道對方用何種方法....

讓銀行接受了$10元的授權金額,但是$300多元的商品金額,且接收到銀行回傳的交易金額也是$300多

意思就是說,就算你要拿訂單金額跟銀行回傳的金額比對也沒用

因為你已經被截斷了,送出去跟拿回來都是假的

就算完全遵照串接的文件使用iframe來做也是一樣

最後的解決方式是.....跟對方要新版本的串接文件,改用元件的方式

因為如果你們家的信用卡金流是以iframe or URL導頁方式執行的話

要記得抽空問一下對方文件有沒有更新版啊!

 

10.使用Web Application的方式來建置網站

不要使用Web Site 建立新網站的方式來開發,萬一網站被侵入了程式碼也會被看光光

看光光就算了,對方還可以直接改你的 .cs or .vb

使用建立Web Application 建立專案的方式開發,就算主機被侵入了也看不到程式碼

萬一現在的網站類型是 Web Site 的話,可以用下面的方式轉換成 Web Application

http://blogs.msdn.com/b/webdev/archive/2009/10/29/converting-a-web-site-project-to-a-web-application-project.aspx

但轉換之前必須要先讓原本的Web Site 可以被建置成功 (連結裡面有提到)

 

11.AJAX的安全性問題

如果你的 AJAX 裡面有牽扯到訂單查詢 or 會員資料查詢修改的話,就必須要再檢查使用者權限

尤其是有關 Insert、Update、Delete

例如有個AJAX裡面的 SQL 如下 :

string sql = @"

update member

set nickname=@nickname,cname=@cname

where account = @account

";

SqlCommand cmd = new SqlCommand();

cmd.Parameters.Add("@nickname", SqlDbType.VarChar,50).Value = nickname;

cmd.Parameters.Add("@cname", SqlDbType.VarChar,50).Value = cname;

cmd.Parameters.Add("@account", SqlDbType.VarChar,50).Value = account;

如果全部參數值是從網頁上傳來的,然後又沒做任何限制擺明了就是個洞

因為直接改account 值就可以幫別人改資料了

此時應該是要檢查AJAX的使用者是否為登入的當事人

SqlCommand cmd = new SqlCommand();

cmd.Parameters.Add("@nickname", SqlDbType.VarChar,50).Value = nickname;

cmd.Parameters.Add("@cname", SqlDbType.VarChar,50).Value = cname;

cmd.Parameters.Add("@account", SqlDbType.VarChar,50).Value = User.Identity.Name;

 

12.盡量不要把重要資訊寫到頁面上的 Hidden

一般把值寫在 <input type="hidden " /> 大部分應該都是為了方便讓 js 去操作

但也造成了只要打開原始碼一看,大概就知道有哪些參數了

寧可多花點效能去SQL查回來,也不要一開始就全部查回來然後丟在網頁表單的 hidden 欄位

 

13.關閉圖檔資料夾的執行權限

依照網站類型,如果是社群或發表文章類的網站幾乎都會有上傳圖片的需求

有上傳就會有風險啊! 像之前 CKEditor 的檔案上傳問題就是

所以如果有那種不需要讀取執行 .aspx 程式的資料夾就把他執行的權限拿掉

不然如果被傳了惡意的檔案上來就很有可能會被執行起來

設定方式可以參考保哥的這篇

IIS7 如何關閉特定目錄的執行權限(與 IIS6 比較)

就會在圖檔或 JS、CSS....等不需要執行.aspx 的地方放一個 web.config 檔案 

內容如下 : 

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

<system.webServer>

<handlers accessPolicy="Read" />

</system.webServer>

</configuration>

 可以防止萬一真的被透過上傳介面上傳了惡意程式上來,也不會被執行

 

14.會員加入、登入記得加個驗證碼

............ 以防駭客太好 try

 

 

 

....................日後有遇到或看到或想到再來補充

 

arrow
arrow
    全站熱搜

    小雕 發表在 痞客邦 留言(0) 人氣()