iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Security

從桃子園灘頭到CySA+系列 第 18 篇

Day18|漏洞在誰身上就補誰

  • 分享至 

  • xImage
  •  

聽起來合理且簡單對吧~但在有時間限制下必須快速決定時真的會混淆,先看清楚漏洞在誰的身上再說。

前一題剛弄懂,XSS 要回去改網站的程式,做 input validation來避免。
下一題掃描報告上又看到 XSS,我題目都沒看完就選了 input validation。

結果正解是 patch,我想說:what???image
(梗圖改編,若有版權敬請告知,配合下架)

結果那個 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。
要把使用者的輸入印回頁面之前,先把 <、> 這類字元轉成 &lt;、&gt;,瀏覽器就會把它當文字顯示,不會當成標籤去執行。

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';";

image

換到 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 那格只能填值。
它兩個都做了,一層沒擋住還有下一層。
image

XSS(Reflected)也一樣,low 是把輸入直接印出來:

$html .= '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';

image

impossible 多了一個 htmlspecialchars,這就是 output encoding:

$name = htmlspecialchars( $_GET[ 'name' ] );
$html .= "<pre>Hello {$name}</pre>";

image

Day17 我在 low 打 <script>alert('XSS')</script> 會跳窗,換到 impossible 同樣的字串就只會原封不動印在頁面上。

Logging只能紀錄,不能修正

還有兩件事常跟上面三個擺在一起的,logging 跟 IDS。
它們很重要,但它們不會讓 SQL injection 打不進來,它們做的是打進來之後讓你知道。

資安控制大致可以照「什麼時候起作用」來分:

  • Preventive(預防):事情發生之前擋下來,Parameterized query、Output encoding、Input validation三個都是,在惡意payload進來以前就擋掉。
  • Detective(偵測):發生了、或正在發生的時候"發現"它,logging、IDS 在這格
  • Corrective(矯正):發生之後把損害修回來,裝 patch、還原備份
  • Compensating(補償):原本的控制做不到的時候,用別的方式達到差不多的效果,Day15 講過

另外還有一種分法是看這個控制是誰在做的,technical(技術,系統自己跑)、managerial(管理,政策與風險評估)、operational(操作,人去執行的流程)。兩種分法同時出現,像是logging 就是 technical 加 detective;人員門禁管制就比較屬於operational加preventive,不過分類法有physical的話就選physical加preventive。

修不了的時候,先擋著

現實上 patch 不一定馬上有,有了也不一定馬上能裝,系統停不了、要等維護時段。
自己的程式也一樣,改 code、測試、上線,不會是今天發現明天就好。

這段空窗期能做的,是在洞前面先擋一層。
比較常聽到的是 WAF 上的 virtual patch(虛擬補丁),不動程式本身,在 WAF 上加一條規則,把打這個洞的請求先擋在外面,爭取時間等正式的修補。
但它沒有把洞補起來,洞還在,只是路先被堵住了,正式的 patch 或改 code 之後還是要做。

作業系統這層也有類似的東西。
Buffer overflow 是程式寫入的資料超過預留的空間,蓋到旁邊的記憶體,攻擊者常利用這點把自己的程式碼塞進去再想辦法跳過去執行。
Windows 內建兩個機制讓這件事變難:

  • DEP(Data Execution Prevention):放資料的記憶體區塊不准當成程式碼執行,塞進去了也跑不起來
  • ASLR(Address Space Layout Randomization):程式載入記憶體的位置每次隨機,攻擊者比較難猜要跳到哪裡

我的理解是,這兩個也不是在修那個 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的話,正常也會設定不讓你改。


上一篇
Day17|先看這段是語言什麼再做決定
系列文
從桃子園灘頭到CySA+ 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言