加密與雜湊 hash
- 加密是一對一,所以被知道加密規則就可以解開。
- hash 是多對一,所以就算知道 hash 規則也不會知道是對應到哪個明文,因為有多個可能,但一個明文只會對應到一個 hash 後的文字,常用於網站密碼。
```php=
<?php
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
// 使用者註冊時,其輸入的 password 經過 hash 處理,
// 資料庫中儲存的密碼就不是使用者原本輸入的密碼。
password_verify($password, $row['password'])
// 使用者登入時,從其輸入的密碼與資料庫中經過 hash 處理的密碼進行比對,
// 來判斷使用者輸入的密碼是不是相同。
?>
---
### XSS Cross-site Scripting
* 可以在他人網站執行 Javascript,例如直接在留言輸入 html 標籤或是 JS 程式碼,php 會把這些文字解析成程式碼而不是單純的字串,直接影響到整個版面。
* 因為可以執行 JS 所以可以做很多種惡意攻擊,例如將網站導到釣魚網站、用 document.cookie 直接拿到 session id。
**修正問題:htmlspecialchars**
* 可以將一些特殊字元編碼成其他形式,就不會被解釋為程式碼。
![](https://i.imgur.com/j4haqHJ.png)
* ==把使用者可以自由控制的內容都加上 htmlspecialchars 處理==
```php=
<?php
function escape($str) {
return htmlspecialchars($str, ENT_QUOTES);
}
echo escape($row['content']);
// 這樣就會留言內容就會以文字原型顯示而不是程式碼
?>
SQL Injection
- 透過輸入內容來直接更改 query 的字串拼接去影響資料庫的內容。
其中"INSERT INTO comments(nickname, content) VALUES('%s', '%s')"
後面的 values 可以直接插入 query 指令,例如 VALUES(SELECT password FROM users WHERE id = 2, '%s')
,這樣就會直接印出密碼。
修正問題:prepared statement
==會自動將輸入內容當成字串拼接起來,就不會有誤認為程式碼的問題==
$sql = "SELECT * FROM users WHERE username=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $username);
$result = $stmt->execute();
// 這段只是執行然後判斷有沒有執行成功,後面還要再把結果取回
if (!$result) {
die($conn->error);
}
$result = $stmt->get_result();
//要將 $stmt 的結果取回,才會是原先的 $conn->query();
權限管理問題
- 在留言板的編輯與刪除中,可以透過調整網址的 get 參數來修改 id,就可以直接修改或刪除該 id 的留言。
- 因此在 select query 的時候就要確保選到的資料是該 user 本人的有權限更動的資料。
$sql = "UPDATE comments SET content=? WHERE id=? AND username=?"; // 多加一個 username 的條件來確認是不是本人, // 而 username 因為有設置過 session id 所以要登入才能取得。