2013-08-05 2 views
0

초보자로서, 나는 PHP MySQL 튜토리얼을 따라 왔으며, 일반적인 MySQL PHP 함수의 사용을 조언했다. 그러나 PDO가 더 나은 대안이라고 들었 기 때문에 필자는 코드를 변환 해왔다.MySQL PDO 쿼리 구문 오류? parameters

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? WHERE id=? AND ?' at line 1 

왜 즉 :

$query = $uspdb->prepare("SELECT post_id, is_approved, reports FROM ? WHERE id=? AND ?"); 
    $query->bindValue(1, $table, PDO::PARAM_INT); 
    $query->bindValue(2, $id, PDO::PARAM_INT); 
    $query->bindValue(3, checkPermission("comment_moderation"),PDO::PARAM_BOOL); 
    $query->execute; 
    $result = $query->fetch(PDO::FETCH_ASSOC); 

첫 번째 줄은 다음과 PDO 예외가 발생합니다 : 난 그냥 다음과 같은 문제에 달렸다? 구문에 무엇이 잘못 될 수 있는지 전혀 알지 못합니다. tutorial I'm reading은 ". $ id"보다는 매개 변수를 추가하기 위해 bindValue 나 execute (array (stuff))를 사용해야한다고 알려줍니다. 좋아하는 사람은 더 안전하기 때문에 어떤 이유로 든 작동하지 않습니다.

+0

테이블 이름을'PDO :: PARAM_INT'로 바인드합니다. 틀렸을 것입니다. –

답변

1

아쉽게도 준비된 문은 데이터 리터럴 만 나타낼 수 있습니다. (에뮬레이트 된 준비의 경우). 개발자는 식별자를 스스로 처리해야합니다. PDO는 도움이 안 됨을 제공합니다.

한 2 개 엄격한 규칙을 따라야하는 동적 식별자가 안전하게하려면

  1. 제대로 식별자를 포맷하려면. 수단
    • 은 백틱의 식별자를 묶습니다.
    • 두 배로 안쪽에 백신을 탈출하십시오.
  2. 하드 코드 된 허용 목록에 대해 확인하십시오.

서식을 지정한 후에 $ table 변수를 쿼리에 삽입하는 것이 안전합니다. 그래서, 코드는 다음과 같습니다 가장 다른 경우에 대한 서식을 ORDER BY와 같은 경우에 충분한 것 같은 있지만, 그러나

$field = "`".str_replace("`","``",$field)."`"; 
$sql = "SELECT * FROM t ORDER BY $field"; 

, 사출의 다른 종류에 대한 가능성이 있습니다 :에 사용자를시키는가 테이블이나 필드를 선택하면 암호 또는 기타 개인 데이터와 같은 중요한 정보가 표시 될 수 있습니다. 동적 식별자를 허용 된 값의 목록과 대조하여 항상 확인하는 것이 좋습니다. 다음은 간단한 예입니다.

$allowed = array("name","price","qty"); 
$key = array_search($_GET['field'], $allowed)); 
if ($key === false) { 
    throw new Exception('Wrong field name'); 
} 
$field = $allowed[$key]; 
$query = "SELECT $field FROM t"; //value is safe 
+0

실제로 사용자에게 남겨지지 않은 채로 위와 같은 입력을 위생적으로 허용해야합니까?공격자는 원하는 변수를 그러한 변수에 삽입 할 수 있습니까? 아니면 사용자가 수정할 수 있도록 허용해야합니까? 내 코드에서 $ 테이블 변수합니다 ($ 타입 변수가 $ _GET되는 다음과 같이 처리됩니다 스위치 ($ 타입) { 경우 "검토" $ 테이블 = "site_cmt_reviews"; $ posttable = "site_review "; 은 휴식, 기본 : $ 테이블 ="... site_cmt_articles "= $ posttable"site_article "; } – ividyon

+0

는 중요하지 않습니다 사용자 입력이 여기 아무 상관이 SQL 쿼리를 만드는 그것의 규칙을 항상 가지고 또는 조만간 주입 될 것입니다. –

+0

스위치는 실제로 내가 말하는 바로 화이트리스트입니다. 더 긴 코드. –

0

일반적으로 질문을 제기 한 후 몇 초 만에 문제가 해결됩니다.

문제는 테이블이나 열 이름이 아닌 키 값만 바인딩 할 수 있다는 것입니다. 자세한있는 테이블 또는 열 이름이 사용자의 재량에 맡길 경우 추가 단계를 이동해야

$query = $uspdb->prepare("SELECT post_id, is_approved, reports FROM $table WHERE id=? AND ?"); 
$query->execute(array($id,checkPermission("comment_moderation"))); 
$result = $query->fetch(PDO::FETCH_ASSOC); 

그것을 소독하기 : 난 그냥 이전처럼 수동으로 테이블 및 열 이름을 삽입 유지해야합니다 위의 상식의 반응. 내 경우에는 다음과 같은 코드가 사용되었습니다.

$type = $_GET[type]; 

switch($type) { 
    case "review": 
     $table = "site_cmt_reviews"; 
     break; 
    default: 
     $table = "site_cmt_articles"; 
} 

여전히 감사합니다!

+0

그래서 주사가 있습니다. –

+0

필자의 예에서, $ table 변수는 코드에 의해 결정되며 사용자가 변경/악의적으로 이용해서는 안되며 실제로 주입 위험은 없습니다. 비록 내가 그렇다고하더라도 그것이 입력을 위생적으로하는 것이 여전히 권장되어야한다고 생각합니다. – ividyon

+0

코드에서 결정되는 사항과 앞으로 변경 될 수있는 방법을 아는 사람은 아무도 없습니다. 귀하의 질문이나이 대답은 아무 것도 언급하지 않습니다. –