복붙노트

동적 테이블 이름으로 SQL 주입을 방지하는 방법은 무엇입니까?

PHP

동적 테이블 이름으로 SQL 주입을 방지하는 방법은 무엇입니까?

나는 높은 평판을 가진 PHP 녀석과 토론을했다.

물론 이것은 멋지지만, 솔직히 mysql_real_escape_string이나 PDO를 사용하여이 코드를 수정하라는 제안이 무엇이 잘못된 것인지 알지 못합니다.

<script type="text/javascript">
    var layer;

    window.location.href = "example3.php?layer="+ layer;

    <?php
        //Make a MySQL connection
        $query = "SELECT Category, COUNT(BUSNAME)
          FROM ".$_GET['layer']." GROUP BY Category";
        $result = mysql_query($query) or die(mysql_error());

이걸로

$layer = mysql_real_escape_string($_GET['layer']);
$query = "SELECT Category, COUNT(BUSNAME)
FROM `".$layer."` GROUP BY Category";

JavaScript 코드가 클라이언트 쪽에서 보내지는 것을 고려하십시오.

해결법

  1. ==============================

    1.귀하의 조언은 실제로 부정확합니다.

    귀하의 조언은 실제로 부정확합니다.

    mysql_real_escape_string ()은 동적 테이블 이름에는 작동하지 않습니다. 따옴표로 구분 된 문자열 데이터를 이스케이프하도록 설계되었습니다. 뒷문 문자를 벗어나지 않습니다. 그것은 작지만 결정적인 차이입니다.

    그래서 SQL 삽입을 삽입 할 수 있습니다. 닫는 백틱 만 사용하면됩니다.

    PDO는 동적 테이블 이름에도 위생을 제공하지 않습니다.

    따라서 동적 테이블 이름을 사용하지 않거나 SHOW TABLES 명령의 테이블 목록과 같은 유효한 값 목록과 비교하는 것이 좋습니다.

    나는이 점을 정말로 완전히 인식하지 못했고, 아마도 나쁜 조언을 되풀이하면서 죄책감을 느꼈다.

  2. ==============================

    2.기록을 위해,이 구멍을 고치는 샘플 코드가 있습니다.

    기록을 위해,이 구멍을 고치는 샘플 코드가 있습니다.

    $allowed_tables = array('table1', 'table2');
    $clas = $_POST['clas'];
    if (in_array($clas, $allowed_tables)) {
        $query = "SELECT * FROM `$clas`";
    }
    
  3. ==============================

    3.실제로 코드를 수정하는 방법에 대한 답변을 얻으려면 다음을 수행하십시오.

    실제로 코드를 수정하는 방법에 대한 답변을 얻으려면 다음을 수행하십시오.

    '...FROM `' . str_replace('`', '``', $tableName) . '`...'
    

    이것은 테이블 이름에있는 모든 백틱을 복제합니다 (이것은 MySQL에서 이스케이프 처리가 수행되는 방법입니다).

    내가 잘 모르겠다는 것 중 하나는 이것이 "인코딩 - 안전"인지 (어떻게 정확히 부르는가?)이다. 하나는 일반적으로 addslashes 대신 mysql_real_escape_string을 권장하는데, 전자는 MySQL 연결의 인코딩을 고려하기 때문입니다. 어쩌면이 문제가 여기에도 적용될 수 있습니다.

  4. from https://stackoverflow.com/questions/5811834/how-to-prevent-sql-injection-with-dynamic-tablenames by cc-by-sa and MIT license