在本教程中,您將學(xué)習(xí)如何修復(fù)常見的數(shù)據(jù)庫(kù)漏洞。
SQL注入是一種攻擊,攻擊者可以通過瀏覽器向應(yīng)用程序服務(wù)器輸入的數(shù)據(jù)(例如Web表單輸入)注入或執(zhí)行惡意SQL代碼。
它可用于公開敏感信息,例如用戶的聯(lián)系電話,電子郵件地址,信用卡信息等。攻擊者甚至可以使用它繞過身份驗(yàn)證過程并獲得對(duì)整個(gè)數(shù)據(jù)庫(kù)的訪問權(quán)限。讓我們看看它是如何工作的。
考慮以下SQL語句,它是在Web應(yīng)用程序中使用用戶名和密碼對(duì)用戶進(jìn)行身份驗(yàn)證的簡(jiǎn)單示例。
SELECT * FROM users WHERE username='username_val' AND password='password_val';
在這里,username_val和password_val分別表示用戶輸入的用戶名和密碼。如果用戶輸入諸如“ john”作為用戶名和“ 123”作為密碼之類的值,則結(jié)果語句將為:
SELECT * FROM users WHERE username='john' AND password='123';
但是假設(shè),如果用戶是攻擊者,他沒有在輸入字段中輸入有效的用戶名和密碼,而是輸入了類似以下內(nèi)容的值: ' OR 'x'='x
在這種情況下,上述SQL查詢將構(gòu)造為:
SELECT * FROM users WHERE username='' OR 'x'='x' AND password='' OR 'x'='x';
該語句是有效的SQL語句,由于WHERE 'x'='x'始終為true,因此查詢將返回users表中的所有行。您可以看到攻擊者通過一個(gè)小技巧就能輕松訪問數(shù)據(jù)庫(kù)的所有敏感信息。
如果users表很大,并且包含數(shù)百萬或行,則該單個(gè)語句還可能通過使系統(tǒng)資源超載而導(dǎo)致拒絕服務(wù)攻擊(DoS攻擊),并使您的應(yīng)用程序?qū)戏ㄓ脩舨豢捎谩?/p>
始終驗(yàn)證用戶輸入,不做任何假設(shè)。切勿直接從用戶輸入中構(gòu)建SQL語句。如果您使用的是PHP和MySQL,則可以使用mysqli_real_escape_string()函數(shù)創(chuàng)建可在SQL語句中使用的合法SQL字符串。
這是一個(gè)使用PHP和MySQL進(jìn)行用戶身份驗(yàn)證的非常基本的示例,演示了如何在從用戶那里獲取輸入時(shí)防止SQL注入。
<?php // Starting session session_start(); /* 嘗試MySQL服務(wù)器連接。 假設(shè)您使用默認(rèn)設(shè)置運(yùn)行MySQL服務(wù)器(用戶'root'沒有密碼) */ $link = mysqli_connect("localhost", "root", "", "demo"); // 檢查連接 if($link === false){ die("錯(cuò)誤:無法連接到數(shù)據(jù)庫(kù)。"); } // 轉(zhuǎn)義用戶輸入以保證安全性 $username_val = mysqli_real_escape_string($link, $_POST['username']); $password_val = mysqli_real_escape_string($link, $_POST['password']); if(isset($username_val, $password_val)){ // 嘗試選擇查詢執(zhí)行 $sql = "SELECT * FROM users WHERE username='" . $username_val . "' AND password='" . $password_val . "'"; if($result = mysqli_query($link, $sql)){ if(mysqli_num_rows($result) == 1){ // 用戶已通過身份驗(yàn)證,請(qǐng)?jiān)诖颂庍M(jìn)行操作 $row = mysqli_fetch_array($result); /*保存會(huì)話變量中的值, 以便稍后在同一會(huì)話引用中訪問它 */ $_SESSION['user_id'] = $row['user_id']; $_SESSION['first_name'] = $row['first_name']; header('Location: welcome.html'); } else{ echo "錯(cuò)誤!無效的用戶名或密碼。"; } } else{ echo "錯(cuò)誤:出了點(diǎn)問題。請(qǐng)?jiān)僭囈淮巍?quot;; } } // Close connection 關(guān)閉連接 mysqli_close($link); ?>
提示:測(cè)試應(yīng)用程序接收的數(shù)據(jù)的大小和類型或內(nèi)容,并實(shí)施適當(dāng)?shù)南拗埔苑乐瓜到y(tǒng)資源被利用。