[ 筆記 ] 資訊安全 -SQL Injection、XSS


Posted by krebikshaw on 2020-08-13

SQL Injection

SQL Injection 駭客的填字遊戲

意思是駭客可以在輸入資料時,用一些奇怪的方式(惡意字串)竄改 SQL 語法,以偷取、假冒別人資料或刪除資料庫,例如以下輸入就可以成功登入別人帳號:

  • 登入時輸入
    • 帳號: ‘ or 1=1 –
    • 密碼: (甚至不用輸入)
// 接收輸入的 SQL
SELECT * FROM users HWERE user='' or 1=1 --' AND pwd =''; // => 永遠成立
  • SQL 語法中的 -- : 代表註解,所以後面的條件就被忽略
  • 因為條件多了 or 1=1,且 pwd 也因為註解被忽略掉,所以 WHERE 條件永遠成立,就可以成功登入帳號了。
  • 照理來說會登入第一個篩選到的帳號

解決方法: Prepare Statement

Prepare Statement 做的就是幫我們處理 SQL 跳脫這件事

步驟:

  • 把要放的參數都改成問號
  • 其實就是 SQL query 換種寫法,拿到資料後的操作是差不多
  • 要注意的是 bind_param() 的第一個參數,有幾個參數就要寫幾個字元,字元依照參數的資料類型而定
    • string => s
    • int => i
<?php
$stmt = $conn->prepare("SELECT * FROM users WHERE username=? and pwd=?"); // => 把參數換成 ?
$stmt->bind_param('ss', $username, $password); // => 替換成準備好的參數
$stmt->execute(); // => 執行 query 語法
$result = $stmt->getResult(); // => 執行結果
if ($result->num_rows > 0) {
    $row = $result->fetch_assoc(); // => 撈資料
}
?>

XSS ( Cross-Site-Scripting )

跟 SQL Injection 一樣,本質也是讓使用者「 輸入的資料」 變成「 程式的一部分 」

利用 input 欄位可以輸入內容的特性,只要使用者輸入特別的 JS 語法,且網頁有 輸出此內容 的時候,就可以竄改網頁或竊取資料。

XSS 漏洞分為幾種類型:

儲存型 XSS ( Stored )

  • 網址列看不出問題
  • 最常見的例子就是網站留言板或是訊息,因為使用者可以留任何訊息。
  • 存在 DB 裡,所以每個使用者打開都會看到被修改的內容
  • 殺傷力最大
<input type="text" placeholder="輸入內容"> // 網站的輸入欄位
<p>文字文字文字</p> // => 理論上的正常輸出

<script>alert("XSS攻擊測試");</script> // 駭客輸入的惡意碼
<p><script>alert("XSS攻擊測試");</script></p> // => 駭客輸入後的不正常輸出

反射型 XSS ( Reflected )

  • 把惡意程式藏在網址列裡,放在 GET 參數傳遞
  • 必須誘導使用者點到假連結才有用
    • 但網址列看起來會很可疑,可用短網址或特殊編碼魚目混珠

如果網頁是在網址上用參數判斷狀態:login.php?status='登入失敗',且輸出錯誤訊息的方式是 直接把 value 印在網頁上,那麼只要把 value 換成 js 語法就可以攻擊成功

// 網頁程式
if (isset($_GET['status']) && !empty($_GET['status'])) {
    echo $_GET['status'];
}

// 網址列
http://www.example.com?status='新增成功'  => 印出新增成功
http://www.example.com?status=<script>alert(1)</script>  => 執行惡意程式

DOM 型 XSS

  • 頁面上有使用到 .html() 或 .innerHTML() 的語法,就可能直接放 JS 語法
  • 跟前兩種 XSS 不一樣,此漏洞要在前端檢查
  • 最好都改成 .innerText()=> 只會輸出純文字

要在哪裡檢查?輸入 or 輸出

檢查有無惡意碼的時機,可以分為在「輸入之前」跟「輸出之前」,一般建議是無論如何、輸出端的檢查一定要做!

輸入驗證:

因為 XSS 有太多漏洞可以鑽: HTML, JavaScript, CSS, XML, URL,要很完整對輸入做防範非常困難。

例如刪除所有 <script>、 onerror 及其他可以執行 JS 的字串,但設黑名單也不是一個理想的方式,因為有太多種變形可以換,白名單是比較推薦的作法,只是要寫的完整也是非常麻煩。

輸出驗證:

  • 使用跳脫字元 escape
  • 如果「 輸出內容 」使用者可以操作,絕對不能輸出原碼( 未經處理 )
  • 把內容轉譯成純文字,而不是程式碼
// php 跳脫字元的內建函式 htmlspecialchars
echo htmlspecialchars($str, ENT_QUOTES, 'utf-8')
// 輸出時需要 encoding
& --> &amp;
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#x27;     
/ --> &#x2F;









Related Posts

W21 + W22_React 學習筆記

W21 + W22_React 學習筆記

[5] 測試是一門學問,關於自動化測試

[5] 測試是一門學問,關於自動化測試

從製作 visfest 2019 badge 認識 ObservableHQ

從製作 visfest 2019 badge 認識 ObservableHQ


Comments