2012-07-03 3 views
41

나는 mysqli_stmt_bind_param 함수를 여러 번 사용했다. 그러나 SQL 삽입을 방지하기 위해 노력하고있는 변수를 분리하면 오류가 발생합니다.준비된 명령문에서 테이블 이름을 매개 변수화 할 수 있습니까?

여기에 몇 가지 코드 예제는 다음과 같습니다

function insertRow($db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol) 
{ 
    $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);"); 
    mysqli_stmt_bind_param($statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol); 
    $statement->execute(); 
} 

어떻게 든 다른 바인드 매개 변수 성명을 발표, 또 다른 물음표 문으로 .$new_table. 연결을 교체하거나 SQL 주입을 방지하기 위해 기존에 추가 할 수 있습니까? 귀하의 질문에

function insertRow($db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol) 
{  
    $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);"); 
    mysqli_stmt_bind_param($statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol); 
    $statement->execute(); 
} 
+2

아니요, 매개 변수가있는 쿼리는 매개 변수 값을 쿼리 문자열로 삭제하는 것이 아니라 RDBMS에 매개 변수가있는 쿼리와 매개 변수를 별도로 제공합니다. 그러나 이러한 쿼리는 테이블 이름이나 필드 이름을 매개 변수로 가질 수 없습니다. 이를 수행하는 유일한 방법은 이미 수행 한 것처럼 쿼리 문자열에 테이블 이름을 동적으로 코딩하는 것입니다. 이 문자열이 잠재적으로 공격에 노출되어 있으면 먼저 유효성을 검사해야합니다. 허용되는 테이블의 화이트리스트리스트와 대조. – MatBailie

+0

mysqli 확장의 사용은 안전합니다, 계속하십시오! 그러나 모든 문자열을 살균하고 유효성을 검사하는 것을 잊지 마십시오. 테이블 또는 필드 이름 또는 데이터베이스와 상충되는 것이 있다면! – B4NZ41

+0

위생 처리에 사용하고자하는 특정 기능이 있습니까? – GK1667

답변

57

짧은 대답은 "아니오"입니다 :이 또는 어떤이의 형태처럼

.

데이터베이스 레벨에서 준비된 명령문은 SQL 문에서 "값"비트에 대한 매개 변수 바인딩 만 허용합니다.

"이것의 의미를 변경하지 않고 명령문을 런타임에 실행할 때 대체 할 수있는"것입니다. 테이블 이름은 SQL 문 자체의 유효성 (즉, 유효한 컬럼 이름)을 판별하고 실행시이를 변경하면 SQL 문이 유효한지 여부가 잠재적으로 변경되므로 런타임 값 중 하나가 아닙니다.

PDOS와 같이 준비된 명령문을 데이터베이스에 실제로 보내지 않고 준비된 명령문 매개 변수 대체를 에뮬레이트하는 데이터베이스 인터페이스 에서조차 약간 더 높은 레벨로, 자리 표시자를 대체 할 수 있기 때문에 해당 시스템의 데이터베이스로 전송되기 전에) 테이블 자리 표시 자의 값은 문자열이며 데이터베이스에 전송 된 SQL 내에 포함되어 있으므로 SELECT * FROM ?mytable 인 경우 param이 실제로 데이터베이스에 SELECT * FROM 'mytable'을 전송하게됩니다 , 이는 유효하지 않은 SQL입니다.

가장 좋은 방법은

SELECT * FROM {$mytable} 

를 계속하지만 절대적으로$mytable 사용자 입력에서 오는 경우 처음에 확인 테이블의 화이트리스트를 가지고 있어야합니다.

+0

큰 충고가 있지만 내 경험상 이것은 더 큰 동적 웹 사이트에는 적용 할 수 없습니다. 사이트에 다중 사용자 설정, 크고 지속적으로 업데이트되는 인벤토리 등이있는 경우이 솔루션을 적용하기가 매우 어려울 것입니다. –

+10

웹 사이트의 크기는 테이블 수와 관련이 거의없고 최종 사용자가 어떤 매개 변수를 통해 쿼리를 보낼 수 있는지 알 수 있습니다. 궁극적으로 그것은 최종 사용자가 처음부터 이렇게 할 수있는 이상한 웹 사이트입니다. –

-3

결국 나는 완벽한 대답을 얻습니다. prepare 문에서 테이블 이름을 동적으로 작성하는 방법. 모든 속임수는 '{}'로 발생합니다. 이 '{}'내부 변수를 사용해야합니다. 그것은 내 코드에서 일하고있다.

$tablename = "run_time_variable";  
$stmt = $conn->prepare("INSERT INTO `{$tablename}` (name, address, phone) VALUES (?,?,?)"); 
$stmt->bind_param("sss", $name, $address, $phone); 
$stmt->execute(); 
+0

이 부분에 대한 답변은 "SQL 삽입을 방지하기 위해 기존 항목에 추가"부분입니까? –

관련 문제