SQL 삽입

SQL injection

사용자 입력을 쿼리 문자열과 분리해 SQL 명령으로 해석되지 않게 합니다.

···
html
<div class="sd"><div class="sd-head"><strong>SQL INJECTION</strong><span id="state">live check</span></div><div class="sd-stage"><div class="query mono" id="query">name = input</div><div class="split"><div class="tile bad" id="concat">concat: changed query</div><div class="tile good" id="param">parameter: data only</div></div></div><div class="sd-foot"><span id="caption">checking boundary</span><span>tap to step</span></div></div>
css
.sd{box-sizing:border-box;width:min(94vw,700px);height:min(86vh,318px);padding:clamp(9px,2.3vmin,18px);border:1px solid var(--line);border-radius:14px;background:var(--surface);color:var(--fg);display:flex;flex-direction:column;gap:clamp(6px,1.8vmin,12px);font:600 clamp(12px,2.6vmin,16px)/1.25 var(--font-sans, sans-serif)}.sd *{box-sizing:border-box}.sd-head,.sd-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:1.25em}.sd-head strong{color:var(--accent);letter-spacing:.06em}.sd-head span,.sd-foot{color:var(--muted)}.sd-foot{font-size:clamp(12px,2.4vmin,14px)}.sd-stage{position:relative;flex:1;min-height:0;display:flex;align-items:center;justify-content:center;gap:clamp(6px,2vmin,18px);overflow:hidden}.sd .mono{font-family:ui-monospace,monospace}.sd .tile{border:1px solid var(--line);border-radius:8px;background:var(--bg);padding:clamp(5px,1.5vmin,10px);text-align:center}.sd .good{color:var(--accent);border-color:var(--accent)}.sd .bad{color:var(--accent-3);border-color:var(--accent-3)}.sd .arrow{color:var(--muted);font-size:clamp(15px,4vmin,28px)}.sd .active{background:color-mix(in srgb,var(--accent) 16%,var(--surface));border-color:var(--accent)}.sd .blocked{background:color-mix(in srgb,var(--accent-3) 13%,var(--surface));border-color:var(--accent-3)}.sd-stage{flex-direction:column}.query{border:1px dashed var(--line);border-radius:6px;padding:clamp(4px,1.3vmin,8px);max-width:94%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.split{display:flex;gap:8px;width:min(96%,520px)}.split .tile{flex:1}.split .focus{box-shadow:0 0 0 2px currentColor}
js
let n=0;function advance(){n=1-n;document.getElementById('query').textContent=n?'SELECT … WHERE name = ?':'SELECT … WHERE name = '+String.fromCharCode(39)+'x'+String.fromCharCode(39)+' OR 1=1';document.getElementById('concat').classList.toggle('focus',!n);document.getElementById('param').classList.toggle('focus',!!n);document.getElementById('state').textContent=n?'bound value':'string concatenation';document.getElementById('caption').textContent=n?'input remains a value':'input alters query logic'}advance();setInterval(advance,950);
document.querySelector('.sd').addEventListener('pointerdown',advance);

SQL 삽입은 사용자 입력을 쿼리 문자열에 이어 붙일 때 데이터가 SQL 문법으로 해석되는 문제입니다. 조건을 바꾸거나 예상치 못한 행에 접근할 수 있습니다.

데모는 공격 문자열을 문자열 결합과 매개변수 바인딩에 각각 통과시킵니다. 매개변수화된 쿼리에서는 값이 데이터로 처리됩니다. 동적으로 만드는 테이블명·열 이름은 별도의 허용 목록으로 제한해야 합니다.

언제 쓰나

사용자 입력이 데이터베이스 조회·수정에 들어가는 모든 경로에서 매개변수 바인딩을 사용합니다.

페이지로 열기 ↗