Mitsubishi GX Works3 / GOT3 的惡意工程混淆邏輯注入攻擊
威脅揭露:https://github.com/MartinxMax/GOT3-exploit
GOT3 中的潛在安全問題
觸控螢幕上的部署頁面將上燈連接至 Y22
,下燈連接至 Y12
。
在 GX3 中,畫了一個簡單的控制畫面:
那麼,你覺得哪一個燈會亮起?
如果你認為會亮起的是 Y22
的燈 ——
你已經掉進陷阱了!
為什麼會這樣???
這個問題涉及到 GX 與 GT 間資料的讀寫方式差異。
在 GX 中,Y
輸出使用的是 八進位制(octal)地址。
但在 GT(GOT) 中,Y
的資料是以 十六進位制(hex)處理。
攻擊者可以利用這個差異,將惡意程式碼包裝在「不可偵測的外殼」中。
用計算驗證結果一樣。
利用 GOT3 特性修改原始專案圖檔,繞過管理者審核
模擬場景:一個內部使用的機密等級污水處理設施。僅有程式編輯部門的機器連網,但內網與設備隔離,無法由編程機橫向滲透。
- 事件 1:內部程式團隊完成 PLC 程式,交給技術主管審核,確認無誤後燒錄。
- 事件 2:你已控制了程式部門某台機器,並取得源碼程式。
- 事件 3:你只能修改 GOT3 專案。
功能區域 | 設備/訊號名稱 | 類型 | 地址(八進位) | 說明 |
---|---|---|---|---|
進水段 | 低水位 | DI 輸入 | X000 | 水位開關,低水位警報 |
高水位 | DI 輸入 | X001 | 高水位啟動水泵 | |
進水泵 | DO 輸出 | Y000 | 控制啟動/停止 | |
格柵池 | 格柵啟動按鈕 | DI 輸入 | X002 | 手動啟動格柵電機 |
格柵運行回訊 | DI 輸入 | X003 | 設備狀態反饋 | |
格柵電機輸出 | DO 輸出 | Y001 | 控制啟動/停止 | |
沉砂池 | 刮泥機啟動按鈕 | DI 輸入 | X004 | 手動控制 |
刮泥機運行狀態回訊 | DI 輸入 | X005 | 狀態反饋 | |
刮泥機輸出 | DO 輸出 | Y002 | 控制啟動/停止 | |
初沉池 | 進出水閥 | DO 輸出 | Y003 | 控制電動閥 |
液位檢測 | DI 輸入 | X006 | 液位開關 | |
生化池 | 溶氧儀 | AI 輸入 | D100 | 溶氧濃度偵測(類比) |
鼓風機 | DO 輸出 | Y004 | 控制啟動/停止 | |
攪拌機控制 | DO 輸出 | Y005 | 控制啟動/停止 | |
攪拌機運行狀態回訊 | DI 輸入 | X007 | 設備回饋 | |
二沉池 | 污泥泵啟動按鈕 | DI 輸入 | X010 | 手動啟動 |
污泥泵 | DO 輸出 | Y006 | 控制啟動/停止 | |
污泥泵啟動按鈕 | DI 輸入 | X011 | 手動啟動 | |
污泥泵 | DO 輸出 | Y007 | 控制啟動/停止 | |
加藥系統 | pH 感測器 | AI 輸入 | D101 | 偵測 pH 值 |
絮凝劑泵 | DO 輸出 | Y010 | 加藥控制 | |
pH 調整泵 | DO 輸出 | Y011 | 控制 pH 加藥 | |
消毒劑泵 | DO 輸出 | Y012 | 控制消毒加藥 | |
消毒段 | 消毒液液位檢測 | DI 輸入 | X012 | 液位警報 |
消毒啟動按鈕 | DI 輸入 | X013 | 手動啟動 | |
消毒泵 | DO 輸出 | Y013 | 控制啟動/停止 | |
警報系統 | 故障警報輸入 | DI 輸入 | X014 | 設備異常警報 |
警報輸出 | DO 輸出 | Y014 | 聲光警報 |
原始圖檔
警報功能運作正常。
加藥啟動:XB ⇒ X13
警報:XC ⇒ X14
加入加藥功能
加藥輸出:YA ⇒ Y12
警報輸出:YC ⇒ Y14
「無法察覺」的惡意專案與混淆邏輯,繞過管理者審查
劫持急停按鈕
完全禁用急停功能。
- 確認程式中加藥輸出
Y12
的邏輯:
2. 確認程式中警報輸出 Y14
的邏輯:
- 因為我們無法修改梯形圖邏輯,所以修改 GOT 畫面:
將急停按鈕綁定到 0x14。
- 將 惡意的
Main.GTX
專案 交給工程部門:
消毒正常啟動:
急停失效:
破壞性滲透
若可修改 Main.gx3
,那麼按下急停後會反而持續進行加藥/消毒。
我們已將警報控制綁定到 0x14,在梯形圖中對應 Y24
。
因此將 X24
加入 OR 邏輯控制加藥:
管理員審查時,只看到控制來自 X14
,容易誤以為是合法邏輯:
備註:實際上這完全不是真正的急停目標。
正常啟動消毒:
急停已被替換,加藥仍然持續進行:
WHO R U ?
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⣤⣤⣤⣶⣶⣾⣿⣿⣿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠷⠾⠿⠶⠶⠶⠿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣴⡶⠿⠟⠛⠛⠛⠻⠭⠭⠤⠤⠤⠒⠒⠛⠛⠉⢉⣉⣉⣉⡉⠉⠉⠓⠲⠤⣄⡀⠀⠀⠀⠀⠀⠈⠻⢿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⣴⡾⠟⠉⠁⠔⠊⠛⠓⠒⠒⠢⠤⠤⠤⠶⠶⠖⠒⠛⠉⠉⠉⠉⢉⣉⣉⠉⠙⠓⠲⢤⣄⡉⠲⢤⡀⠀⠀⠀⠀⠈⢻⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣾⡿⠋⠀⠀⠀⠀⣀⡤⠔⠒⠒⠒⠒⠲⠦⠤⠀⠀⠀⠀⠀⠀⠀⣠⠂⠀⠀⠀⠈⠉⠉⠓⠒⠤⣍⠳⢤⡈⠒⢄⡀⠀⠀⠀⢻⣿⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢠⣿⠀⠀b⠀⠀⠀⡐⠁⠀⠀⠀⠀⠀⠀⠀⠢⡀⠀⠀⠀⠀p⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢆⠙⠢⡀⠀⠀⠀t⠀⠀⢻⣷⡀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⢀⣾⡟⠀⠀⠀⠀⠀⠁⠀⢀⣀⣀⣀⣀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⠿⢿⣿⣿⣿⣿⣶⣦⣀⠀⠀⠀⠀⠀⠀o⠀⠀⠀⠀⠻⣷⡄⠀⠀⠀⠀⠀
⠀⢀⣴⡿⠋⣀⣀⣀⠀⠤⢄⢠⣾⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⡀⠀⠀⠀⠀⣴⣿⠏⠉⣀⣠⣼⣿⣿⣿⣿⣿⣭⣿⣧⠀⢠⣤⡄⠀⠀⢀⣴⣶⣢⡿⢿⣶⣄⠀⠀⠀
⢠⣿⠟⡡⠚⣉⠄⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠛⠛⠻⢿⣿⠿⠛⠀⠀⠀⠀⠻⢿⣶⡾⠟⠛⠉⠉⢠⣄⡀⠉⠉⠉⠉⠀⠃⣀⣤⣤⣶⣶⣤⣤⡀⠈⠙⠪⠻⣷⡄⠀
⣿⡿⡸⠁⡏⢠⣶⣾⣿⣶⣶⣤⡀⢀⣀l⡀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀i⠀⠈⠻⢿⣶⣤⣤⣤⣶⣾⠿⠟⠉⣴⠀⠀⠉⠻⣷⡀⠀⢁⠘⣿⡆
⣿⡇⡇⠀⡇⠈⠀⠀⢠⣆⠈⠿⠿⠿⠟⠀⠀⠀⢀⣴⡿⠟⠀⠀⠀i⠀⠀⠀⠀⣀⣀⣀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣿⣧⣀⠀⠀⢹⣿⠀⢸⠀⢸⣿
⠘⣿⣧⠀⠳⠄⠀⠀⣾⣿⠀⠀⠀⠀⠀⢀⣠⣾⣿⠋⠀⠀⠀⠀⠀⠀⣀⣀⣈⡙⠛⢻⣧⠓⠲⠖⠒⠢⠀⠀⢀⣀⣤⣶⣾⠟⠋⠉⢹⣿⠿⣷⡆⣸⡿⠀⡘⠀⢸⣿
⠀⠙⣿⡝⠒⢤⠀⣼⣿⣿⣤⡀⠀⠤⠚⠉⠘⠋⠛⣷⣄⠀⠀⡀⠀⠚⠿⠟⠛⠟⢠⣿⠇⠀⠀⣀⣠⣴⣶⣿⡿⢿⣿⠉⠀⠀⢀⣠⣿⡏⠀⠀⠀⡿⠁⢠⠇⢠⣿⠇
⠀⠀⢹⣿⡄⠀⢀⣿⣿⡿⢻⣿⣷⣦⣄⣀⡀⠀⠀⠈⠛⢿⠿⠃⠀⠀⠀⣀⣀⣠⣤⣴⣶⣾⠿⠟⠛⠉⠁⠀⢀⣾⣿⣤⣶⣾⣿⣿⠟⠁⠀⠀⠀⠤⠒⢉⣴⡿⠋⠀
⠀⠀⠀⣿⣇⠀⢸⣿⣿⡇⣼⡟⠈⠙⣿⡟⠿⠿⣿⣶⣶⣶⣶⠾⠿⣿⡿⠟⠛⠛⠋⠉⠹⣿⡄⠀⣀⣠⣤⣶⣿⣿⣿⠟⠉⣰⣿⠋⠀⠀⠀⠀⠀⢐⣾⡿⠋⠀⠀⠀
⠀⠀⠀⢹⣿⠀⢸⣿⣿⣷⣿⣿⣀⣸⣿⣁⣀⠀⠀⢸⣿⠁⠀⠀⠀⣿⡇⠀⠀⢀⣀⣀⣤⣿⣿⣿⣿⣿⠿⠛⠉⢿⣇⣀⣴⡿⠁⠀⠀⠀⠀⠀⢠⣿⠟⠀⠀⠀⠀⠀
⠀⠀⠀⢸⣿⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⢿⣿⠋⠉⠀⠀⠀⠀⢘⣿⣿⠏⠀⠀⠀⠀e⠀⠀⠀⣼⡏⠀⠀⠀⠀⠀⠀
⠀⠀⠀⢸⡏⠀⠀⢹⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⢿⡿⠛⠉⠁⠀⠀⠈⢿⣧⠀⠀⢀⣠⣾⡿⠛⠁⠀⠀⠀⠀⠀⠀⢀⣼⡟⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣿⡇⠀⠀⠈⢿⣧⣿⡇⢹⣿⡄⠹⣿⡄⠀⠈⢿⣇⠀⠀⠀⠀⢸⣷⠀⠀⠀⠀⠀⠀⢈⣿⣷⣾⡿⠟⠉⠀⠀⡀⠀⠀⢀⠀⢀⣴⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣿⡇⠀⠀c⠀⠈⠻⠿⣷⣶⣿⣷⣤⣿⣿⣄⣀⣘⣿⣀⣀⣀⣀⣸⣿⣤⣤⣤⣶⣶⣿⠿⠟⠋⠁⣀⡤⠖⢋⣩⡴⠞⢉⣤⣾⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⢰⣿⠀⠀⢀⠀⠀⠠⡀⠀⠈⠉⠉⠙⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠋⠉⠉⠁⠀⣀⡤⠖⢋⣡⡴⠞⠋⣡⣤⣾⠿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⢸⣿⠀⠀⠸⡀⠀⠀⠙⠶⣤⣀⣀⠀⠀⠈⠉⠉⠉⠉⠉⠉⢉⠉⣁⣀⣀⡀⠤⠖⣚⣩⠥⠖⠛⠉⣁⣤⣶⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⢸⣿⠀⠀⠀⠉⠲⢤⣄⣀⡀⠀⠈⠉⠉⠉⠀⠀⠀⣀⣉⣁⣀⡭⠭⠤⠒⠒⠋⠉⠁⢀⣠⣴⣶⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠈⢿⣆⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⣀⣤⣶⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠈⠻⣷⣦⣀c⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣤⣴⣾⣿⡿⠿⠟⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀h⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠈⠙⠻⠿⢿⢶⣶⣶⣶⣶⣶⣶⢾⠿⠿⠛⠛⠋⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