정보보안의 원리
웹 416쪽 무료 · 종이책 B5 416쪽
© K-BOOKS · 무료 웹 열람용 콘텐츠입니다. 무단 복제·저장·인쇄·재배포를 제한합니다.
데이터베이스에서 자료를 찾으려면 질의를 보냅니다. SQL의 SELECT는 필요한 열을 선택하고, FROM은 대상 테이블을 지정하며, WHERE는 조건을 정합니다. 예를 들어 소유자가 alice인 책만 읽는 질의는 업무에서 허용할 검색 범위를 표현합니다. 이용자의 이름은 그 조건에 들어가는 데이터입니다.
문제가 되는 방식은 SQL 문장 조각과 외부 입력을 문자열 연결로 합치는 것입니다. 작은따옴표가 자료의 시작과 끝을 표시하는 문맥에서 입력에 같은 문법 기호가 들어가면, 프로그램이 의도한 자료 경계가 달라질 수 있습니다. SQL 인젝션은 따옴표 하나가 무조건 나쁘기 때문에 생기는 문제가 아닙니다. 데이터와 명령을 구분할 구조를 유지하지 않은 것이 핵심입니다.
다음 예제는 메모리에만 존재하는 두 행의 가상 데이터베이스입니다. 실제 계정이나 서버를 사용하지 않습니다. 먼저 데이터를 만든 뒤, 같은 입력을 문자열 연결 질의와 매개변수화 질의에 각각 전달해 결과가 왜 달라지는지 읽어봅니다.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE books(owner TEXT, title TEXT)")
db.executemany("INSERT INTO books VALUES(?, ?)", [
("alice", "Network Notes"),
("bob", "System Notes"),
])
owner = "alice' OR 1=1 --"Python 3 + sqlite3. 가상의 메모리 DB만 만들며 파일이나 외부 서버에 접근하지 않습니다.
unsafe = "SELECT title FROM books WHERE owner='" + owner + "'"
print(db.execute(unsafe).fetchall())
safe = "SELECT title FROM books WHERE owner=?"
print(db.execute(safe, (owner,)).fetchall())
db.close()위 준비 코드에 이어 실행하는 비교 예시. unsafe는 취약한 구현을 이해하기 위한 코드입니다.
첫 번째 결과에는 두 책이 모두 나오고, 두 번째 결과는 빈 목록 []입니다.
첫 질의에서는 owner의 작은따옴표가 원래 값의 경계를 끝냅니다. 뒤의 OR 1=1이 질의 조건으로 해석되어 두 행 모두 참이 됩니다. -- 뒤는 SQLite에서 주석으로 처리됩니다. 문제는 데이터로 받은 내용이 SQL 구조에 들어간 지점입니다.
두 번째 질의의 ?는 값을 넣을 자리입니다. 실행 함수의 두 번째 인수로 owner 전체를 전달하므로 해당 문자열 자체와 일치하는 소유자를 찾습니다. 그런 소유자는 가상 테이블에 없으므로 빈 목록이 나옵니다. 공격처럼 보이는 문자열을 단순히 지워서 해결한 것이 아닙니다.
일반 입력 alice를 전달하면 안전한 질의는 alice의 책 하나를 반환합니다. 실제 이름에 작은따옴표가 들어 있는 정상 데이터도 문법을 손으로 조립하지 않고 전달할 수 있습니다.
깨달음데이터가 무엇이든 그 데이터가 SQL 문법의 자리를 차지하지 않도록 구조를 분리하는 것이 핵심입니다.
매개변수는 일반적으로 값의 자리에 사용합니다. 테이블 이름과 열 이름, 정렬 방향까지 이용자가 임의로 정하게 만들고 같은 바인딩으로 해결할 수 있다고 가정해서는 안 됩니다. 정렬이 필요하면 프로그램에 정의한 허용 목록에서 고르게 하고, 선택 결과를 정해진 구조로 연결합니다. 입력 형식을 검사하는 일도 여전히 필요합니다.
매개변수화 질의가 권한 검사를 대신하지는 않습니다. 이용자가 102라는 번호를 보내서 다른 사람 문서를 조회할 수 있는 문제는 질의가 문법적으로 안전해도 생길 수 있습니다. 서버가 인증한 주체의 권한 범위 안에서 조회하도록 조건을 정해야 합니다. 데이터베이스 계정에도 업무에 필요한 권한만 줍니다. 조회 서비스가 전체 테이블을 삭제할 수 있다면 다른 결함이 생겼을 때 피해가 커질 수 있습니다.
오류 메시지와 응답 차이도 살펴야 합니다. 데이터베이스 오류 전체를 화면에 내보내면 내부 구조가 드러날 수 있고, 성공과 실패의 차이가 쌓이면 원래 공개하려던 것보다 많은 정보를 알려 줄 수 있습니다. 그렇다고 오류 문구만 숨긴다고 인젝션이 고쳐지지는 않습니다. 매개변수화와 권한, 오류 처리, 기록을 함께 확인해야 합니다.
저장 프로시저나 ORM을 사용했다는 이름도 면죄부는 아닙니다. 내부에서 동적 SQL을 다시 문자열로 합치면 같은 문제가 생길 수 있습니다. 점검에서는 도구의 이름보다 실제 값이 어디에서 질의로 바뀌는지 추적합니다. 수정 뒤에는 정상 이름, 따옴표가 있는 이름, 허용되지 않은 객체 요청을 각각 확인하여 정상 기능과 접근 경계가 모두 유지되는지 봅니다.
무료 학습은 그대로, 종이책은 필요한 분을 위한 선택지입니다.
웹 416쪽 무료 · 종이책 B5 416쪽
웹 513쪽 무료 · 종이책 B5 513쪽