1.實驗內容
1.1 近期學習內容簡述
(1)學習了Web前後端的語言的簡介
(2)學習了SQL隱碼攻擊的多個例項,知道了SQL隱碼攻擊的原理
(3)學習了XSS跨站指令碼攻擊的原理和示例
(4)瞭解了CSRF的原理和防範方法
(5)瞭解了Burpsuite等工具
1.2 實驗內容簡述
- (1)Web前端HTML
能正常安裝、啟停Apache。理解HTML,理解表單,理解GET與POST方法,編寫一個含有表單的HTML - (2)Web前端javascipt
理解JavaScript的基本功能,理解DOM
在(1)的基礎上,編寫JavaScript驗證使用者名稱、密碼的規則。在使用者點選登陸按鈕後回顯“歡迎+輸入的使用者名稱”
嘗試注入攻擊:利用回顯使用者名稱注入HTML及JavaScript - (3)Web後端:MySQL基礎:正常安裝、啟動MySQL,建庫、建立使用者、修改密碼、建表
- (4)Web後端:編寫PHP網頁,連線資料庫,進行使用者認證
- (5)最簡單的SQL隱碼攻擊,XSS攻擊測試
- (6)安裝DVWA或WebGoat平臺,並完成SQL隱碼攻擊、XSS、CSRF攻擊
2.實驗過程
2.1 Web前端HTML(能正常安裝、啟停Apache。理解HTML,理解表單,理解GET與POST方法,編寫一個含有表單的HTML)
(1)正常安裝、啟停Apache
-
使用
sudo apt install apache2
命令自動安裝配置Apache(由於kali自帶,這裡就不展示了) -
使用
sudo systemctl start apache2
命令啟動Apache,使用sudo systemctl status apache2
命令檢視Apache狀態
可知已經啟動
-
瀏覽器瀏覽
localhost
可再次確定Apache啟動成功
-
使用
sudo systemctl stop apache2
命令關閉Apache,使用sudo systemctl status apache2
命令檢視Apache狀態
可知已經關閉
(2)理解HTML,理解表單,理解GET與POST方法,編寫一個含有表單的HTML
-
在
/var/www/html/
建立檔案Get_method.html
- 建立一個html檔案在桌面,然後使用命令
sudo mv Get_method.html /var/www/html/Get_method.html
將其移動到/var/www/html/
- Get_method.html中寫入Get方法的html程式碼
- 訪問
http://localhost/Get_method.html
並提交資料
可知,Get方法提交後,資料在URL中可見
- 建立一個html檔案在桌面,然後使用命令
-
在
/var/www/html/
建立檔案Post_method.html
-
建立一個html檔案在桌面,然後使用命令
sudo mv Post_method.html /var/www/html/Post_method.html
將其移動到/var/www/html/
-
Post_method.html中寫入Post方法的html程式碼
-
訪問
http://localhost/Post_method.html
並提交資料
可知,Post方法提交後,資料在URL中不可見,因為資料放在HTTP請求的主體部分(body),不會顯示在URL中。
-
但是抓包還是能抓到明文資料,使用https就會安全很多
-
(3)總結 GET 方法和 POST 方法
區別 | GET 方法 | POST 方法 |
---|---|---|
請求目的 | 從指定的資源請求資料 | 向指定的資源提交資料以進行處理(例如,建立/更新資源) |
請求引數位置 | 引數附加在URL的末尾(查詢字串) | 引數包含在HTTP請求的主體中 |
資料可見性 | 引數在URL中可見,可能會被快取和記錄在伺服器日誌中 | 引數在HTTP請求主體中,相對不那麼容易被直接訪問或記錄 |
資料大小限制 | 通常受限於URL長度和伺服器配置(較短) | 無嚴格限制,取決於伺服器配置(較長) |
安全性 | 不太安全,因為引數在URL中可見 | 相對更安全,因為引數不在URL中,但需要使用HTTPS來確保資料傳輸的安全性 |
瀏覽器書籤 | 可以將請求URL書籤化 | 無法直接書籤化POST請求的URL |
快取 | 瀏覽器和某些中介軟體可能會快取GET請求的響應 | POST請求的響應通常不會被快取 |
使用場景 | 適用於請求資料而不改變伺服器狀態的操作(例如,搜尋查詢) | 適用於提交資料以改變伺服器狀態的操作(例如,表單提交) |
2.2 Web前端javascipt(理解JavaScript的基本功能,理解DOM;在(1)的基礎上,編寫JavaScript驗證使用者名稱、密碼的規則。在使用者點選登陸按鈕後回顯“歡迎+輸入的使用者名稱”;嘗試注入攻擊:利用回顯使用者名稱注入HTML及JavaScript)
-
在
/var/www/html/
建立檔案Post_JS.html
-
Post_JS.html中寫入Post方法的html程式碼
點選檢視程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register: POST JS 20222420</title>
<style>
/* 簡單的樣式,用於顯示歡迎資訊 */
#welcomeMessage {
color: green;
font-weight: bold;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Register: POST JS 20222420 </h1>
<form id="myForm" action="/submit" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<br><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br><br>
<button type="submit">Submit</button>
</form>
<p id="welcomeMessage"></p> <!-- 用於顯示歡迎資訊的元素 -->
<script>
// 獲取表單元素
const form = document.getElementById('myForm');
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
// 新增事件監聽器
form.addEventListener('submit', function(event) {
// 阻止表單的預設提交行為
event.preventDefault();
// 獲取使用者輸入
const username = usernameInput.value.trim();
const password = passwordInput.value.trim();
// 驗證使用者名稱和密碼
const usernameValid = username.length >= 5;
const passwordValid = password.length >= 8 && /\d/.test(password);
// 如果驗證透過
if (usernameValid && passwordValid) {
// 顯示歡迎資訊
document.write('歡迎' + username);
} else {
// 如果驗證失敗
alert('使用者名稱必須至少包含5個字元,密碼必須至少包含8個字元且包含至少一個數字。');
}
});
</script>
</body>
</html>
-
驗證“JavaScript驗證使用者名稱、密碼格式”的功能。驗證在使用者點選按鈕後回顯“歡迎+輸入的使用者名稱”的功能。
- 使用者名稱符合,但密碼未含數字
我只設定了一個提示資訊,所以使用者名稱和密碼均提醒了
- 使用者名稱長度不夠,密碼符合
我只設定了一個提示資訊,所以使用者名稱和密碼均提醒了
- 使用者名稱、密碼格式均符合,回顯“歡迎+輸入的使用者名稱”
- 使用者名稱符合,但密碼未含數字
-
注入攻擊:利用回顯使用者名稱注入HTML及JavaScript
使用者名稱輸入<script>alert('你被20222420攻擊了!')</script> <h1>你被20222420攻擊了</h1>
- JavaScript效果
- HTML效果
- JavaScript效果
2.3 Web後端(MySQL基礎:正常安裝、啟動MySQL,建庫、建立使用者、修改密碼、建表)
(1)安裝
使用sudo apt install mariadb-server
命令自動安裝配置即可,mariadb-server適用於需要儲存和管理大量資料的場景。由於kali自帶了mariadb,這裡就不展示了
(2)啟動並驗證,並登入
-
使用
systemctl start mysql
啟動,systemctl status mysql
驗證
disable是指未設定開機自啟動,但其是啟動了的、在執行的
-
登入,使用
sudo mysql -uroot -p
,輸入mysql的密碼時直接輸入“回車”
(3)建庫並驗證
使用create database test;
建立名為test的資料庫例項,然後使用show databases;
驗證
(4)建立使用者並驗證
使用CREATE USER 'test'@'%' IDENTIFIED BY 'test';
,還可以將test資料庫例項的許可權授予test使用者
(5)修改密碼
使用ALTER USER 'test'@'%' IDENTIFIED BY 'change';
(6)建表並使用、驗證
-
使用
CREATE TABLE testTable (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL);
可以建立一個表並設定了主鍵
-
新增資料到表,只需要新增到
name
,主鍵會自動遞增新增
INSERT INTO testTable (name) VALUES ('Alice');
`INSERT INTO testTable (name) VALUES ('Bob');``
-
檢視、驗證表
使用select * from testTable;
,可知表建立成功併成功新增了資料
2.4 Web後端:編寫PHP網頁,連線資料庫,進行使用者認證
-
root使用者建立
user_auth
資料庫例項,並建立表users
、插入資料-
建立
user_auth
資料庫例項
-
進入例項,建立表
users
,CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL,password VARCHAR(50) NOT NULL);
-
修改root密碼,使其不為空(否則後續連不上),並給予其user_auth的許可權(雖然預設root建立者有許可權)
-
插入資料,
INSERT INTO users (username, password) VALUES ('testuser', 'testpassword');
-
-
編寫PHP網頁
點選檢視程式碼
<?php
session_start();
// 資料庫連線引數
$servername = "localhost";
$dbusername = "root";
$dbpassword = "root";
$dbname = "user_auth";
// 建立資料庫連線
$conn = new mysqli($servername, $dbusername, $dbpassword, $dbname);
// 檢查連線是否成功
if ($conn->connect_error) {
die("連線失敗: " . $conn->connect_error);
}
// 如果表單已提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$inputUsername = $_POST['username'];
$inputPassword = $_POST['password'];
// 查詢資料庫中的使用者
$result = $conn->query("SELECT * FROM users WHERE username = '$inputUsername' AND password = '$inputPassword'");
if ($result->num_rows > 0) {
// 如果使用者存在,獲取其資訊
$row = $result->fetch_assoc();
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $inputUsername;
echo "登入成功!";
// 這裡可以重定向到其他頁面
// header("Location: protected_page.php");
// exit();
} else {
echo "使用者名稱不存在,或密碼錯誤。";
}
// 關閉結果集
$result->close();
}
// 關閉資料庫連線
$conn->close();
?>
<!DOCTYPE html>
<html>
<head>
<title>使用者登入</title>
</head>
<body>
<h2>登入 made by 20222420</h2>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
使用者名稱: <input type="text" name="username" required><br>
密碼: <input type="password" name="password" required><br>
<input type="submit" value="登入">
</form>
</body>
</html>
- 登入,驗證“使用者認證”功能
-
使用者不存在或密碼錯誤示例
我沒有區分具體是使用者不存在還是密碼錯誤
-
驗證,登入成功示例
-
2.5 最簡單的SQL隱碼攻擊,XSS攻擊測試
使用2.4中的資料庫和php網頁
-
SQL隱碼攻擊
使用' or 1=1; --
作為使用者名稱,注意一定要在--
後新增空格否則會卡死在相關語句。密碼可以隨便填
這樣sql語句變為SELECT * FROM users WHERE username = '' or 1=1; -- AND password = '$inputPassword'
。WHERE中一定為真,並且--
後的語句被註釋掉了導致不需要密碼
-
XSS攻擊
-
首先需要修改一下php網頁,使其可以回顯使用者輸入的賬戶名,否則攻擊語句無法執行
如圖,修改程式碼,使其可以在登入失敗時回顯輸入的使用者名稱
-
驗證,輸入
<script>alert("20222420XSS")</script>
如圖,利用網站沒有對使用者提交資料進行轉義處理或者過濾的缺點,新增了html程式碼,嵌入到web頁面中去
-
2.6 安裝DVWA或WebGoat平臺,並完成SQL隱碼攻擊、XSS、CSRF攻擊
(1)DVWA平臺
-
完成SQL隱碼攻擊
- 首先輸入
' or 1=1; --
進行測試
可以,SQL隱碼攻擊已經成功,輸出了全表的內容。還可知顯示的id並不是表中的id而是直接返回了我輸入的內容。
- 進一步進行SQL隱碼攻擊,獲取更多資訊
使用' or 1=1 union select version(),database(); --
如下圖,可知,不僅顯示了人名,還透過union顯示了資料庫的版本號為“5.7.26”,及當前資料庫名“dvwa”
- 首先輸入
-
完成XSS攻擊
-
題目如圖
-
這一題中,只能選擇語言並提交。透過仔細觀察和反覆嘗試,可知點選提交後會在URL中出現
default=
並顯示所選擇的語言。
可以分析出,該網頁使用的是GET來傳遞引數
-
改變
default=
後的內容,實現XSS攻擊
改為<script>alert("20222420XSS")</script>
,由下圖可知成功
-
-
完成CSRF攻擊
-
分析該題
該題可以更改自己的密碼,然後可以驗證修改後的密碼
-
測試後發現,引數直接透過URL傳遞
-
準備CSRF攻擊
透過burp攔截,我就得到了一個傳送的包,然後透過burp中的工具直接便捷得生成CSRF攻擊用的html
-
修改一下生成的html中的密碼的值,使其變為我想要攻擊他人時使其密碼改變為的值,如
6666
,然後複製生成的URL
-
這樣,當他人在登陸著
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/
時,若點選了我的危險網站(即上面生成的URL,或包含該URL的其他看似正常的網站),他的密碼就會被我改變
如下圖所示
-
測試
由下圖可知,成功了
-
(2)WebGoat平臺
-
完成SQL隱碼攻擊
-
在
Login_Count
輸入1 or 1=1; --
進行測試
但顯示無法解析我的輸入到一個數字
-
檢視題目得知,只有一個空對於SQL隱碼攻擊是脆弱的,看來應該是下面一個空
在User_Id
輸入1 or 1=1
,在Login_Count
輸入正常的數字。如下可知注入成功。
-
-
完成XSS攻擊
直接輸入<script>alert("20222420XSS")</script>
-
完成CSRF攻擊
-
這道題需要從傳送評論,但必須從其他地方傳送
只需要用burp攔截獲取包的格式,然後生成CSRF的html,再修改一下生成的html即可,如下圖,我想傳送的評論是test
星級為4
-
複製得到的URL
-
驗證
當登陸著http://127.0.0.1:8080/WebGoat/csrf/review
的人點選了該URL,就會傳送該評論(test
,星級為4
)
驗證過程如下面三圖,可知我(即被攻擊者)已經成功從其他位置傳送了該評論
-
3.問題及解決方案
- 問題1:無法將建立的檔案放入/var/www/html/
- 問題1解決方案:利用sudo mv命令就有許可權了
- 問題2:SQL隱碼攻擊時一直不成功
- 問題2解決方案:詢問AI,本來AI是不會給相關的答案的。但換一種方式問,問我這樣能否透過,AI就給出了回答。然後我就得知原來--後需要空格才能起到註釋的效果,這樣我就解決了問題。
- 問題3:我寫的網頁先用SQL語句驗證了使用者名稱,然後用$row['password'] === $inputPassword驗證密碼。但只有使用者名稱能使用SQL隱碼攻擊,這導致我無法用SQL隱碼攻擊登入。
- 問題3解決方案:更改程式碼,像課件裡的一樣用SQL語句同時驗證使用者名稱和密碼即可直接透過SQL隱碼攻擊登入。
- 問題4:php連線不上資料庫
- 問題4解決方案:經過檢查,程式碼是沒問題的,資料庫也沒問題。可能是因為資料庫的root使用者沒有設定密碼,且$dbpassword = "";不代表沒有密碼,導致連線不上資料庫。設定密碼後便解決了。
4.學習感悟、思考等
在這次實驗中,我體會了Web開發中的前端與後端技術是如何協同工作的。透過安裝和配置Apache伺服器以及MySQL資料庫,我學會了如何在伺服器端搭建一個Web環境。編寫HTML表單和JavaScript驗證邏輯,讓我對前端技術有了更深入的理解,特別是在處理使用者輸入和表單提交方面。同時,我也認識到了前端驗證的重要性,但它並不能替代後端驗證,因為前端驗證可以被繞過。此外,透過編寫PHP網頁和進行使用者認證,我進一步瞭解前端和後端mysql的協同。在測試SQL隱碼攻擊、XSS攻擊、CSRF攻擊的過程中,我也深刻認識到了Web安全的複雜性。
參考資料
- 《Java程式設計與資料結構教程(第二版)》
- 《Java程式設計與資料結構教程(第二版)》學習指導
- ...