資訊安全不可疏忽。
簡述 這裡想強調「看不到不代表摸不到」的概念。在實作編輯與刪除留言時,為了管理權限,我們在渲染畫面的時候多加一個判斷是只有自己的留言才會顯示編輯跟刪除的按鈕 ,像這樣:
火山矽肺病只有在自己登入後才可以編輯或刪除自己的留言。
雖然畫面上表面上看起來沒什麼問題 ,但其實這背後存在一個漏洞,等等讓我們繼續看下去。
你想不到的神展開 這裡就不賣關子了,直接讓你看有什麼漏洞。
刪除別人的留言:
修改別人的留言:
發現問題 為什麼會這樣?這得看一下我們是怎麼實作編輯與刪除功能的。
編輯留言:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php require_once ('./conn.php' ); $id = $_POST ['id' ]; $content = $_POST ['content' ]; $sql = "UPDATE comments SET content=? WHERE id=?" ; $stmt = $conn ->prepare($sql ); $stmt ->bind_param('si' , $content , $id ); $stmt ->execute(); header('Location: ./index.php' ); ?>
刪除留言:
1 2 3 4 5 6 7 8 9 10 11 12 <?php require_once ('./conn.php' ); $id = $_GET ['id' ]; $sql = "UPDATE comments SET is_deleted=1 WHERE id=?" ; $stmt = $conn ->prepare($sql ); $stmt ->bind_param('i' , $id ); $stmt ->execute(); header('Location: ./index.php' ); ?>
注意到問題了嗎?這兩段程式完全沒有做權限檢查 。
為什麼一開始要強調「看不到不代表摸不到」?因為這就是問題所在,就算我讓前端畫面看起來不能動別人的留言,但我還是可以用「網址」發一個 GET
請求到後端,讓後端執行對應指令。
解決問題 所以正確的作法應該是後端也要做權限檢查 ,既然已經有登入機制,那在做編輯、刪除或新增等等的資料時都應該要像登入一樣用 session 機制確保是使用者本人 ,才可以執行對應行為。
所以把剛剛的程式碼修改一下。
刪除留言:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php require_once ('./conn.php' ); session_start(); $id = $_GET ['id' ]; $username = $_SESSION ['username' ]; $sql = "UPDATE comments SET is_deleted=1 WHERE id=? AND username=?" ; $stmt = $conn ->prepare($sql ); $stmt ->bind_param('is' , $id , $username ); $stmt ->execute(); header('Location: ./index.php' ); ?>
編輯留言:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php require_once ('./conn.php' ); session_start(); $id = $_POST ['id' ]; $content = $_POST ['content' ]; $username = $_SESSION ['username' ]; $sql = "UPDATE comments SET content=? WHERE id=? AND username=?" ; $stmt = $conn ->prepare($sql ); $stmt ->bind_param('sis' , $content , $id , $username ); $stmt ->execute(); header('Location: ./index.php' ); ?>
後記 在做完這個 case 後體會到原來有些事情不是「單靠前端」就能解決的。像是表單驗證,即便前端先檢查過後端也要再檢查一次。為什麼?因為使用者很多時候可以繞過前端的檢查 ,直接向後端發 request,如果這時候後端沒有做檢查呢?那就挫咧但了。所以比起前端,後端更需要具備資訊安全的知識,這一點真的很重要,很重要。