在這一章,你將會學到如何編寫精美的跨網站腳本攻擊(XSS)與SQL攻擊 fuzzer,來攻擊以GET與POST請求接收HTTP參數的URL。fuzzer是一種軟體,它會試著送出錯誤或格式不正確的資料來尋找其他軟體的錯誤。fuzzer有兩種常見的類型:mutational與generational。mutational fuzze會試著用不良的資料來汙染已知良好的輸入,而不考慮協定或資料結構。相較之下,generational fuzzer會考慮伺服器通訊協定的微細差別,並使用這些差別來生成技術上有效的資料,傳送給伺服器。使用這兩種fuzzer,都是為了讓伺服器回傳錯誤訊息給fuzzer。
我們要來寫一個mutational fuzzer, 你可以在已經知道某個URL或HTTP請求的良好輸入時使用它。當你可以使用fuzzer來找出XSS與SQL攻擊漏洞之後,就知道如何入侵SQL攻擊漏洞,從資料庫中取出帳號與密碼雜湊。
為了找到與入侵XSS與SQL攻擊漏洞,我們會在C#中使用核心的HTTP程式庫,用程式來建構HTTP請求。我們會先編寫一個簡單的fuzzer來解析URL,並使用GET與POST請求來fuzz HTTP參數。接下來,我們會針對SQL攻擊漏洞來開發完整的入侵程式 ,使用精心製作的HTTP請求來取得資料庫內的使用者資訊。
我們會用一個小型的Linux版本,稱為BadStore,來測試這一章的工具(你可以在VulnHub網站取得,https://www.vulnhub.com/)。BadStore的設計有許多可讓SQL與XSS攻擊的漏洞(以及其他的)。我們從VulnHub下載BadStore ISO之後,會使用免費的VirtualBox虛擬軟體來建立一個虛擬機器,以啟動BadStore ISO,如此一來,當我們進行攻擊時,就可以避免攻擊到自己的主機系統。
設定虛擬機器
要在Linux、Windows或OS X安裝VirtualBox,你要從https://www.virtualbox.org/下載VirtualBox軟體。(安裝過程應該很簡單;你只要跟隨下載軟體的網站上的最新說明操作即可。)虛擬機器(VM)可讓我們使用實體電腦來模擬一個電腦系統。我們可以使用虛擬機器來輕鬆建立與管理有漏洞的軟體系統(例如我們將在這本書中使用的這一個)。
添加host-only虛擬網路
你或許需要在設定VM之前先建立一個host-only(不對外連線)的虛擬網路。host-only的網路只可以在VM與主機系統之間進行通訊。以下是建立步驟:
1. 按下File4Preferences來開啟VirtualBox - Preferences對話方塊。在OS X上,選擇VirtualBox4Preferences。
2. 按下左邊的Network部分。你應該可以看到兩個標籤:NAT Networks與Host-only Networks。在OS X,按下Settings對話方塊上面的Network標籤。
3. 按下Host-only Networks標籤,接著按下右邊的Add host-only network (Ins)按鈕。這個按鈕的圖樣是一張網路卡與一個加號。它應該會建立一個名為vboxnet0的網路名稱。
4. 按下右邊的Edit host-only network (Space)按鈕。這個按鈕的圖樣是一把螺絲起子。
5. 在打開的對話方塊中,按下DHCP Server標籤。將Enable Server打勾。在Server Address欄位中, 輸入IP位址192.168.56.2。
在Server Mask欄位中,輸入255.255.255.0。在Lower Address Bound欄位中,輸入192.168.56.100。在Upper Address Bound欄位中,輸入192.168.56.199。
6. 按下OK來將改變存至host-only網路。
7. 再次按下OK來關閉Settings對話方塊。
建立虛擬機器
安裝VirtualBox並將它設為host-only網路之後,以下是設定VM的方法:
1. 按下左上角的New圖示,如圖2-1所示。
2. 當畫面出現對話方塊來讓你選擇作業系統的名稱與類型時,選擇下拉式選項Other Linux (32-bit)。
3. 按下Continue之後,你可以看到提供RAM給虛擬機器的畫面。將RAM的大小設為512 MB並按下Continue。(在fuzz與入侵漏洞時,會讓web伺服器使用許多虛擬機器的RAM。)
4. 當電腦要求你建立一個新的虛擬硬碟時,選擇Do not add a virtual hard drive並按下Create。(我們會以ISO來映像執行BadStore。)現在你可以在VirtualBox Manager視窗左邊窗格中看到VM,如圖2-1 所示。
圖 2-1:含有 BadStore VM 的 VirtualBox
以BadStore ISO啟動虛擬機器
建立VM之後,請按照以下的步驟設定它,來以BadStore ISO啟動:
1. 在VirtualBox Manager的左窗格的VM按下右鍵,並按下Settings。
你可以看到一個對話方塊,顯示網路卡、CD-ROM與其他雜項的設定情形。
2. 在Settings對話方塊中選擇Network標籤。你可以看到七種網路卡設定,包括NAT(網路位址轉譯)、host-only與bridged。選擇host-only網路來配置一個IP位址,它只能讓主機存取,而非其餘的Internet。
3. 你必須將Advanced下拉選單的網路卡類型設為較舊的晶片組,因為BadStore是基於舊的Linux核心,不支援一些較新的晶片組。請選擇PCnet-FAST III。
現在按照以下的步驟來設定CD-ROM,用硬碟的ISO來啟動:
1. 選擇Settings對話方塊的Storage標籤。按下CD圖示,以顯示一個選單,它裡面有一個選擇虛擬CD/DVD磁碟檔案的選項。
2. 按下Choose a virtual CD/DVD disk file選項,找到你之前存至檔案系統的 BadStore ISO,並將它設為可啟動的媒體。現在虛擬機器已經可以啟動了。
3. 按下Settings標籤右下角的OK來儲存設定。接著在VirtualBox Manager 左下角,按下Settings齒輪按鈕旁的Start按鈕來啟動虛擬機器。
4. 啟動機器之後,你可以看到這個訊息:"Please press Enter to activate this console"。按下enter並輸入ifconfig來查看你取得的IP配置。
5. 取得虛擬機器的IP位址之後,在你的網頁瀏覽器輸入它,你可以看到圖2-2所示的畫面。
圖 2-2:BadStore web 應用程式的首頁
SQL攻擊
在現今豐富的web應用程式中,程式員必須能夠在幕後儲存與查詢資訊,以提供高品質、穩健的使用者體驗。這通常是以結構化查詢語言(SQL;讀為sequel)資料庫來完成的,例如MySQL、PostgreSQL或Microsoft SQL Server。
SQL可讓程式員藉由SQL陳述式來以程式與資料庫互動。SQL陳述式是要求資料庫根據你提供的資訊或規則來建立、讀取、更新或刪除資料的程式碼。例如,列表2-1的SELECT陳述式可詢問資料庫:在託管的資料庫內的使用者人數。
列表 2-1:SQL SELECT 陳述式範例
SELECT COUNT(*) FROM USERS
有時程式員需要動態的SQL陳述式(也就是說,根據使用者與web應用程式的互動來改變)。例如,程式員可能需要根據某些使用者的ID或使用者名稱,來從資料庫選出資訊。
但是,當程式員拿使用者從不可信任的用戶端(例如web瀏覽器)提供的資料或值來建構SQL陳述式時,如果用來建立與執行SQL陳述式的值未被妥善地清理,可能會導入SQL攻擊漏洞。例如,列表2-2的C# SOAP方法可用來將一位使用者插入web伺服器上的資料庫。(SOAP,或簡易物件存取通訊協定 是一種XML支援的web技術,其用途是在web應用程式快速建立API。它在C#與Java等企業語言中很受歡迎。)
列表 2-2:可被SQL攻擊破解的C# SOAP方法
[WebMethod]public string AddUser(string username, string password){NpgsqlConnection conn = new NpgsqlConnection(_connstr);conn.Open();string sql = "insert into users values('{0}', '{1}');";1 sql = String.Format(sql, username, password);NpgsqlCommand command = new NpgsqlCommand(sql, conn);2 command.ExecuteNonQuery();conn.Close();return "Excellent!";}
在這個案例中,程式員並未在建立1與執行2 SQL字串之前,先對使用者名稱與密碼進行清理。因此,攻擊者可以建構一個使用者名稱或密碼字串,來讓資料庫執行精心製作的SQL程式碼,讓他們可在遠端執行命令,完全控制資料庫。
如果你將一個單引號與其中一個參數一起傳入(例如用user'name來取代username),ExecuteNonQuery()方法會試著執行不正確的SQL查詢指令(見列表2-3)。接著方法會丟出一個例外,它會被顯示在HTTP回應中讓攻擊者看到。
列表 2-3:因為這個SQL指令是使用者提供的未清理的資料,所以它是無效
insert into users values('user'name', 'password');
許多可存取資料庫的軟體庫,都讓程式員藉由參數化查詢(parameterized queries)來安全地使用web瀏覽器這種不可信任的用戶端提供的值。這些程式庫會自動清理被傳給SQL指令的不可信值,將單引號、括號及在SQL語法中使用的其他特殊字元轉換掉。參數化查詢指令與其他類型的物件關係映射(ORM)程式庫,如NHibernate,都可協助防止這類的SQL攻擊問題。
這些由使用者提供的值,較有可能出現在SQL指令的WHERE子句內,如列表 2-4所示。
列表2-4:這個SQL SELECT陳述式會選擇特定user_id的一個資料列
SELECT * FROM users WHERE user_id = '1'
如列表2-3 所示,將一個單引號丟入未被妥善清理的HTTP參數,再用它來建構動態SQL指令時,會讓web應用程式丟出錯誤(例如HTTP回傳碼500),因為在SQL中,一個單引號代表字串的開頭或結尾。因為這個單引號過早結束字串,或開始一個字串卻未結束它,所以會造成陳述式的不正確。藉由將HTTP回應解析成這種請求,我們可以fuzz這些web應用程式,並在參數被篡改時,搜尋會讓回應產生SQL錯誤的HTTP參數(由使用者提供的)。(摘錄整理自《灰帽 C#》)
學習使用C#將沉悶但重要的資安工作自動化
很多人問我為什麼這麼喜歡C#。我身為開放原始碼軟體的支持者、Linux的忠誠使用者,和Metasploit的貢獻者(它主要是用Ruby來編寫的),這麼喜歡C#是很奇怪的事情。當我在幾年前開始使用C#來寫程式時,Miguel de Icaza(GNOME 的發起者)剛啟動一個小型的專案,稱為Mono。
實質上,Mono的目的,是以開放原始碼的方式來實作Microsoft的.NET框架。C#這種語言已經被提案成為ECMA標準,而.NET框架已經被Microsoft吹捧為Java的替代品,因為它的程式碼可以在一個系統或平台上編譯,並且在另一個系統或平台上執行。唯一的問題在於,Microsoft只釋出供Windows作業系統使用的.NET 框架。Miguel與一小群的核心貢獻者一肩承擔,讓Mono專案成為.NET框架與Linux社群接觸的橋樑。幸運的是,有一位建議我學習C#、也知道我對Linux很有興趣的朋友告訴我這個羽翼未豐的專案,要我看看是否可以同時使用C#與Linux。從那之後,我就無法自拔了。
C#是一種優美的語言。這種語言的原創者與首席建構師Anders Hejlsberg原本的工作是編寫Pascal與後來出現的Delphi編譯器。這些經驗讓他對各種程式語言的強大功能具備敏銳的覺查力。在Hejlsberg加入Microsoft之後,C#在2000年左右誕生了。C#早期採用一些Java的語言功能,例如Java的語法細節,但隨著時間的推移,它演變為自成一格的語言,並搶先在Java之前加入一大堆功能,例如LINQ、委派(delegates)與匿名方法。使用C#,你可以擁有許多C與C++的強大功能,也可以使用ASP.NET堆疊來編寫完整的web應用程式或豐富的桌面應用程式。在Windows上,WinForms是UI程式庫的首選,但是在Linux上,GTK與QT都很容易使用。
最近Mono也開始在OS X平台上支援Cocoa工具組。甚至也支援iPhone與Android。
在寫這本書時,Microsoft不但收購了Xamarin(由Miguel de Icaza創建,以支援Mono框架的公司),也開放大量的.NET框架核心原始碼。而且Microsoft正積極地參與Mono社群,以促進使用Microsoft技術來開發行動軟體。
許多人從事的是與安全有關的工作,例如網路與應用安全工程師,並且依賴某種程度的自動化來掃描安全漏洞或分析惡意軟體。因為安全專家們喜歡使用各式各樣的作業系統,所以我們很難寫出可讓所有人都輕鬆運用的工具。
Mono是一種很棒的選項,因為它跨平台,而且有傑出的核心程式庫集合,讓安全專家可以輕鬆地自動執行許多層面。如果你想要學習編寫漏洞入侵程式、自動掃瞄基礎設施的漏洞、反編譯其他的.NET應用程式、讀取離線registry hives(登錄檔註冊單元),或創建自訂的跨平台payload,那麼本書探討的許多主題都可以協助你踏出第一步(你甚至不需要具備 C#的背景)。文⊙Brandon Perry(本書《灰帽 C#》作者)
開發攻擊性與防禦性的C#
身為一位攻擊或防禦軟體的開發者,你必須找出適合你的語言。在合理情況下,一種語言之所以被選中,只因為它是開發者最熟悉的一種。不過,你應該回答以下這些問題,來決定是否選擇某種語言:
• 目標的主要執行環境為何?
• 外界如何偵測與記錄這種語言寫出來的payload(指令內容)?
• 我的軟體需要保持隱匿的程度(例如,常駐記憶體)?
• 用戶端與伺服器端對這種語言的支援程度如何?
• 是否有個大型社群正在開發這種語言?
• 學習曲線為何?以及這種語言的維護難易度如何?
針對這些問題,C#提供了令人滿意的解答。關於目標的執行環境這個問題,在重度使用Microsoft的環境中,.NET是卓越的候選者,因為它已內建於Windows多年了。且因為.NET開放原始碼,現在C#已經是一種可在各種作業系統上執行的成熟語言了。真正支援跨平台的語言非常誘人。
C#一直是.NET語言的代表。因為C#的入門門檻極低,而且擁有廣大的開發社群,你可以快速上手並使用它。此外,因為.NET是一種受控(managed)、豐富型態的語言,你可以輕鬆地將編譯好的組譯碼反編譯為C#。因此,編寫攻擊性的C#的人,不盡然必須在真空環境中獨自發展,反而可以參考豐富的.NET惡意軟體範例,將它們反編譯,閱讀它們的等效原始碼,並"借用"它們的功能。你甚至可以採用.NET反射API來動態載入與執行既有的.NET惡意軟體範例,當然,前提是它們已經被充分地復原,以確保不會造成任何傷害。
PowerShell的最後一個版本(此時是v5)實作的記錄機制比現有的腳本語言還要多。從防禦者的觀點來看,這是很棒的事情。從滲透測試者、模擬攻擊方或 對手的角度來看,這會大幅增加攻擊時的雜訊。就一本說明C#的書籍而言,為什麼我要提到這一點?當我寫愈多PowerShell,我就愈認同當攻擊者使用C#來開發工具時,會比使用PowerShell還要敏捷,容我解釋一下:
• .NET提供一種豐富的反射API,可讓你輕鬆載入已編譯的C#組譯碼,並在記憶體中與它動態互動。藉由在PowerShell payload上執行所有額外的自我訓練(introspection),反射API可協助攻擊者開發PowerShell payload來扮演.NET組譯碼載入器與執行器的角色,讓攻擊者更有機會躲避雷達的偵查。
• 如Casey Smith(@subTee)所展示的,在預設的Windows安裝版本中,有許多合法、Microsoft簽署的二進位檔案可當成C# payload的優良承載程序-msbuild.exe是最隱秘的一種。使用MSBuild來承載C#惡意軟體,可完美體現"在地生活",這個概念指的是:讓攻擊者融入目標環境,只產生極少的足跡,以存 活一段很長的時間。
• 目前反惡意軟體的供應商在相當程度上仍然未意識到.NET組譯碼在執行階段的能力。外界仍有許多非受控(unmanaged)惡意程式碼尚未把焦點放在有效地掛鉤.NET來執行動態執行階段自我訓練。
• 因為具備存取大量.NET類別庫的能力,熟悉PowerShell的人可以發現轉移至C#是比較順暢的做法。反過來說,如果熟悉C#的人想要將技術轉移到PowerShell與F#等其他.NET語言,他們的入門門檻會比較低。
• C#類似PowerShell,是一種高階語言,也就是說,開發者不需要煩惱低階的編碼與記憶體管理問題。不過,有時你需要做"低階"的事情(例如,與Win32 API互動)。幸運的是,透過C#的反射API與P/Invoke及封送處理(marshaling)介面,你可以隨心所欲地操作底層。文⊙Matt Graeber(Microsoft MVP)
書籍簡介
灰帽 C# 建立自動化安全工具的駭客手冊
Brandon Perry/著
賴屹民/譯
碁峰出版
售價:450元
作者簡介
Brandon Perry
從開放原始碼的.NET作品Mono開始編寫C#應用程式。在空閒時間,他喜歡編寫Metasploit框架的模組、解析二進位檔案,與fuzz一些東西。他是Wicked Cool Shell Scripts 第二版(No Starch Press)的作者之一。