SQL 인젝션이란?
SQL 코드를 애플리케이션 입력 파라미터(input 태그)에 삽입하여 데이터베이스를 비정상적으로 조작하는 방식입니다.
SQL 인젝션을 통해 공격자는 민감한 데이터에 접근, 수정 및 시스템을 장악할 수 있게 됩니다.
기본 원리
웹 애플리케이션이 사용자의 입력을 적절히 검증하지 않거나 이스케이프하지 않고 직접 삽입할 때 발생합니다.
SQL문을 작성해신 분들은 쉽게 이해가 가능하실텐데 로그인 SQL문을 작성을 예시로 설명하겠습니다.
SELECT * FROM USER WHERE id = 'input_id' AND password = 'input_pw';
이때 SQL 인젝션을 해보겠습니다.
SELECT * FROM USER WHERE id = 'admin' AND password = '1234' OR '1' = '1';
위 SQL는 항상 참이 되어 어떤 비밀번호를 입력하더라도 admin으로 로그인을 할 수 있게 됩니다.
실제 코드 예제
@Slf4j
@RestController
public class UserController {
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping("/login")
public String vulnerableLogin(@RequestParam String id, @RequestParam String password) {
String sql = "SELECT name FROM users WHERE id = '" + id + "' AND password = '" + password + "'";
String name = jdbcTemplate.queryForObject(sql, String.class);
log.info("로그인 유저 : {}", name);
log.info("SQL문 : {}", sql);
return name;
}
}
@Entity
@Table(name = "users")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
private String id;
private String password;
private String name;
private String role;
}
파라미터
{{URL}}?id=admin&password=' OR '1'='1
위 코드처럼 적절히 사용자의 입력을 검증하지 않거나 이스케이프 하지 않았을 때 직접 삽입이 가능합니다.
SQL 인젝션 공격은 다양한 형태로 공격할 수 있으며 단순히 인증을 우회하는 방법으로 시작해서 DB 구조를 파악하여 민감한 정보를 추출하거나, 데이터를 수정하고 삭제하는 등 광범위하게 영향을 미칠 수 있습니다.
SQL 인젝션 막는 방법
준비된 구문(Prepared Statements)
SQL 쿼리의 구조와 데이터를 분리하여 처리함으로써 공격자가 쿼리 구조를 변경할 수 없게 만듭니다.
@GetMapping("/login-safe")
public User safeLogin(@RequestParam String id, @RequestParam String password) {
String sql = "SELECT * FROM users WHERE id = ? AND password = ?";
return jdbcTemplate.queryForObject(
sql,
new Object[]{id, password},
new BeanPropertyRowMapper<>(User.class)
);
}
저는 이 코드를 보고 처음에는 저렇게 해도 or '1' = '1'를 막을 수 없지 않을까? 라는 생각을 했었는데 직접 넣는 방식과 다른 점은 준비된 구문은 입력받은 파라미터를 무조건 문자열로 취급을 한다는 것입니다. 즉 or '1'='1'은 sql문이 아닌 그냥 문자열로 취급을 하여 SQL 인젝션이 되지 않는 것입니다.
저장 프로시저
저장 프로시저는 데이터베이스 내에서 미리 컴파일된 SQL문을 실행하므로 동적으로 생성되는 SQL문의 위험을 줄일 수 있습니다.
저장 프로시저를 잘 모르시는 분을 위해 간략하게 설명드린다면 DB의 함수라고 생각하시면 될 것 같습니다.
입력 값 검증
사용자 입력을 받을 때 예상되는 데이터 타입, 길이, 형식 등을 엄격하게 검사하여 특수문자나 SQL 키워드가 포함된 입력은 거부하거나 이스케이프 처리를 해야합니다.
'웹 보안' 카테고리의 다른 글
[웹 보안] 세션 하이잭킹 (1) | 2025.05.01 |
---|---|
[웹 보안] 파일 업로드 취약점 (1) | 2025.04.30 |
[웹 보안] CSRF (1) | 2025.04.28 |
[웹 보안] XSS (1) | 2025.04.23 |