sql注入入門
SQL注入入門
聲明
“SQL 注入,是網絡安全領域里最經典、最廣為人知的漏洞之一。它的出現,曾讓無數網站和數據庫在一夜之間陷入危機。今天,我們將通過實際案例,了解 SQL 注入的原理、危害以及如何防御。但在此之前,務必記?。罕菊n程僅用于學習與研究,請勿將所學用于任何非法用途?!?/p>
前置知識點
學習sql注入首先需要知道sql是什么
sql是結構化查詢語言,也是一種編程語言
通過這個語言我們可以對數據庫執行下面操作:
- 查詢數據
- 修改數據
- 刪除數據
- 添加數據
- ……
什么是數據庫
可以用來高效存儲大量數據,就和excel表格一樣
sql例子
假如test數據庫中有一個叫users的表,我們想要知道這個表里面有什么內容,則:
select * from users;
這個語句會輸出users表中的所有內容

可以看到有兩個字段分別是username和password
對應的有兩行數據
這個時候就可以簡單了解了sql的用法
需求
現在需要實現一個登錄的功能,其實很簡單,就是用戶輸入用戶名和密碼發送到服務器,服務器在將用戶提交的內容到數據庫中查詢,如果查詢存在這個用戶且密碼正確的話,就登錄成功,否則登錄失敗
那么這個時候的sql語句就可以是:
select username,password from users where username='' and password='';
單引號的內容就是用戶輸入的內容,如果數據庫里面存在這個用戶的話就會返回用戶這個數據,如果沒有的話就是空的數據,例如我們的用戶是chuxue:

可以看到服務器查詢到了1行數據,如果用戶不存在呢:

雖然寫著結果1,但是是0行數據
作為開發者
現在已經了解了sql語句以及登錄功能是如何實現的
需要你完成一個登錄的功能,這個時候我們去動手寫一個web服務
我們使用php作為后端程序:
# /var/www/html/sql.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQL注入練習</title>
<style>
.form-box{
width: fit-content;
margin: 150px auto;
background-color: #eee;
padding: 20px;
display: flex;
flex-direction: column;
gap: 10px;
font-size: 22px;
transform: scale(1.2)
}
input[type="submit"]{
padding: 5px;
font-size: 22px;
}
.success{
color:green;
font-size: 22px;
text-align :center;
}
.fail{
font-size: 22px;
text-align :center;
color: red;
}
</style>
</head>
<body>
<form method="get" action="./sql.php" class="form-box">
<label for="username">
username:
<input type="text" name="username" id="username">
</label>
<br>
<label for="password">
password:
<input type="password" name="password" id="password">
</label>
<br>
<input type="submit" value="登錄">
</form>
</body>
</html>
<?php
// 成功和失敗的樣式
// <div class='success'>登錄成功</div>
// <div class='fail'>登錄失敗</div>
$username = $_GET["username"];
$password = $_GET["password"];
$dbhost ='localhost';
$dbuser = 'root';
$dbpass = 'root';
$dbname = 'test';
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$conn){
echo "<div class='fail'>連接失敗</div>";
}
$sql = "select username,password from users where username='$username' and password='$password'";
$result = mysqli_query($conn, $sql);
if(mysqli_num_rows($result)>0){
echo "<div class='success'>登錄成功</div>";
}else{
echo "<div class='fail'>登錄失敗</div>";
}
?>
上面的代碼就簡單實現了一個登錄的功能,現在介紹一下關鍵的代碼:
# 創建兩個變量username和password,變量的值是前端通過get方式提交的數據
$username = $_GET["username"];
$password = $_GET["password"];
# 設計一個查詢語句,包含用戶和密碼的變量
$sql = "select username,password from users where username='$username' and password='$password'";
# 執行查詢,并把結果返回給$result變量
$result = mysqli_query($conn, $sql);
# 這個方法會返回查詢結果有幾行
mysqli_num_rows($result)
# 和前面說的一樣,如果有這個用戶的話上面返回的是1,如果沒有的話返回的是0
本地使用phpstudy搭建了php環境:

上來就是登錄失敗是因為一開始沒有用戶數據查詢,問題不大
我們嘗試輸入一個正確的用戶看看能不能登錄:

可以看到登錄成功
作為攻擊者
作為攻擊者,我們沒有賬號和密碼應該怎么去登錄到系統中呢?
這就是我們今天要學習的sql注入了
我們先看看我們在后端的語句
$sql = "select username,password from users where username='$username' and password='$password'";
我們發現用戶輸入的內容直接拼接到了sql語句當中,這樣帶來的后果就是攻擊者可以控制輸入的內容來改變sql語句的結構,例如:
# 攻擊者輸入的是英文單引號:'
# 那么原來的sql語句就變成了:
$sql = "select username,password from users where username=''' and password='$password'";
# 那么這個sql的結構就亂了,username的內容提前閉合了,并且多了一個單引號,那么這個語句是會報錯的

頁面確實報錯了,證明我們的確可以通過輸入的內容去控制sql語句的結構,現在我們就可以通過構造語句去繞過用戶密碼直接登錄:
payload:
' or 1=1 -- asd
解釋一下上面的內容
首先使用單引號提前閉合用戶名,不然我們輸入的sql語句都算是用戶名的內容,然后加上條件判斷or,or的作用就是只要兩邊有一個成立那么這個查詢語句就成立,所以不管用戶名對不對,我們輸入的1=1肯定是對的。
其次就是兩個橫桿“--”,這個在mysql中是注釋符號,sql語句不會執行后面的內容,這兩個橫桿后面必須帶上空格,這里輸入了asd是隨便輸入的,為了給你們體現空格,那么之前說了一個單引號會提前閉合語句,然后導致多了一個單引號并報錯,所以我們需要使用注釋符號去把后面的單引號注釋了。
這樣一來,攻擊者輸入的內容到服務器執行的語句就變成了:
select username,password from users where username='' or 1=1 --
由于1=1條件成立,所以查詢一定是有結果的并且是所有的結果,之前mysqli_num_rows的結果就會大于0,登錄成功:

防范
預處理 操作:
$stmt = $conn->prepare("SELECT username, password FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password); // s 表示字符串
$stmt->execute();
$result = $stmt->get_result();
認識sql注入
看到這里你已經初步了解到了sql注入的原理
實際上sql注入的方式有很多,不僅僅可以繞過登錄,不僅僅只是這種繞過
我們如果每種情況都自己寫靶機來訓練的話有點費時間,所以已經有人專門搭建好一個sql注入的訓練平臺:sqli-labs
項目地址:sqli-labs
小結
SQL注入是一種常見且危險的網絡攻擊方式,它通過惡意輸入改變SQL語句的結構,進而竊取或修改數據庫中的敏感數據。通過本教程,你已經了解了SQL注入的基本原理及一種常見攻擊方式。為了防止SQL注入攻擊,我們應始終采用參數化查詢、使用ORM框架、嚴格驗證用戶輸入等安全措施。

浙公網安備 33010602011771號