security

網路安全(4) Web Application Security

今天來講講web application security 基本上這篇講的是所有開發者都要知道的最基本知識 最近CS領域實在太過火紅 網頁開發更是前仆後繼 但並不是每個開發者都對security有sense 如果你搜尋 "password ext:xls" 就會發現挺多不可思議的連結

Alt text

但誰無年少 誰不輕狂 看完後把冷汗擦一擦 讓這篇文章介紹目前最常見的幾個安全問題

OWASP

講到security一定要知道的Project OWASP: Open Web Application Security Project 裡面介紹了各種不同的網路安全問題 每幾年的十大安全問題排名跟範例 完全免費 基本上是所有做security的聖經

OWASP

值得一提的是他們每幾年就會統計最常見的網路安全問題 先來看一下2010的跟2013的(2013是最新的list)

基本上榜上有名的都挺固定的 劉伯溫說忠臣要比奸臣更奸 要擋住駭客的唯一方式就是比駭客厲害 今天就來瞭解一下這些到底是什麼 以下的code sample主要來自於AppsecTutorialSeries

A1: SQL Injection

其實Injection包含了很多種 除了SQL injection之外還有code injection, os command injection, xml injection等等 但最惡名昭彰的當然就是sql injection 簡單的code如下

void queryDB(string name){
	string sql = "select * from users where name = '" + name + "'";
	doQuery(sql);
}

很好 簡單易懂

如果server拿到的name是John 那sql就是"select * from users where name = John"

如果server拿到的name是Steve 那sql就是"select * from users where name = Steve"

如果server拿到的name是John or 1 = 1 那sql就是"select * from users where name = John or 1 = 1"

這下high了 因為where的condition always true 第三個sql回傳database的所有row的所有column

Alt text

現在還笑得出來 那要是server拿到的name是John;DROP TABLE users;

Alt text

要是這是真的發生了怎麼辦 別怕 這時候還有一個辦法 趕快上這個網站Linkedin 找份新工作吧 你的user都不見了

同樣的case可以apply到很多地方 如果你把user輸入給你的東西原封不動拿去run os command line就是command injection, 把user輸入給你的東西原封不動寫進log就會有log injection 很多初出茅廬的developer不知道或是忘記預防injection的問題 這也是為什麼injection是OWASP多年來的不動榜首

SQL Injection 預防

最基本的一件事情就是把你web server的error log關起來(不要return給client) 不要讓任何訊息洩露 如果你沒關起來hacker大概隨便try兩次就知道你的table name了

然後要怎麼防呢 當然就是要好好validate user input 在CS領域有個用來嚇初學者的冠冕堂皇的名詞 叫做parameterized query

其實概念也很簡單 就是你server端先把你的sql query寫好 至於username之類的變數呢 就等validate之後再丟進去 好處就是code有code的syntax跟允許的character data有data的syntax跟允許的character code跟data分清楚你的test也會比較好寫

至於各種語言怎麼implement 請參考Query Parameterization Cheat Sheet

A2: Broken Authentication and Session Management

這個category包含所有的盜帳號 不論你帳密是被猜到還是被竊聽到都算

這裡要先介紹session session可以抽象的想成client跟server的一次conversation 每次的conversation開始的時候會先問帳密 認證了之後會生成一個session id也就是這次對話的id 只要是同一個session id你就不需要每傳一次訊息都重新登入

懂了之後呢 開始介紹這個類型的可能被攻擊的點

這個category有幾種類型

1.傳輸未加密 傳輸內容被中間人竊聽 之前都有提過 解法就是用httpsssh

2.session在user登出之後沒有清理掉 或是session id不會time out 更慘的是session id直接寫在URL裡面 比如說

http://example.com/myprofile?sessionid=abcde

任何人只要拿到這個session id 他根本不用知道你的帳密 就可以直接假裝是你 把你戶頭的錢轉走之類的

3.存密碼的時候沒有hash 或是 hash的時候沒有add salt 之前講過 可以暴力硬破

A3: Cross-Site Scripting(XSS)

XSS是injection的一種 也就是Script injection 那為什麼要從Injection的category單獨出來呢 因為剛剛A1講的Injection的攻擊目標是server, SQL injection的目標是database server, command injection的目標是webserver等等 但XSS的目標是其他使用者

