찾다

 >  Q&A  >  본문

PHP에서 SQL 주입을 방지하는 방법은 무엇입니까?

<p>사용자 입력이 수정 없이 SQL 쿼리에 삽입되면 다음 예와 같이 애플리케이션이 SQL 주입에 취약해집니다. </p> <pre class="lang-php Prettyprint-override"><code>$unsafe_variable = $_POST['user_input']; mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')"); <p>이는 사용자가 <code>value');--</code>와 같은 항목을 입력할 수 있기 때문입니다. 쿼리는 다음과 같습니다. </p> <pre class="brush:php;toolbar:false;">INSERT INTO `table`(`column`) VALUES('value'); DROP TABLE table;--') <p>이런 일이 발생하지 않도록 하려면 어떻게 해야 합니까? </p>
P粉128563140P粉128563140453일 전615

모든 응답(2)나는 대답할 것이다

  • P粉238355860
  • P粉283559033

    P粉2835590332023-09-01 11:53:19

    어떤 데이터베이스를 사용하든 관계없이 SQL 주입 공격을 피하는 올바른 방법은 SQL에서 데이터를 분리하여 데이터가 여전히 데이터이고 >SQL 파서의 명령으로 해석되지 않도록 하는 것입니다. 올바른 형식의 데이터 부분을 사용하여 SQL 문을 생성할 수 있지만 세부 사항을 완전히 이해했다면 항상 준비된 문과 매개변수화된 쿼리를 사용해야 합니다. 는 매개변수와 별도로 데이터베이스 서버로 전송되고 구문 분석되는 SQL 문입니다. 이렇게 하면 공격자가 악성 SQL을 주입하는 것이 불가능합니다.

    이를 달성하려면 기본적으로 두 가지 옵션이 있습니다.

    1. PDO 사용(지원되는 모든 데이터베이스 드라이버의 경우):

      으아악
    2. 사용 MySQLi(MySQL용):
      PHP 8.2+부터 < code>execute_query()를 사용하여 하나의 방법으로 매개변수를 준비하고, 바인딩하고, SQL 문을 실행할 수 있습니다.

      으아악

      PHP8.1까지:

      으아악

    MySQL 이외의 데이터베이스에 연결하는 경우 두 번째 드라이버별 옵션(예: PostgreSQL의 경우 pg_prepare()pg_prepare() 및 < /code>pg_execute()

    )을 참조할 수 있습니다. PDO는 보편적인 옵션입니다.

    연결을 올바르게 설정하세요

    PDO

    MySQL 데이터베이스에 액세스하기 위해 PDO를 사용할 때 실제 준비된 명령문은 기본적으로 사용되지 않습니다. 이 문제를 해결하려면 준비된 문의 시뮬레이션을 비활성화해야 합니다. PDO

    를 사용하여 연결을 만드는 예는 다음과 같습니다.

    으아악 위의 예에서 오류 모드는 꼭 필요한 것은 아니지만 추가하는 것이 좋습니다 PDOException. 이런 식으로 PDO는

    PDOException

    을 발생시켜 모든 MySQL 오류를 알려줍니다. 그러나 setAttribute() forcing 은 PDO에게 시뮬레이션된 준비된 문을 비활성화하고 실제

    준비된 문 문을 사용하도록 지시하는 첫 번째

    setAttribute()字符集 줄입니다. 이렇게 하면 명령문과 값이 MySQL 서버로 전송되기 전에 PHP에 의해 구문 분석되지 않습니다(공격자가 악의적인 SQL을 삽입할 기회가 없습니다). 생성자의 옵션에서

    charset

    을 설정할 수 있지만, "이전" PHP 버전(5.3.6 이전)은

    DSN의 charset 매개변수

    를 자동으로 무시한다는 점에 유의하는 것이 중요합니다.

    🎜Mysqli🎜 🎜mysqli의 경우 동일한 루틴을 따라야 합니다. 🎜으아악

    지침

    prepare的SQL语句由数据库服务器解析和编译。通过指定参数(? 或命名参数,如上例中的 :name),您可以告诉数据库引擎您要过滤的位置。然后,当您调用 execute를 통과하면 준비된 문이 지정한 매개변수 값과 결합됩니다.

    여기서 중요한 점은 매개변수 값이 SQL 문자열이 아닌 컴파일된 문장과 결합된다는 점입니다. SQL 주입은 데이터베이스로 보낼 SQL을 생성할 때 스크립트를 속여 악성 문자열을 포함시키는 방식으로 작동합니다. 따라서 실제 SQL을 매개변수와 별도로 전송함으로써 예상치 못한 결과가 발생할 위험을 제한할 수 있습니다.

    Prepared 문을 사용할 때 전송하는 모든 매개변수는 문자열로 처리됩니다(데이터베이스 엔진이 일부 최적화를 수행할 수 있으므로 매개변수도 당연히 숫자로 처리될 수 있음). 위의 예에서 $name 变量包含 'Sarah'; DELETE FROMEmployees 结果只是搜索字符串 "'Sarah'; DELETE FROMEmployees"이고 빈 테이블으로 끝나지 않습니다.

    Prepared 문을 사용하는 또 다른 이점은 동일한 세션에서 동일한 문을 여러 번 실행하는 경우 한 번만 구문 분석되고 컴파일되므로 속도가 빨라진다는 것입니다.

    아, 삽입 방법을 문의하셨으니 다음 예를 들어보세요(PDO 사용).

    으아악

    동적 쿼리에 준비된 문을 사용할 수 있나요?

    쿼리 매개변수가 포함된 준비된 문을 계속 사용할 수 있지만 동적 쿼리 자체의 구조는 매개변수화할 수 없으며 특정 쿼리 함수도 매개변수화할 수 없습니다.

    이러한 특정 시나리오의 경우 가장 좋은 방법은 화이트리스트 필터를 사용하여 가능한 값을 제한하는 것입니다.

    으아악

    회신하다
    0
  • 취소회신하다