SQLi
사이버 범죄자가 웹 애플리케이션의 입력값을 조작하여 원래 의도와 다른 SQL 쿼리를 실행하게 만드는 보안 취약점이다. 이를 통해 인증 우회, 데이터 조회, 데이터 삭제 등 다양한 악의적 행동이 가능하다.
이 공격은 웹 기반 입력 양식에서 사용자가 생성한 SQL 문이 데이터베이스를 직접 쿼리할 수 있을 때 성공한다. 이러한 공격은 기본 코드 패턴에 취약성이 포함된 WordPress 플러그인과 같은 공유 코드베이스를 사용하면서 확산되었다. 이 취약성은 전체 애플리케이션으로 전달되고, 공유 코드를 사용하는 수십만 개의 웹사이트에 영향을 미칠 수 있다.
‼️ SQLi 예시
예를 들어, 사용자가 제품 id 값을 입력하면, 제품 이름과 설명에 액세스할 수 있다.
SELECT product_name, product_description
FROM products
WHERE product_id = [입력값];
⚔️ 공격 URL → 입력 값에 ‘999 OR 1=1’ 가 들어감
<http://www.ecommercesite.com/products/products.asp?productid=999> OR 1=1
🔨 변형된 쿼리
SELECT product_name, product_description
FROM products
WHERE product_id = 999 OR 1=1;
결과 : 1=1은 항상 참(True) 이므로, 조건이 무의미해지기 때문에 모든 제품 정보가 노출됨
또다른 예시로 아래와 같이 입력하면,
<http://www.ecommercesite.com/products/products.asp?productid=999>; DROP TABLE users;
SELECT product_name, product_description
FROM products
WHERE product_id = 999;
DROP TABLE users;
위와 같이 쿼리가 변형되어,
제품 조회 이후 users 테이블이 삭제됨 → 매우..심각한 피해 🥹
방지
1. Prepared Statements (파라미터 바인딩)
가장 강력하고 표준적인 방어 방법 !
SQL 쿼리의 구조와 데이터 입력값을 분리 → 입력값이 절대 SQL 코드로 해석되지 않도록 함.
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, inputUsername);
stmt.setString(2, inputPassword);
ResultSet rs = stmt.executeQuery();
공격자가 inputUsername = ‘ OR 1=1 을 입력해도 SQL 구문으로 작동하지 않고 문자열로 처리 됨 !
2. 입력값 유효성 검사 (Input Validation)
사용자로부터 입력받은 값이 의도한 형식과 일치하는 지 검사하여 이상한 문법, 특수문자 등을 사전에 차단함.
- 길이 제한이나 숫자만 들어와야 하는 필드에 숫자 외 문자를 제한
- 논리 연산자가 포함된 문자열 필터링
3. Web Application Firewall (WAF) 적용
SQLi를 필터링하고 잠재적 위협을 차단하기 위해 기업은 웹 애플리케이션 방화벽(WAF)을 설치할 수 있다.
WAF는 알려진 서명의 많은 목록에 대해 애플리케이션에 대한 입력을 일치시켜 악성 SQL 쿼리를 찾아내고 차단한다.
이 목록은 정기적으로 업데이트되고 패치되어 진화하는 위협 동향을 따라갈 수 있도록