기술문서
>PHP
PDO로 ORDER BY 절을 SQL INJECTION 방어 하면서 동적으로 바인딩 하려면?
자료 기본정보
주요 프로그램 스펙
- 평점: 10.0
- 라이선스: free
피드백 및 다운로드
- 사용자 평점: 10.0
- 조회: 1
제조사 및 등록 정보
- 제작사: LUZENSOFT
- 등록일: 2026-01-25 10:52:48
- 설명
#PDO 에서 WHERE나 INSERT 절의 값은 변수 바인딩(bindValue)이 가능하지만, ORDER BY의 컬럼명이나 ASC/DESC 키워드는 바인딩이 불가능합니다. SQL 문법상 식별자(Identifier)로 취급되기 때문입니다.
이를 안전하게 동적으로 처리하면서 #SQL #Injection을 방어하는 가장 확실한 방법은 **"화이트리스트(#Whitelist) 필터링"**입니다.
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]);