본문 바로가기

SQL 인젝션(SQL Injection) 방지 "바인딩 변수"

반응형
$sql = "SELECT level FROM member WHERE id = ?";

id = ?의 의미
PHP의 Prepared Statement(준비된 쿼리) 방식에서 ?는 바인딩 변수(placeholder) 역할을 합니다.
즉, id = ?는 실행 전에는 값이 없는 상태이며, 이후 실제 데이터를 안전하게 바인딩하여 SQL을 실행하는 방식입니다.

 

왜 ?를 사용해야 할까?
SQL 인젝션(SQL Injection) 방지

사용자가 입력한 데이터를 직접 SQL에 넣으면 해킹에 취약합니다.
?(바인딩 변수)를 사용하면 MySQL이 자동으로 문자열을 이스케이프 처리하여 안전합니다.
성능 향상

SQL 실행 계획을 미리 캐싱하여 반복 실행 시 성능이 향상됩니다.
데이터 타입 자동 처리

숫자, 문자열 등 데이터 타입을 자동 변환하여 오류를 줄입니다.

Prepared Statement의 작동 과정

$sql = "SELECT level FROM g5_member WHERE id = ?";
$stmt = $conn->prepare($sql); // SQL 준비
$stmt->bind_param("s", $id); // 값 바인딩 (s: 문자열)
$stmt->execute(); // SQL 실행
$stmt->bind_result($level); // 결과값 바인딩
$stmt->fetch(); // 결과 가져오기

실행 과정

  1. ?가 포함된 SQL을 prepare()로 미리 준비.
  2. bind_param()을 사용하여 ? 자리에 실제 값을 바인딩(삽입).
  3. execute()로 쿼리 실행.
  4. bind_result()로 결과를 바인딩(저장).
  5. fetch()로 결과를 가져옴.

bind_param("s", $id); 의미

$stmt->bind_param("s", $mb_id);

첫 번째 인자 "s": 데이터 타입 지정
"s" → String (문자열)
"i" → Integer (정수)
"d" → Double (실수)
"b" → Blob (이진 데이터)
두 번째 인자 $mb_id: 바인딩할 실제 데이터
즉, "s"를 지정했기 때문에 $mb_id는 문자열로 처리됩니다.

✅ SQL 인젝션 방지 예제 비교

 (위험한 방식 - 직접 변수를 넣음)

$id = $_GET['id'];
$sql = "SELECT level FROM member WHERE id = '$id'";
$result = $conn->query($sql);

사용자가 "test' OR '1'='1" 입력 시

결과: 모든 회원의 mb_level이 노출될 위험!

 (안전한 방식 - Prepared Statement)

$id = $_GET['id'];
$sql = "SELECT level FROM member WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $id);
$stmt->execute();
$stmt->bind_result($level);
$stmt->fetch();

사용자가 "test' OR '1'='1" 입력해도 MySQL이 자동으로 문자열 처리하여 보안 유지.

🔹 요약

id = ?는 바인딩 변수로, 실제 값이 나중에 들어감.
bind_param("s", $id);을 사용해 안전하게 값을 바인딩.
SQL 인젝션을 방지하고, 성능을 높이는 효과가 있음.
이제 ?가 왜 중요한지 이해되셨을 겁니다!

반응형

댓글


Copyright ⓒ SmartWeb All rights reserved.