🧨 실전 SQL 인젝션 — 브라우저에서 진짜 실행 REAL ENGINE · sql.js (SQLite WASM) CWE-89 · KISA SQL 삽입
이건 mock이 아닙니다. 실제 SQLite가 WebAssembly로 컴파일되어 브라우저 안에서 돌고, 당신의 입력을 그대로 SQL로 실행합니다. 진짜로 로그인을 우회하고 UNION으로 계정을 덤프해 본 뒤, 똑같은 페이로드가 파라미터 바인딩에서 막히는 걸 확인하세요.
WebAssembly SQLite 엔진 부팅 중…
🗄️ 실제 데이터베이스 (users 테이블)
이 행들은 브라우저 내 SQLite DB에 실제로 존재합니다 — 공격자가 노리는 대상입니다.
⚠️ 취약한 로그인 (문자열 결합 SQL) VULNERABLE
쿼리를 입력값 문자열 결합으로 만듭니다. 정상 로그인 후, 인젝션을 시도해 보세요.
실제 실행되는 SQL:
—
결과가 여기 표시됩니다.
🔎 취약한 검색 → UNION 계정 덤프 VULNERABLE
LIKE로 상품을 검색합니다. UNION 페이로드로 users 테이블을 결과에 끌어옵니다.
실제 실행되는 SQL:
—
결과가 여기 표시됩니다.
✅ 안전한 로그인 (파라미터 바인딩) SECURE
같은 엔진·같은 페이로드지만, 입력을 파라미터로 바인딩해 SQL로 해석되지 않습니다.
Prepared Statement + 바인딩 값:
—
결과가 여기 표시됩니다.
왜 뚫리고, 어떻게 막나
문자열 결합은 신뢰할 수 없는 입력을 SQL 본문에 섞습니다. 그래서
문자열 결합은 신뢰할 수 없는 입력을 SQL 본문에 섞습니다. 그래서
' OR '1'='1' -- 가 쿼리의 논리를 바꿔버리고(-- 가 비밀번호 검사를 주석 처리), 인증이 우회됩니다. 파라미터 바인딩은 쿼리와 데이터를 분리된 채널로 보내 드라이버가 입력을 SQL로 해석하지 않으므로, 같은 페이로드가 그냥 문자열 리터럴이 되어 어떤 사용자와도 일치하지 않습니다.
VULNERABLE
// Java — 문자열 결합 (취약) String q = "SELECT * FROM users WHERE " + "username='" + user + "' AND " + "password='" + pass + "'"; stmt.executeQuery(q); // 입력이 SQL로 실행됨
SECURE
// Java — PreparedStatement (안전) String q = "SELECT * FROM users WHERE " + "username=? AND password=?"; PreparedStatement ps = con.prepareStatement(q); ps.setString(1, user); ps.setString(2, pass); ps.executeQuery(); // 입력은 데이터로만 처리
⚠️ 교육용 시뮬레이션입니다. SQLite 엔진은 브라우저 안(sql.js / WebAssembly)에서만 로컬로 동작하며, 실제 서버·네트워크는 관여하지 않고 데이터가 기기를 벗어나지 않습니다.