🍃 NoSQL 인젝션(MongoDB) 시뮬레이터 Burp M00200 · NoSQL Injection
쿼리 파라미터를 그대로 필터 객체로 조립하면 $gt/$ne 같은 연산자가 주입되어 전체 문서가 유출됩니다. SQL 인젝션의 NoSQL 버전으로, 에러 시그니처(mongoerror)와 응답 길이 차이로 탐지합니다.
① 취약한 엔드포인트 (수동 탐침) VULNERABLE
username 파라미터에 JSON 연산자를 넣어 필터를 조작해 보세요. 취약 서버는 $gt: 로 전체 사용자를 반환하고, 안전 서버는 문자열 정확 일치만 허용합니다.
🔬 실전 스캐너 - Burp Suite 기법 적용
아래 스캐너는 실제 Burp Suite Pro가 사용하는 페이로드 전량을 이 페이지 안의 가상 타겟에 대입해 스캔합니다. 방어를 켜고 다시 스캔하면 같은 페이로드가 전부 차단되는 것을 확인할 수 있습니다. (모든 요청은 브라우저 안에서만 처리 - 실제 네트워크 전송 없음)
② 취약 vs 안전 코드
VULNERABLE
// Express + MongoDB - 파라미터를 필터로 그대로 조립
app.get("/api/user", async (req, res) => {
const filter = { username: req.query.username }; // 🚨 문자열?
// 몽고 드라이버는 JSON 형태 입력을 객체로 해석해
// {"$gt":""} 가 '모든 값보다 큼' 연산자로 동작한다
const users = await db.collection("users").find(filter).toArray();
res.json({ count: users.length, users });
});
SECURE
// 타입 강제 + 정확 일치
app.get("/api/user", async (req, res) => {
const u = req.query.username;
if (typeof u !== "string" || !/^[\w.-]{1,64}$/.test(u)) {
return res.status(400).json({ error: "bad username" }); // ✅ 타입/형식 강제
}
// 문자열이 확정됐으므로 연산자 주입 불가
const user = await db.collection("users").findOne({ username: u });
if (!user) return res.status(404).json({ error: "not found" });
res.json({ username: user.username, role: user.role }); // 필요 필드만
});
방어 핵심: 쿼리 입력에 타입 강제(typeof === 'string')를 먼저 할 것 · 몽고 드라이버에 JSON 원문을 필터로 넘기지 말 것 · 응답에는 필요한 필드만 · 스캐너는
mongoerror 시그니처(에러 기반)와 응답 길이 차(Blind)로 탐지한다.⚠️ 교육용 시뮬레이션입니다. 모든 공격은 페이지 내부 가상 타겟에서만 시연되며 실제 네트워크 전송이나 외부 시스템 접근은 없습니다. 페이로드 집합은 Burp Suite Pro 기법 카탈로그의 교육용 엄선 서브셋입니다.