駭客?聽起來真的超酷


Posted by 小小碼農 on 2021-06-22

這篇會說明基本常見的駭客入侵與防禦的方法

  • 有沒有印象使用瀏覽器的時候,莫名其妙被導到不知名網站,接著原本網站就莫名的被登出....?
  • 或是忘記帳密時,收到一封有你帳密的 email,跟你說這是你忘記的帳密...?

諸如此類狀況,當下可能覺得還好,沒事,但事後回想,心裡還是會有點毛毛的....好像有種怪怪的感覺正在萌芽....

請說明雜湊跟加密的差別在哪裡,為什麼密碼要雜湊過後才存入資料庫

得先說明密碼為何不能存明碼。

雖然後端資料庫在儲存使用者的密碼時,不能存明碼已經是一種常識,儘管大家都覺得自家資料庫很安全,絕不可能攻破,但攻擊簡單防守難,攻擊者只要找到一個漏洞就可以鑽,防守者卻得思考所有可能的攻擊,防守範圍根本不一樣。

這時候就要預設最壞情況 -- 資料庫被駭了,駭客得到密碼了,不過好在不是存明碼的形式,駭客可能可以破解,但或許要花上十年、二十年,應該沒有多少駭客會願意,這樣我們或許就可以說我們防守成功。

接下來是一些超前部署部分,看看如何做到即使資料庫被駭了,使用者的真實密碼也不會洩漏出去

  • 雜湊 (Hash)
    不可逆。就算知道了雜湊過後的秘文,也無法回推出明文