那要怎麼inject呢 也是很簡單 比如說一個網站的某頁有很多comments 每個人都可以寫comment 而且寫的comment都會被其他人看到

那今天如果hacker也寫了comment

I like this post<script>/*Bad code*/</script>

因為webser會load所有comment給所有在瀏覽這一頁的user 所以這個script就會被執行 而且user不知道(因為html不會show script tag) 那你想得到的javascript能做的事他都能做了 偷cookie session 或是覆蓋一個假的login panel在真的login panel上 你帳密輸入完就直接傳到hacker的server去 完全看不出來因為你browser的網址是正確的

inject到HTML element只是其中一種可能 也可能inject到html tag的attribute 也可以inject到CSS 也可以inject到網站要redirect的URL

Cross-Site Scripting 預防

XSS Prevention Cheat Sheet 洋洋灑灑寫了7個rule 但其實Rule#0最重要 就是好好validate所有的user input 剩下的都是防禦各個可能被inject的點的實作細節

A4: Insecure Direct Object Reference

如果server直接用user給的變數去access檔案 就可以去猜server存其他檔案的檔名or資料夾 舉個例子

http://example.com/showimage?image=img1

這是網站要給你看的image1的link 那你想看img2就直接把後面改成img2 如果可以看得到那就是A4

更慘的是如果允許輸入這種

http://example.com/showimage?image=../../password/password.txt

那就更精彩了

Insecure Direct Object Reference預防

Access control也就是每個檔案的存取權限設定好 或是最重要的validate user input

A5: Security Misconfiguration

像是你安裝一個database 會有default的帳密比如說user: admin 密碼: admin 你沒有把它拿掉 或是server error的時候你把所有error message全部傳給client

Security Misconfiguration 解法

  1. 認真看doc

  2. 所有檔案等等的權限都開到最低 不需要的port都關掉 只提供需要提供的東西

A6: Sensitive Data Exposure

傳輸未加密或密碼沒有用hash或加salt 老問題

A7: Missing Function Level Access Control

網頁沒有做好access control 比如說一些webserver的default path:

/log

/phpmyadmin

/admin等等 這些權限沒關就屬於這類

有沒有開始覺得都大同小異了

A8: Cross Site Request Forgery

這個比較有名 我覺得排在A8算是低估它了 因為通常這個攻擊如果成功了 傷害會比較巨大

基本上我們跟server能做的互動 取決於server開放給我們的權限 比如說A可以轉錢到別人信箱 可是不能改B的密碼 也不能把C的錢轉給自己

可是今天要是有權限的話就不一樣了 什麼時候會有權限呢 就是你的cookie/session還有效的時候(比如你現在開facebook不用輸入密碼 因為你cookie還有效) 讓你在你不知情的情況下送http request 這就是你很常收到垃圾郵件或惡意郵件的時候 他都會要你點個link 那絕不是只是要你點廣告衝流量而已 如果你點了 剛好你另外一個網站(比如銀行)的cookie沒有到期 他就可以假裝是你 送http request

CSRF 解法

  1. 一個request過來前先看一下他的header 看他是不是自己網站的header 還是cross site的header
  2. 對於非get的重要request 要求提供驗證碼 或是重新驗證使用者

A9: Using Components with Known Vulnerabilities

就是你用了不安全的第三方軟體 明明他們已經承認有問題了你還不換或不更新 就會被攻擊

A10: Unvalidated Redirects and Forwards

有些request會把使用者導到其他網站或頁面 他直接抓取網址的url的parameter來redirect 就很好被攻擊

response.sendRedirect(request.getParameter("url"));

Unvalidated Redirects and Forwards解法

就是乖乖validate不然就不要redirect

總結

做學問最重要的就是總結 異中求同 同中求異

A1 A4 A7 A10: user的input可能是惡意的 網址亂打 檔案亂存取等等

A2 A6: 密碼學沒學好

A3 A8: 偷偷拿你的cookie/session做壞事

A5 A9: 乖乖看doc乖乖更新

我認為這主題的投資報酬率實在是挺高的 因為重要的問題都是換湯不換藥 即使之後會出新的top10也大概就是這十項再交換順序 如果有幾項沒聽過 總覺得跟人家聊天搭不上話 手腳不好施展 這篇文章的都看懂就夠了 真的有需要寫的時候你再去深入研究細節即可