2008-09-19 5 views
8

주입에 대한 방지를 위해 매개 변수화 된 쿼리를 사용하는 코드가 있지만 테이블 구조에 관계없이 쿼리를 동적으로 생성 할 수 있어야합니다. 이 작업을 수행하는 적절한 방법은 무엇입니까?매개 변수화 된 SQL 열?

예를 들어 이름, 주소, 전화 열이있는 테이블이 있다고 가정 해 보겠습니다. 열 표시을 실행하고 옵션으로 선택 드롭 다운을 채우는 웹 페이지가 있습니다.

다음으로 검색이라는 텍스트 상자가 있습니다. 이 텍스트 상자는 매개 변수로 사용됩니다.

현재 내 코드는 다음과 같은 :

 
result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search); 

나는 비록에서 구역질 느낌을 얻을. 매개 변수화 된 쿼리를 사용하는 이유는 이스케이프을 사용하지 않기 위해서입니다. 또한 이스케이프은 이스케이프 열 이름 용으로 설계되지 않았을 가능성이 큽니다.

내가 의도 한대로 작동하는지 어떻게 확인할 수 있습니까?

편집 : 나는 동적 쿼리를 요구하는 이유는 스키마는 사용자가 구성 할 수 있다는 것입니다, 나는 하드 코딩 아무것도를 해결하기 위해 주변되지 않습니다.

답변

6

열 이름을 전달하는 대신 코드가 하드 코딩 된 테이블을 사용하여 열 이름으로 변환하는 식별자를 전달하십시오. 즉, 모든 데이터가 합법적으로 번역되었거나 유효하지 않은 것으로 알려져 있기 때문에 악성 데이터가 전달되는 것에 대해 걱정할 필요가 없습니다. Psudoish 코드 :

@columns = qw/Name Address Telephone/; 
if ($columns[$param]) { 
    $query = "select * from contacts where $columns[$param] = ?"; 
} else { 
    die "Invalid column!"; 
} 

run_sql($query, $search); 
+0

하드 코딩은 나를위한 선택 사항이 아니므로, 제안 해 주셔서 감사합니다! – Martin

+0

요점은 열 이름을 하드 코드하지 않고 인터페이스에서 전달하지 않는 것입니다. 열 목록을 동적으로 가져올 수 있지만 위의 동일한 솔루션을 계속 사용하십시오. 전달 된 데이터의 일부를 열 이름으로 만들지 마십시오. SQL 삽입으로부터 보호됩니다. – zigdon

+0

+1 예, 저는 다음과 같이 말합니다. 사용자가 데이터를 입력 할 수는 있지만 사용자가 코드를 제공 할 수는 없습니다. –

0

트릭은 탈출 및 유효성 검사 루틴에 자신이 있어야합니다. 다른 유형의 리터럴에 대해 오버로드 된 자체 SQL 이스케이프 함수를 사용합니다. 아무데도 사용자 입력에서 직접 (리터럴 값을 인용하는 대신) 표현식을 삽입하지 않습니다.

여전히 수행 할 수 있습니다. 열 이름의 유효성을 검사하기 위해 별도의 — 및 엄격한 — 기능을 사용하는 것이 좋습니다. 당신은 당신이 당신의 자신의 열 이름에 대해 할 수 있습니다 가정에 의존해야합니다

 
/^\w[\w\d_]*$/ 

같은, 그것은 단지 하나의 식별자를 수용 할 수 있습니다.

0

필자는 ADO.NET을 사용하고 Escape 문제를 처리하는 명령에 SQL 명령과 SQLParameters를 사용합니다. 당신이뿐만 아니라 마이크로 소프트 툴 환경에있는 경우 그래서, 난 내 매개 변수 보호 아직 동적 SQL을 구축하고 매우 sucesfully이를 사용하는 것이 말할 수

행운의 가장

0

의 결과에 따라 열을 확인 가능한 스키마 값을 열거하는 테이블에 대한 다른 쿼리. 두 번째 쿼리에서 스키마를 정의하는 데 사용되는 열 이름에 선택 항목을 하드 코딩 할 수 있습니다. 행이 리턴되지 않으면 입력 된 컬럼이 유효하지 않습니다.

0

표준 SQL에서 구분 식별자는 큰 따옴표로 묶습니다.

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ? 

가 도시 총액 (안 이름의 경우 변환 된 버전)와 SomeTable라는 테이블을 선택할 것이며, 도시 총액 열이라고 SomeColumn에 조건을 적용한다 :이 있다는 것을 의미한다.

그 자체만으로는별로 도움이되지 않지만, 웹 양식을 통해 입력 한 이름에 큰 따옴표가있는 escape() 기술을 적용 할 수 있다면 쿼리를 합리적으로 구축 할 수 있습니다.

물론 탈출구 사용을 피하고 싶다고 말했습니까? 실제로 탈출구를 제공하는 매개 변수에는이 매개 변수를 사용할 필요가 없습니다. 장소 소유자. 그러나 사용자 제공 데이터를 쿼리에 넣는 경우 악의적 인 사람들로부터 자신을 보호해야합니다.

다른 DBMS는 구분 된 식별자를 제공하는 다양한 방법을 가지고 있습니다. 예를 들어, MS SQL Server는 큰 따옴표 대신 [대문자] 대괄호를 사용하는 것으로 보입니다.

0

일부 데이터베이스의 열 이름은 공백을 포함 할 수 있습니다. 즉, 열 이름을 인용해야하지만 데이터베이스에 이러한 열이 포함되어 있지 않은 경우 연결하기 전에 정규 표현식이나 일종의 검사를 통해 열 이름을 실행하십시오. SQL에 :

if ($column !~ /^\w+$/) { 
    die "Bad column name [$column]"; 
}