header-cover

SQL Injection이란

SQL injection이 무엇인지와 어떻게 막을 수 있는지

2022-11-09·
 

SQL Injection이란?

 
SQL 인젝션(SQL 삽입 공격)은 악의적인 사용자가 데이터베이스와 연동된 웹 애플리케이션에서 조작된 질의(쿼리)문을 주입하여 웹 서비스에 대한 DB정보를 열람또는 조작할 수 있는 하나의 취약점입니다. 인젝션 공격은 OWASP Top10 중 첫 번째에 속해 있었으며, 공격이 비교적 쉬운 편이고 공격에 성공할 경우 큰 피해를 입힐 수 있는 공격입니다.
 
OWASP : 에 관한 정보노출, 악성 파일 및 스크립트, 보안 취약점 등을 연구하는 회사.
보안에 큰 영향을 줄 수 있는 보안 취약점목록을 발표합니다
 
notion image

OWASP에서 발표한 10가지의 웹 보안위협

대표적인 사례들

 

공격방식

notion image
notion image
이때 로그인이 성공하게 된다면 SQL Injection이라고 할 수 있다
 
그렇다면 이러한 방식이 왜 실행될 수 있었을까?
  • 실제 실행되는 SQL 질의문 ( 사용자의 입력값을 그대로 전달받아 실행)
SELECT * FROM Users WHERE id = 'TESTID@gmail.com' AND password='123' OR "1"="1" //혹은 SELECT * FROM Users WHERE id = '' OR 1=1'--AND password='123'
123 OR 1=1 로 전달한 비밀번호가 SQL 조건에 그대로 들어가면서 1=1이라는 참조건과 OR(한쪽이라도 true면 전체 조건문이 true) 를 통해
password 부분이 무조건 TRUE 를 반환하게 되고 이때 아이디만 일치하거나 아이디 자체에 집어넣게 된다면 사용자 정보 혹은 관리자 계정(모든 데이터의 최상단에 있는 계정으로 로그인)을 알 수 있게 됩니다
 
  • 실제 서버쪽에서 처리하는 SQL 쿼리문 (예시)
const sql = "select * from Users where id='" + QueryString.id + "' AND password ='" + QueryString.password + "'"; con.query(sql, function (err, result) { if (err) throw err; res.send(result); });
 
이러한 방식을 논리적 오류를 이용하였다해서 오류 기반 SQL 주입(Error based SQL Injection)이라고 합니다
 
이 외에도
  1. UNION 기반 SQL 주입(UNION-Based SQL Injection) → UNION 명령을 이용
  1. 부울(참,거짓) 기반 SQL 주입([Blind] Boolean-Based SQL Injection) → 참과 거짓의 응답을 이용(로그인 , 아이디 중복확인)
  1. 시간 기반 SQL 주입 → 마찬가지로 참과 거짓의 응답을 이용하는 기법 SLEEP, BENCHMARK
  1. 저장된 프로시져 SQL 주입 → 저장 프로시저를 이용
  1. 다량 SQL 주입
 

대응 방식

 
위 예시를 바탕으로..
//in Node.js const sql = "select * from Users where id='" + req.params.id + "' AND password ='" + req.params.password + "'"; con.query(sql, function (err, result) { if (err) throw err; res.send(result); });
이러한 방식을 사용하면 안된다 ( 파라미터를 직접 코딩 )
 
  • Parameter Binding (필수적으로 사용됨)
(프로그램에 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는 행위를 의미)
 
bind variable(PreparedStatement in JAVA) → “'123' OR "1"="1"” 문장을 돌면서 바꿔준다+효율성
let id = req.params.id; //QueryString.id let password = req.params.password; //QueryString.password const sql = 'SELECT * FROM User WHERE id = ? AND password = ?'; dbconn.query(sql, [id , password], function(err, results, field){ ... }); //자동으로 파싱해준다
  1. 자동으로 SQL의 ‘?’의 순서와 배열 순서가 일치하도록 매핑되어 SQL이 실행됨
  1. SQL 질의문에 대해서 한번만 실행시키고 이후 값만 바꿔 계속 실행될 수 있음
 
 
  • 서버에서 발생한 에러메시지를 클라이언트에서 노출시키지 않을 것 ( 정보 노출 )
    • 어떤 dbms를 쓰는지, 버전이 무엇인지 등 이러한 부분이 노출되어 악의적으로 사용될 수 있다
 
  • 입력 값에 대한 검증
    • 하나의 대응 방식이 될 수 있다

참고한 블로그 및 자료

 
Video preview