PHP에서 Sprintf 함수는 종종 형식 형식을 구성하는 데 사용되므로 SQL 쿼리 문자열을 동적으로 생성하는 데 도움이됩니다. 그러나 SQL 쿼리를 구축하기 위해 Sprintf를 직접 사용할 때는 추가주의가 필요합니다. 아래에서는 Sprintf를 사용하여 SQL 쿼리를 구성 할 때 일반적인 함정과 몇 가지 모범 사례를 구축 할 때 일반적인 함정에 뛰어들 것입니다.
SPRINTF를 사용하여 SQL 쿼리를 구축 할 때 가장 큰 문제 중 하나는 SQL 주입 취약성입니다. Sprintf는 사용자 입력을 자동으로 처리하지 않으므로 단순히 입력을 문자열에 형식화하고 삽입하므로 사용자 입력이 우연히 처리되면 SQL 주입 취약점으로 이어질 수 있습니다.
예:
$userId = $_GET['user_id'];
$sql = sprintf("SELECT * FROM users WHERE user_id = %d", $userId);
$ userId가 1 또는 1 = 1 과 같은 악의적 인 입력 인 경우 쿼리가 발생하게됩니다.
SELECT * FROM users WHERE user_id = 1 OR 1=1
이렇게하면 모든 사용자 데이터가 반환되어 심각한 보안 문제가 발생합니다.
솔루션 : SQL 주입을 피하려면 SQL을 직접 접합하는 대신 준비 문을 사용해야합니다. Sprintf 는 편리하지만 SQL 주입을 방지하지는 않습니다. PDO 또는 MySQLI가 제공 한 준비된 진술을 사용하는 가장 안전한 방법.
// 사용 PDO 전처리 진술
$stmt = $pdo->prepare("SELECT * FROM users WHERE user_id = :user_id");
$stmt->execute(['user_id' => $userId]);
Sprintf 함수는 형식 문자열을 사용하여 변수를 삽입하여 형식 오류를 유발할 수 있습니다. 예를 들어, 문자열을 삽입하면 따옴표가 올바르게 처리되지 않으면 SQL 구문 오류가 발생하거나 사출 취약점이 더 심각하게 발생할 수 있습니다.
예:
$username = "O'Reilly";
$sql = sprintf("SELECT * FROM users WHERE username = '%s'", $username);
위의 코드는 쿼리에 O'Reilly를 삽입하고 다음 SQL을 생성합니다.
SELECT * FROM users WHERE username = 'O'Reilly'
단일 따옴표가 올바르게 탈출되지 않기 때문에 SQL 오류가 발생합니다.
솔루션 : 이를 피하려면 AddSlashes () 또는 MySQLI_REAL_ESCAPE_STRING ()를 사용하여 사용자가 입력 한 특수 문자를 피할 수 있습니다. 더 나은 접근 방식은 준비 문을 사용하는 것입니다.이 명령문은 자동으로 탈출을 처리합니다.
// 사용 mysqli 탈출
$username = mysqli_real_escape_string($conn, $username);
$sql = sprintf("SELECT * FROM users WHERE username = '%s'", $username);
그러나 앞에서 언급했듯이 전처리 진술은 더 권장되는 접근법입니다.
%d를 사용하여 정수를 형식화하거나 플로팅 포인트 숫자를 포맷하기 위해 %f를 사용하는 경우 전달 된 매개 변수가 올바른지 확인해야합니다. 정수 또는 비 플로이트 포인트가 아닌 변수가 전달되는 경우 Sprintf는 예기치 않은 결과를 출력 할 수 있습니다.
예:
$price = "99.99";
$sql = sprintf("SELECT * FROM products WHERE price = %f", $price);
$ 가격 은 문자열이지만 %f는 부동 수를 기대합니다. 이로 인해 예상치 못한 결과가 발생할 수 있습니다. 특히 Sprintf가 유형 변환을 수행 할 때 잘못된 형식의 숫자가 쿼리 실패를 일으킬 수 있습니다.
솔루션 : 요구 사항을 충족하는지 확인하기 위해 변수의 유형을 미리 확인하는 것이 가장 좋습니다. 예를 들어, 부동 숫자를 변환합니다.
$price = (float)$price;
$sql = sprintf("SELECT * FROM products WHERE price = %f", $price);
문자열 및 날짜 필드는 종종 SQL 쿼리에 관여합니다. 문자열 필드에는 단일 따옴표 ( ' )가 제공되어야하며 날짜 필드는 적절한 형식으로 제공되어야합니다. Sprintf를 사용 하여이 필드를 직접 삽입하면 따옴표를 추가하거나 잘못된 날짜 형식을 사용하는 것을 잊을 수 있습니다.
예:
$date = '2023-04-22';
$sql = sprintf("SELECT * FROM events WHERE event_date = %s", $date);
위의 코드에 의해 생성 된 쿼리는 $ date가 따옴표로 둘러싸여 있지 않기 때문에 오류가 오류 될 수 있으며 생성 된 쿼리 문은 다음과 같습니다.
SELECT * FROM events WHERE event_date = 2023-04-22
이것은 SQL에 의해 잘못된 구문으로 구문 분석됩니다.
솔루션 : 날짜 및 문자열 필드를 적절하게 형식화하거나 전처리 명령문을 사용하여 자동으로 처리하십시오.
// 날짜와 견적을 형식화합니다
$sql = sprintf("SELECT * FROM events WHERE event_date = '%s'", $date);
SPRINTF를 사용하여 URL을 구축하는 경우 특수 문자로 인한 오류를 피하기 위해 매개 변수가 올바르게 인코딩되고 처리되어 있는지 확인하십시오.
예:
$userId = 123;
$url = sprintf("https://www.example.com/user?id=%d", $userId);
특히 쿼리 문자열에서 잠재적 인 문자 충돌을 피하려면 모든 동적 매개 변수를 urlencode () 함수를 사용하여 인코딩해야합니다.
$userId = urlencode($userId);
$url = sprintf("https://www.gitbox.net/user?id=%s", $userId);
SQL 주입을 피하십시오 : Sprintf를 통해 직접 SQL 쿼리를 스 플라이 싱하는 대신 전처리 문 (PDO 또는 MySQLI)을 사용하십시오.
탈출 사용자 입력 : Sprintf 를 통해 SQL 쿼리를 실제로 구축 해야하는 경우 사용자 입력을 피하십시오.
변수 유형 확인 : 서식 중에 사용되는 데이터 유형이 예상과 일치하고 서식 오류를 피하십시오.
문자열 및 날짜 필드를 적절하게 처리하십시오 . SQL 쿼리에서 따옴표 및 날짜 형식을 적절하게 사용하십시오.
URL에주의하십시오 : Sprintf가 URL을 빌드하는 데 사용되는 경우 URL이 쿼리 매개 변수를 인코딩해야합니다.
관련 태그:
SQL