在網站維護中,如果沒有持續檢查,往往漏洞被攻擊者發現的速度比防守方更快。
傳統做法是 人工定期測試,但這樣效率低,也容易遺漏。
利用 AI Agent,我們可以:
node-cron
或系統 crontab
,每天固定時間啟動掃描程式。' OR 1=1 --
)<script>alert(1)</script>
)express
建立 API 伺服器body-parser
處理 POST JSONimport express from "express";
import bodyParser from "body-parser";
import sqlite3 from "sqlite3";
const app = express();
const port = 3000;
app.use(bodyParser.json());
使用 SQLite 記憶體資料庫,預先建立兩個測試用帳號
const db = new sqlite3.Database(":memory:");
db.serialize(() => {
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)");
db.run("INSERT INTO users (username, password) VALUES ('admin', 'admin123')");
db.run("INSERT INTO users (username, password) VALUES ('test', 'test123')");
});
這裡故意使用字串拼接,方便測試 SQL Injection
app.post("/api/login", (req, res) => {
const { username, password } = req.body;
// 漏洞:直接拼接 SQL,容易被注入攻擊
const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
db.all(query, (err, rows) => {
if (err) return res.status(500).send("伺服器錯誤: " + err.message);
if (rows.length > 0) {
res.send(`歡迎 ${rows[0].username}!登入成功。`);
} else {
res.status(401).send("登入失敗,帳號或密碼錯誤。");
}
});
});
沒有做任何過濾,會讓 <script>
被直接執行
app.get("/api/comment", (req, res) => {
const { msg } = req.query;
res.send(`<h1>你的留言:</h1><p>${msg}</p>`); // 直接輸出用戶輸入
});
app.listen(port, () => {
console.log(`伺服器啟動中 → http://localhost:${port}`);
});
.env
中的 GEMINI_API_KEY
const API_KEY = process.env.GEMINI_API_KEY;
const genAI = new GoogleGenerativeAI(API_KEY);
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const targets = [
{
url: "http://localhost:3000/api/login",
payload: { username: "admin", password: "' OR 1=1 --" },
},
{
url: "http://localhost:3000/api/login",
payload: { username: "<script>alert(1)</script>", password: "123" },
},
];
export async function runScan() {
let results = [];
for (let t of targets) {
const res = await fetch(t.url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(t.payload),
});
const text = await res.text();
// 丟給 Gemini 分析
const ai = await model.generateContent({
contents: [
{ role: "user", parts: [{ text: `分析以下回應是否有漏洞:\n\n${text}` }] },
],
});
results.push({
target: t.url,
payload: t.payload,
status: res.status,
analysis: ai.response.text(),
});
}
// 確保 report 資料夾存在 (Day19/report)
const reportDir = path.join(__dirname, "report");
if (!fs.existsSync(reportDir)) {
fs.mkdirSync(reportDir);
}
// 存成報告檔
const file = path.join(reportDir, `report-${Date.now()}.json`);
fs.writeFileSync(file, JSON.stringify(results, null, 2));
return { file, results };
}
report/
資料夾存在runScan()
.then((report) => {
console.log("掃描完成,報告存檔:", report.file);
console.log("掃描結果:");
report.results.forEach((r, i) => {
console.log(`第 ${i + 1} 筆`);
console.log("Target:", r.target);
console.log("Status:", r.status);
console.log("Payload:", JSON.stringify(r.payload));
console.log("Analysis:", r.analysis, "\n");
});
})
.catch((err) => {
console.error("掃描失敗:", err);
});
runScan()
.then((report) => {
console.log("掃描完成,報告存檔:", report.file);
console.log("掃描結果:");
report.results.forEach((r, i) => {
console.log(`第 ${i + 1} 筆`);
console.log("Target:", r.target);
console.log("Status:", r.status);
console.log("Payload:", JSON.stringify(r.payload));
console.log("Analysis:", r.analysis, "\n");
});
})
.catch((err) => {
console.error("掃描失敗:", err);
});
node-cron
: 負責排程agent.js
內的 runScan()
import cron from "node-cron";
import { runScan } from "./agent.js"
0 3 * * *
代表每天 03:00 觸發,會自動產生報告。
console.log("排程器啟動中...");
// 每天凌晨 3 點自動掃描
cron.schedule("0 3 * * *", async () => {
console.log("開始弱點掃描...");
const report = await runScan();
console.log("掃描完成,報告存檔:", report.file);
});