hash

  • 將明文丟進公式後變成一串秘文
  • 無論明文內容長短,透過雜湊演算法出來都是一樣的長度
  • 同樣的輸入經過雜湊,保證一定會得到同樣的輸出
  • 多對一關係,不同內容可能對應到同一組值,此情況稱為「碰撞(collision)」,但機率極低

    補充:一個雜湊函式的好壞也取決於是否容易發生碰撞

  • 由於無法逆向解出明文,安全性相較加密來的高

  • 常見演算法:SHA 系列

    方法:

  1. password_hash()
    $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
  • 為 PHP 內建的 hash() 函式,只需要將加密方式傳給 hash() 函式。可以直接指明 sha256, sha512, md5, sha1 等加密方式
    ex: $password = hash("sha256", $password);

  • 將經過演算法的密碼儲存在變數中

  • 第一個參數是原始 password,第二個參數是演算法,建議可使用 PASSWORD_DEFAULT,每次處理都會產生隨機的 SALT
  1. password_verify()

    $password = 'ilovecoding12345' // 原始密碼
    
    if(password_verify($password, $row_['password])) {
     $_SESSION['name'] = $username;
    } else {
     header('Location: login.php?errCode=2');
     die();
    }
    
    header('Location: index.php');
    
  • 檢查輸入的密碼是否存在相對應的資料,是則導回首頁,否則導回登入頁並報錯
  • 將經過 password_hash() 處理的密碼,進行驗證,用於登入功能
  • password_verify('使用者輸入的密碼', '資料庫裡的密碼'),根據回傳的 boolean 值,進行操作
  • 加密 (Encryption)
    可逆。知道了加密後的秘文,只要知道金鑰,就可以還原出明文

    • 將明文資訊改變成難以讀取的密文,例如常見的「凱薩加密」,可透過「解密」還原內容
    • 加密與解密都同樣要透過金鑰來執行
    • 一對一對應關係
    • 分為對稱與非對稱式

      • 對稱式加密:

        • AES, DES 等
        • 發送者與持有者持有相同金鑰來加解密資訊
        • 傳遞金鑰的過程中(發送 request, response)被竊取資訊的話,再強的加密演算法都沒有用,因此有了非對稱式加密
        • 明文 ABC,經由加密後每位向後移三位,變成 CDE,這樣就是簡單的對稱式加密
      • 非對稱式:

        • RSA, DSA 等
        • 使用者都擁有一對金鑰,公鑰加密,私鑰解密
        • 訊息由其中一把公鑰加密,必須由另一把私鑰解密
        • 安全性相較對稱式來得更高
        • 有五人 ABCD 與 E,還有一口箱子,E 將唯一一把私鑰留給自己,公鑰分別發給其餘四人一人一把,並且說:「有人想跟他說悄悄話就把訊息放到箱子裡上鎖」,過幾天 E 打開箱子真的有訊息。

        藉由上述,我們知道只有 E 能開箱子,因為只有他有唯一一把私鑰,同時確保只有 E 能看到其中的內容

額外補充 -- 雜湊加鹽(SALT)

一樣的密碼經過雜湊以後,就一定會有一樣的雜湊值,針對這一點,建立一個常用字串對照雜湊值的表格,藉此強硬破解雜湊後的密碼

我們叫它「彩虹表」

至於如何防範?我們只要給密碼加鹽(SALT)就可以。
在原本密碼雜湊前,先加入一段固定字串(SALT),比如在原本密碼前我們都先加上 1234

ilovecoding1234(SALT) -> 1234ilovecoding1234

這樣即使有了對照表,也不知道加入了什麼鹽或是怎麼加的,短時間也難以破解。
本人輸入密碼的話,只要照著原本方式加鹽回去,做雜湊,比較是否吻合資料庫中的雜湊值就可以了。

雜湊常用在平台上的密碼驗證,因為平台實際上不需要知道使用者真正輸入的密碼,透過雜湊不可逆的機制,可以最好的保護使用者的明碼。而區塊鏈則會用到不對稱式加密的機制,讓一個訊息能透過私鑰及公鑰被加密傳輸與保護。而編碼基本上毫無安全性可言,換個方式表達而已,像是摩斯密碼,只要有人懂這套規則就能輕易轉譯回來。

簡單說,密碼存明碼就是違反資訊安全的起手式!!不可姑息!!

includerequireinclude_oncerequire_once 的差別

此四種函式的作用都是包含並執行指定檔案,最主要差別在使用時機

  • include()和 require()差別

    • include() 引入檔案時,如遇到錯誤,會提示錯誤並繼續執行。
    • require() 引入檔案時,如遇到錯誤,會提示錯誤並終止執行。
    • require() 通常放在 php 頁面最前,php 在執行前就會先讀入 require()引入的檔案,檔案內容會變成此頁指令碼的一部份,include()只在用到時才放進來,通常是放在流程控制的處理區段中,php 指令碼在執行到它時,才會將檔案包含進來。即 require()是預載入機制,位置在指令碼最前面,一開始就引入所有可能用到的檔案;include()是即用即載入,位置靈活。
  • 在後面加上 _once 的區別

    • include()、require()執行即包含檔案,不會對引入的檔案進行比較判斷,可能會出現重複包含的情況;而 include_once()、require_once()在包含時會先判斷檔案是否已經包含過了,如果已包含,則不再包含檔案,這樣的引入檔案方式即可以節省資源,又可避免重複定義的錯誤。

請說明 SQL Injection 的攻擊原理以及防範方法

SQL injection

  • SQL 語法常用於 database 系統中,攻擊者可透過更改語法邏輯或加入惡意特殊指令方式,竊取或修改資料

  • 防禦方法:prepared statement
    「參數化查詢」或是「預處理」,簡單說就是另外準備好參數來給值,在所有需要填入數值或資料的地方。

    Prepared Statement 會替 SQL 語句進行預處理,利用提供的 bindValue 或 bindParam 函式將欲查詢的參數或數值綁定上去,底層查詢時,其參數會保證作為數值傳遞,不會成為 SQL 語句的一部份,因此可避免掉 SQL Injection 的問題

  • 方法舉例

      <?ph
        $sql = 'INSERT INTO comments (username, content) VALUE (?, ?)'; // 準備好 SQL 語法,用問號(稱為佔位符或參數)替換查詢中的所有變量
        $stmt = $connect->prepare($sql); // 準備結果查詢
        $stmt->bind_param('ss', $username, $content); //將所有變量綁定到先前準備的語句
        $result = $stmt->execute(); // 執行語句
      ?>
    

    建議所有要下 sql 的地方都要加上預處理方法(prepared statement)

請說明 XSS 的攻擊原理以及防範方法

XSS
Cross-site scripting,跨網站指令碼攻擊。

  • 透過網頁開發時的漏洞,在使用者可以輸入訊息的地方,輸入惡意指令碼,透過被攻擊者的身份去執行一些管理的動作以得到想要的資訊(帳號、密碼等),或是導向到釣魚網站。

惡意指令碼通常是 JavaScript,但其他語言 HTML, CSS, JAVA 等也都有可能

  • 防禦方法
    htmlspecialchars()

    將預定義的特殊字元轉換成 HTML 僅能顯示用的編碼

    • 語法
      htmlspecialchars( $string , $quote_flags , $encoding , $double_encode )

      • $string: 須轉換的字串
      • $quote_flags: 用來設定引號的轉換,基本上建議使用 ENT_QUOTES 單雙引號都轉換(預設是僅轉換雙引號)
      • $encoding: 用來設定要轉換的編碼,預設是 UTF-8
      • $double_encode: 是否要對全部進行轉換,預設值是轉換全部的 HTML 碼

請說明 CSRF 的攻擊原理以及防範方法

Cross Site Request Forgery,跨站請求偽造

  • 當用戶登錄網站時,聯覽器會記錄 cookies,如果用戶未登出或 cookies 未過期(關閉瀏覽器並不代表網站已登出或 cookies 可立即過期)的期間,造訪了其他危險或不知名網站,點擊了攻擊者的連結,便會向原網站發出某項功能請求(request),原網站的伺服器接收後會誤以為是用戶合法操作而執行。

簡單舉例,可能是在某大型平台點擊了某項連結,進而被導到其他(釣魚)網站,點了不知名的按鈕,然後就被駭客利用你本人發送 request 去取得某平台的資料或做出某項行為。

  • 防範手法

    • 用戶端

      • 使用完記得登出,也別隨意瀏覽不明網站
      • 避免在瀏覽器自動儲存帳密
      • 基本上,用戶端能做的不多
    • 伺服器端

      • request 裡面有一個欄位叫做 referer,代表這個 request 從哪裡來,可以檢查這個欄位是不是合法 domain
      • 加上圖形或簡訊驗證碼,常見於銀行帳戶等需要高度安全的領域,若每個網頁都這樣,也實在不方便
      • 加上 CSRF token,在 form 裡面加上一個 hidden 欄位,叫做 CSRF token,其中填入由 server 隨機產生的一組亂碼並且存在 server 的 session 中,提交後,server 比對 form 中的 token 是否跟 session 中的一樣,來確認是不是本人發出的 request,每一段不同 session 就應該要更換一次 CSRF token,但是攻擊者若是掌握任一個你底下的 subdomain,就可以幫你寫 cookie 且順利攻擊
      • Double Submit Cookie,解法與第 CSRF token 類似,前半段同樣都由 server 產生一組隨機的 token 且加在 form 上面,不同點在後面,不用把這個值寫在 session 保存在 server 外,同時讓 client side 設定一個叫 CSRF token 的 cookie,值也是一組 cookie,利用cookie 只會從相同 domain 帶上來的機制,使攻擊者無法從不同 domain 得到此 cookie
    • 瀏覽器端

      • SameSite cookie,簡單說只要 cookie 不是從原網頁來的就會被消除掉,但目前只有 chrome 支持

      • 原先:Set-Cookie: session_id=ewfewjf23o1;

      • 修正:Set-Cookie: session_id=ewfewjf23o1; SameSite

上述有幾點攻擊手法都是類似的,總歸一句:

「 永遠不要相信來自 client 的資訊 」

就可以避免掉很多惡意攻擊


#hacker







Related Posts

Laravel 7 passing collection to anonymous components

Laravel 7 passing collection to anonymous components

菜逼八寫Flutter(3) - 列表、圖片Widget

菜逼八寫Flutter(3) - 列表、圖片Widget

Express 實作留言板:新增會員、登入、留言、編輯及刪除

Express 實作留言板:新增會員、登入、留言、編輯及刪除


Comments