216.73.216.120 TODAY : 2,541
자료실 서브 타이틀 아이콘

기술문서

 > 

PHP

PDO로 ORDER BY 절을 SQL INJECTION 방어 하면서 동적으로 바인딩 하려면?

자료 기본정보

PDO로 ORDER BY 절을 SQL INJECTION 방어 하면서 동적으로 바인딩 하려면?

주요 프로그램 스펙

  • 평점: 10.0
  • 라이선스: free

피드백 및 다운로드

  • 사용자 평점: 10.0
  • 조회: 1

제조사 및 등록 정보

  • 제작사: LUZENSOFT
  • 등록일: 2026-01-25 10:52:48
  •  

- 설명

#PDO 에서 WHEREINSERT 절의 값은 변수 바인딩(bindValue)이 가능하지만, ORDER BY의 컬럼명이나 ASC/DESC 키워드는 바인딩이 불가능합니다. SQL 문법상 식별자(Identifier)로 취급되기 때문입니다.


이를 안전하게 동적으로 처리하면서 #SQL #Injection을 방어하는 가장 확실한 방법은 **"화이트리스트(#Whitelist) 필터링"**입니다.

이를 안전하게 동적으로 처리하면서 #SQL #Injection을 방어하는 가장 확실한 방법은 **"화이트리스트(#...


1. 화이트리스트 필터링 방식 (권장)

허용된 컬럼명만 배열에 담아두고, 사용자가 입력한 값이 이 배열에 있는지 확인한 후 쿼리에 직접 삽입하는 방식입니다.

PHP

// 1. 허용할 컬럼 리스트 정의
$allowed_columns = ['no', 'hn', 'cpu', 'ram', 'traffic', 'mutime'];
$allowed_order = ['ASC', 'DESC'];

// 2. 사용자 입력값 (예: $_GET['sort'])
$sort = $_GET['sort'] ?? 'no';
$dir = strtoupper($_GET['dir'] ?? 'DESC');

// 3. 화이트리스트 검증 (없으면 기본값 설정)
$order_by = in_array($sort, $allowed_columns) ? $sort : 'no';
$order_dir = in_array($dir, $allowed_order) ? $dir : 'DESC';

// 4. 쿼리 생성 (검증된 값이므로 안전함)
$sql = "SELECT * FROM server_list ORDER BY $order_by $order_dir";
$stmt = $pdo->prepare($sql);
$stmt->execute();


2. 숫자를 이용한 매핑 (더 엄격한 방식)

입력값으로 컬럼명 자체를 받지 않고, 숫자 인덱스를 받아 서버에서 매핑하는 방식입니다.

PHP

$sort_map = [
    1 => 'no',
    2 => 'hn',
    3 => 'cpu'
];

$idx = (int)($_GET['sort_idx'] ?? 1);
$order_by = $sort_map[$idx] ?? 'no';

$sql = "SELECT * FROM server_list ORDER BY $order_by";


3. 왜 바인딩이 안 되나요?

많은 개발자들이 아래와 같은 실수를 합니다.

  • 잘못된 예 (작동 안 함): $stmt = $pdo->prepare("SELECT * FROM table ORDER BY :column"); 바인딩을 하면 PDO는 자동으로 따옴표를 붙여서 ORDER BY 'hn'과 같이 만듭니다. SQL은 이를 컬럼명이 아닌 단순 문자열로 인식하여 정렬이 작동하지 않거나 에러가 발생합니다.

  • 잘못된 예 (보안 위험): $sql = "SELECT * FROM table ORDER BY " . $_GET['sort']; 사용자가 sort=hn; DROP TABLE users; 같은 값을 보내면 데이터베이스가 파괴될 수 있습니다.


4. 실전 적용

서버 목록 대시보드에서 CPU, RAM, 업데이트 시간순으로 정렬 기능을 넣으실 때 아래와 같이 구성해 보세요.

#PHP

// fetch_server_list.php
$sort = $_GET['sort'] ?? 'mutime';
$allowed = ['no', 'hn', 'cpu', 'ram', 'mutime'];

if (!in_array($sort, $allowed)) $sort = 'mutime';

$sql = "SELECT * FROM servers WHERE date = :date ORDER BY $sort DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute(['date' => $target_date]);



이 카테고리 Navigation
전체 카테고리 Navigation