1. Lab 개요

이번 실습은 상품 카테고리 필터에서 발생하는 SQL Injection 취약점을 이용하여, 정상적으로는 노출되지 않는 미출시 상품을 조회하는 문제이다.
애플리케이션에서 특정 카테고리를 선택하면 서버에서는 다음과 같은 SQL Query가 실행된다.
SELECT * FROM products
WHERE category = 'Gifts'
AND released = 1
여기서 released = 1 조건에 의해 출시된 상품만 조회된다.
따라서 이번 실습의 목표는 SQL Injection을 통해 해당 조건을 우회하고, released = 0인 미출시 상품까지 화면에 표시하는 것이다.
2. 실습 환경 확인

Lab에 접속하면 상품 목록과 함께 다음과 같은 카테고리 필터를 확인할 수 있다.
- All
- Accessories
- Corporate gifts
- Food & Drink
- Gifts
카테고리를 선택하면 해당 카테고리에 해당하는 상품만 조회되는 구조이다.
이번 문제에서는 이 카테고리 필터에 전달되는 값이 SQL Query에 사용되는 입력값이라는 점이 핵심이다.
3. 취약한 파라미터 확인

카테고리 중 하나인 Corporate gifts를 선택하면 URL에서 다음과 같은 요청을 확인할 수 있다.
/filter?category=Corporate+gifts
여기서 확인할 수 있는 핵심 파라미터는 다음과 같다.
category
즉, category 파라미터에 전달되는 값이 서버의 SQL Query에서 다음 부분에 사용되는 것으로 볼 수 있다.
WHERE category = 'Corporate gifts'
따라서 이번 실습에서는 category 파라미터를 SQL Injection 공격 지점으로 사용하였다.
4. SQL Injection 수행

category 파라미터에 다음과 같은 값을 입력하였다.
' OR 1=1--
각 부분의 의미를 보면 다음과 같다.
기존 SQL Query에서 사용되고 있던 문자열을 작은따옴표로 종료한다.
'
1=1은 항상 참(TRUE)이므로, 기존의 카테고리 조건과 관계없이 WHERE 절의 조건을 참으로 만들 수 있다.
OR 1=1
--
SQL의 주석을 의미한다.
따라서 뒤에 존재하는 기존 조건을 주석 처리하여 실행되지 않도록 한다.
원래 SQL Query가 다음과 같았다면,
SELECT * FROM products
WHERE category = 'Gifts'
AND released = 1
입력값이 적용된 후에는 개념적으로 다음과 같은 형태가 된다.
SELECT * FROM products
WHERE category = '' OR 1=1--'
AND released = 1
-- 이후의 내용이 주석 처리되면서,
AND released = 1
조건 역시 적용되지 않게 된다.
결과적으로 WHERE 조건은 사실상 OR 1=1에 의해 항상 참이 되어, 출시 여부와 관계없이 상품이 조회된다.
5. 결과 확인

SQL Injection을 수행한 이후 기존 화면에서는 확인할 수 없었던 상품들이 추가로 나타나는 것을 확인하였다.
즉,
released = 1
조건이 무력화되면서 정상적으로는 표시되지 않아야 하는 미출시 제품까지 조회되었다.
이를 통해 Lab이 정상적으로 해결되었다.
6. 핵심 정리
이번 실습의 핵심은 사용자 입력값인 category가 SQL Query의 WHERE 절에 직접 사용되고 있다는 점이다.
정상적인 SQL Query에서는
category = 'Gifts' AND released = 1
과 같이 카테고리와 출시 여부를 모두 확인하지만,
' OR 1=1--
형태의 입력값을 이용하면
- ' : 기존 문자열 종료
- OR 1=1 : WHERE 조건을 항상 참으로 변경
- -- : 이후 SQL 조건을 주석 처리
할 수 있다.
결과적으로 released = 1이라는 제한 조건이 적용되지 않아 숨겨진 미출시 상품까지 조회할 수 있었다.