聽起來合理且簡單對吧~但在有時間限制下必須快速決定時真的會混淆,先看清楚漏洞在誰的身上再說。
前一題剛弄懂,XSS 要回去改網站的程式,做 input validation來避免。
下一題掃描報告上又看到 XSS,我題目都沒看完就選了 input validation。
結果正解是 patch,我想說:what???
(梗圖改編,若有版權敬請告知,配合下架)
結果那個 XSS 不在網站的程式裡,是在 IIS 本身。
IIS 是微軟的web伺服器軟體,沒人有它的原始碼,想改也改不了,只能等微軟出修補,把它裝上去。
我後來回頭看,這題不是不會,是上一題的答案還黏在手上,看到 XSS 這三個字母就反射出去了。
同樣叫 XSS,洞在不同人的程式碼裡,修法就不一樣。
如果洞在廠商的產品裡,像 IIS、Apache、Windows、某台設備的韌體,那能做的事大致就是等廠商release patch,然後按照Risk的程度排定修補時程。
如果洞在自己的程式裡,公司自己寫的網站、外包寫給公司的系統,這時候才輪得到「改程式」,沒有人會幫你出 patch。
這跟 Day07 先看弱點的主詞是憑證還是伺服器,是同一種讀法,只是這次主詞換成「誰的程式碼」。
講到改程式,常出現的有三個:parameterized query、output encoding、input validation。
我一開始以為這三個是同一件事的不同說法,後來才知道它們各擋各的。
Parameterized query(參數化查詢,也叫 prepared statement)擋的是 SQL injection。
做法是先把 SQL 語句的形狀定好,使用者輸入的東西只能填進預留的位置,資料庫只會把它當成一個值,不會當成 SQL 語法去解析。
所以就算有人打 ' OR '1'='1,資料庫看到的也只是一串很奇怪的 ID,不會拿去當成語法執行。
Output encoding(輸出編碼)擋的是 XSS。
要把使用者的輸入印回頁面之前,先把 <、> 這類字元轉成 <、>,瀏覽器就會把它當文字顯示,不會當成標籤去執行。
Input validation(輸入驗證)比較像是門口的檢查,這一格只收數字,就不要讓字母進來。
它能擋掉很多亂七八糟的東西,但如果做法是列一張黑名單,擋掉 '、<script> 這些字元,攻擊者換個編碼方式寫同樣的東西,就有機會繞過去。
直接看 code 比較有感,Day17 架的那台 DVWA,每個模組頁面右下角都有一個 View Source,可以直接看不同難度的原始碼。
SQL Injection 在 low 難度長這樣,使用者輸入的 $id 直接黏進 SQL 字串裡:
$id = $_REQUEST[ 'id' ];
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

換到 impossible 難度:
$id = $_GET[ 'id' ];
if(is_numeric( $id )) {
$id = intval ($id);
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
is_numeric 是 input validation,不是數字就不往下走。prepare 加 bindParam 是 parameterized query,SQL 的形狀先定好,:id 那格只能填值。
它兩個都做了,一層沒擋住還有下一層。
XSS(Reflected)也一樣,low 是把輸入直接印出來:
$html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';

impossible 多了一個 htmlspecialchars,這就是 output encoding:
$name = htmlspecialchars( $_GET[ 'name' ] );
$html .= "<pre>Hello {$name}</pre>";

Day17 我在 low 打 <script>alert('XSS')</script> 會跳窗,換到 impossible 同樣的字串就只會原封不動印在頁面上。
還有兩件事常跟上面三個擺在一起的,logging 跟 IDS。
它們很重要,但它們不會讓 SQL injection 打不進來,它們做的是打進來之後讓你知道。
資安控制大致可以照「什麼時候起作用」來分:
另外還有一種分法是看這個控制是誰在做的,technical(技術,系統自己跑)、managerial(管理,政策與風險評估)、operational(操作,人去執行的流程)。兩種分法同時出現,像是logging 就是 technical 加 detective;人員門禁管制就比較屬於operational加preventive,不過分類法有physical的話就選physical加preventive。
現實上 patch 不一定馬上有,有了也不一定馬上能裝,系統停不了、要等維護時段。
自己的程式也一樣,改 code、測試、上線,不會是今天發現明天就好。
這段空窗期能做的,是在洞前面先擋一層。
比較常聽到的是 WAF 上的 virtual patch(虛擬補丁),不動程式本身,在 WAF 上加一條規則,把打這個洞的請求先擋在外面,爭取時間等正式的修補。
但它沒有把洞補起來,洞還在,只是路先被堵住了,正式的 patch 或改 code 之後還是要做。
作業系統這層也有類似的東西。
Buffer overflow 是程式寫入的資料超過預留的空間,蓋到旁邊的記憶體,攻擊者常利用這點把自己的程式碼塞進去再想辦法跳過去執行。
Windows 內建兩個機制讓這件事變難:
我的理解是,這兩個也不是在修那個 overflow,程式裡那段寫錯的地方還在,只是被利用的難度變高了。
真正的修法還是回到上面那個問題,洞是誰寫的,就找誰改。
| 洞在哪 | 能做的 | 我的理解 |
|---|---|---|
| 廠商產品(IIS、OS、韌體) | 裝廠商的 patch | 沒有原始碼,只能等廠商修 |
| 自家程式 | parameterized query、output encoding、input validation | 各擋各的,可以疊著用 |
| 兩者都還沒修好 | WAF virtual patch、補償控制、DEP/ASLR | 先擋著,洞還在 |
| logging、IDS | 發現有人在打 | 偵測,不是修 |
DVWA幫大家實作在上面給大家看,有興趣可以架一台在自己環境研究研究,自己架來打才不會有授權問題,不然上法院很麻煩滴!
Windows 的話,用系統管理員開 PowerShell 打:
Get-ProcessMitigation -System
可以看到這台電腦目前 DEP、ASLR 這些記憶體防護是開是關,現在就可以看一下自己的電腦。
看看就好,不要因為好奇手動去關它,關掉之後就是把門打開。
BTW,DVWA最好關在隔離的實驗環境裡,他本身就是設計來給你打的,可想而知漏洞一大堆;公司的電腦也不要自己去改記憶體防護的設定,公司公發電腦如果有裝EDR的話,正常也會設定不讓你改。